1 1.1 haad /* 2 1.1 haad * Copyright (c) 2010 The NetBSD Foundation, Inc. 3 1.1 haad * All rights reserved. 4 1.1 haad * 5 1.1 haad * This code is derived from software contributed to The NetBSD Foundation 6 1.1 haad * by Adam Hamsik. 7 1.1 haad * 8 1.1 haad * Redistribution and use in source and binary forms, with or without 9 1.1 haad * modification, are permitted provided that the following conditions 10 1.1 haad * are met: 11 1.1 haad * 1. Redistributions of source code must retain the above copyright 12 1.1 haad * notice, this list of conditions and the following disclaimer. 13 1.1 haad * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 haad * notice, this list of conditions and the following disclaimer in the 15 1.1 haad * documentation and/or other materials provided with the distribution. 16 1.1 haad * 17 1.1 haad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 1.1 haad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 1.1 haad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 1.1 haad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 1.1 haad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 1.1 haad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 1.1 haad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 1.1 haad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 1.1 haad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 1.1 haad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 1.1 haad * POSSIBILITY OF SUCH DAMAGE. 28 1.1 haad */ 29 1.1 haad 30 1.1 haad #include <sys/types.h> 31 1.1 haad #include <sys/param.h> 32 1.1 haad 33 1.1 haad #include <ctype.h> 34 1.1 haad #include <err.h> 35 1.1 haad #include <errno.h> 36 1.1 haad #include <stdio.h> 37 1.1 haad #include <stdlib.h> 38 1.1 haad #include <string.h> 39 1.1 haad 40 1.1 haad #include <prop/proplib.h> 41 1.1 haad 42 1.1 haad #include <dm.h> 43 1.1 haad 44 1.1 haad #ifdef RUMP_ACTION 45 1.1 haad #include <rump/rump.h> 46 1.1 haad #include <rump/rumpclient.h> 47 1.1 haad #include <rump/rump_syscalls.h> 48 1.1 haad #endif 49 1.1 haad 50 1.1 haad /* dmctl command is used to communicate with device-mapper driver in NetBSD 51 1.1 haad * it uses libdm library to create and send required data to kernel. 52 1.1 haad * 53 1.6 andvar * Main purpose of dmctl is to add possibility to use device-mapper driver 54 1.1 haad * from outside of LVM scope. 55 1.1 haad */ 56 1.1 haad 57 1.1 haad #define DMCTL_CMD_REQ_NODEVNAME 0 /* Command do not require device name */ 58 1.1 haad #define DMCTL_CMD_REQ_DEVNAME 1 /* Command require device name to work */ 59 1.1 haad #define DMCTL_CMD_REQ_NEWNAME 2 /* Command require device name and 60 1.1 haad newname to work */ 61 1.1 haad struct command { 62 1.1 haad const char *cmd_name; 63 1.1 haad const char *cmd_help; 64 1.1 haad const char *ioctl_cmd_name; 65 1.1 haad int min_args; 66 1.1 haad int (*cmd_func)(int, char *[], libdm_task_t); 67 1.1 haad }; 68 1.1 haad 69 1.3 joerg static const char *dvname; /* device name */ 70 1.3 joerg static const char *cmdname; /* command user issued */ 71 1.1 haad 72 1.1 haad static char * parse_stdin(char *); 73 1.1 haad 74 1.1 haad static int dmctl_get_version(int, char *[], libdm_task_t); 75 1.1 haad static int dmctl_get_targets(int, char *[], libdm_task_t); 76 1.1 haad static int dmctl_get_device_info(int, char *[], libdm_task_t); 77 1.1 haad static int dmctl_create_dev(int, char *[], libdm_task_t); 78 1.1 haad static int dmctl_dev_rename(int, char *[], libdm_task_t); 79 1.1 haad static int dmctl_dev_remove(int, char *[], libdm_task_t); 80 1.1 haad static int dmctl_dev_resume(int, char *[], libdm_task_t); 81 1.1 haad static int dmctl_dev_suspend(int, char *[], libdm_task_t); 82 1.1 haad static int dmctl_dev_deps(int, char *[], libdm_task_t); 83 1.1 haad static int dmctl_list_devices(int, char *[], libdm_task_t); 84 1.1 haad static int dmctl_table_reload(int, char *[], libdm_task_t); 85 1.1 haad static int dmctl_table_status(int, char *[], libdm_task_t); 86 1.3 joerg __dead static void usage(void); 87 1.1 haad 88 1.3 joerg static struct command commands[] = { 89 1.1 haad { "version", 90 1.1 haad "Print driver and lib version.", 91 1.1 haad NULL, DMCTL_CMD_REQ_NODEVNAME, 92 1.1 haad dmctl_get_version }, 93 1.1 haad { "targets", 94 1.1 haad "List available kernel targets.", 95 1.1 haad NULL, DMCTL_CMD_REQ_NODEVNAME, 96 1.1 haad dmctl_get_targets }, 97 1.1 haad { "create", 98 1.1 haad "Create device with [dm device name].", 99 1.1 haad NULL, DMCTL_CMD_REQ_DEVNAME, 100 1.1 haad dmctl_create_dev }, 101 1.1 haad { "ls", 102 1.1 haad "List existing dm devices.", 103 1.1 haad "names", DMCTL_CMD_REQ_NODEVNAME, 104 1.1 haad dmctl_list_devices }, 105 1.1 haad { "info", 106 1.1 haad "Get info about device with [dm device name].", 107 1.1 haad NULL, DMCTL_CMD_REQ_DEVNAME, 108 1.1 haad dmctl_get_device_info }, 109 1.1 haad { "rename", 110 1.1 haad "Rename device with [dm device name] to [dm device new name].", 111 1.1 haad NULL, DMCTL_CMD_REQ_NEWNAME, 112 1.1 haad dmctl_dev_rename }, 113 1.1 haad { "remove", 114 1.1 haad "Remove device with [dm device name].", 115 1.1 haad NULL, DMCTL_CMD_REQ_DEVNAME, 116 1.1 haad dmctl_dev_remove }, 117 1.1 haad { "resume", 118 1.1 haad "Resume IO on dm device [dm device name].", 119 1.1 haad NULL, DMCTL_CMD_REQ_DEVNAME, 120 1.1 haad dmctl_dev_resume }, 121 1.1 haad { "suspend", 122 1.1 haad "Suspend IO on dm device [dm device name].", 123 1.1 haad NULL, DMCTL_CMD_REQ_DEVNAME, 124 1.1 haad dmctl_dev_suspend }, 125 1.1 haad { "deps", 126 1.6 andvar "Print physical dependencies for dm device [dm device name].", 127 1.1 haad NULL, DMCTL_CMD_REQ_DEVNAME, 128 1.1 haad dmctl_dev_deps }, 129 1.1 haad { "reload", 130 1.1 haad "Switch active and passive tables for device with [dm device name].", 131 1.1 haad NULL, DMCTL_CMD_REQ_DEVNAME, 132 1.1 haad dmctl_table_reload }, 133 1.1 haad { "status", 134 1.1 haad "Print status for device with [dm device name].", 135 1.1 haad "table", DMCTL_CMD_REQ_DEVNAME, 136 1.1 haad dmctl_table_status }, 137 1.1 haad { "table", 138 1.1 haad "Print active table for device with [dm device name].", 139 1.1 haad NULL, DMCTL_CMD_REQ_DEVNAME, 140 1.1 haad dmctl_table_status }, 141 1.1 haad { NULL, 142 1.1 haad NULL, 143 1.1 haad NULL, 0, 144 1.1 haad NULL }, 145 1.1 haad }; 146 1.1 haad 147 1.1 haad int 148 1.1 haad main(int argc, char *argv[]) 149 1.1 haad { 150 1.1 haad int i; 151 1.1 haad int oargc; 152 1.1 haad libdm_task_t task; 153 1.1 haad 154 1.1 haad oargc = 0; 155 1.1 haad 156 1.1 haad #ifdef RUMP_ACTION 157 1.1 haad if (rumpclient_init() == -1) 158 1.1 haad err(EXIT_FAILURE, "rump client init failed"); 159 1.1 haad #endif 160 1.1 haad 161 1.1 haad /* Must have at least: device command */ 162 1.1 haad if (argc < 2) 163 1.1 haad usage(); 164 1.1 haad 165 1.1 haad /* Skip program name, get and skip device name and command. */ 166 1.1 haad cmdname = argv[1]; 167 1.1 haad if (argc > 2) { 168 1.1 haad oargc = 1; 169 1.1 haad dvname = argv[2]; 170 1.1 haad } 171 1.1 haad 172 1.1 haad if (argc > 3) { 173 1.1 haad argv += 3; 174 1.1 haad argc -= 3; 175 1.1 haad oargc = 2; 176 1.1 haad } else { 177 1.1 haad argv = 0; 178 1.1 haad argc = 0; 179 1.1 haad } 180 1.1 haad 181 1.1 haad for (i = 0; commands[i].cmd_name != NULL; i++) 182 1.1 haad if (strcmp(cmdname, commands[i].cmd_name) == 0) 183 1.1 haad break; 184 1.1 haad 185 1.1 haad if (commands[i].cmd_name == NULL) 186 1.1 haad errx(EXIT_FAILURE, "unknown command: %s", cmdname); 187 1.1 haad 188 1.1 haad if (commands[i].ioctl_cmd_name != NULL) 189 1.1 haad cmdname = commands[i].ioctl_cmd_name; 190 1.1 haad 191 1.1 haad if (oargc != commands[i].min_args) { 192 1.1 haad (void)fprintf(stderr, "Insufficient number of arguments for " 193 1.1 haad "command: %s specified\n", commands[i].cmd_name); 194 1.1 haad usage(); 195 1.1 haad } 196 1.1 haad 197 1.1 haad /* 198 1.1 haad * Create libdm task, and pass it to command handler later. 199 1.1 haad * Don't release it here because it will be replaced by different 200 1.1 haad * dictionary received from kernel after libdm_task_run. 201 1.1 haad */ 202 1.1 haad task = libdm_task_create(cmdname); 203 1.1 haad 204 1.1 haad (*commands[i].cmd_func)(argc, argv, task); 205 1.1 haad 206 1.1 haad return 0; 207 1.1 haad } 208 1.1 haad 209 1.1 haad /* 210 1.1 haad * Print library and kernel driver versions if command can be used only when 211 1.1 haad * major, minor number of library version is <= kernel. 212 1.1 haad */ 213 1.1 haad static int 214 1.1 haad dmctl_get_version(int argc __unused, char *argv[] __unused, libdm_task_t task) 215 1.1 haad { 216 1.4 christos uint32_t ver[3]; 217 1.1 haad 218 1.4 christos (void)libdm_task_get_cmd_version(task, ver, sizeof(ver)); 219 1.1 haad 220 1.1 haad printf("Library protocol version %d:%d:%d\n", ver[0], ver[1], ver[2]); 221 1.1 haad 222 1.1 haad if (libdm_task_run(task) != 0) 223 1.1 haad err(EXIT_FAILURE, "dmctl_get_version: libdm_task_run failed."); 224 1.1 haad 225 1.4 christos (void)libdm_task_get_cmd_version(task, ver, 3); 226 1.1 haad printf("Kernel protocol version %d:%d:%d\n",ver[0], ver[1], ver[2]); 227 1.1 haad 228 1.1 haad libdm_task_destroy(task); 229 1.1 haad return 0; 230 1.1 haad } 231 1.1 haad 232 1.1 haad /* 233 1.1 haad * Get list of available targets from kernel and print them. 234 1.1 haad */ 235 1.1 haad static int 236 1.1 haad dmctl_get_targets(int argc __unused, char *argv[] __unused, libdm_task_t task) 237 1.1 haad { 238 1.1 haad libdm_cmd_t cmd; 239 1.1 haad libdm_iter_t iter; 240 1.1 haad libdm_target_t target; 241 1.1 haad uint32_t ver[3]; 242 1.1 haad 243 1.1 haad if (libdm_task_run(task) != 0) 244 1.1 haad err(EXIT_FAILURE, "dmctl_get_targets: libdm_task_run failed."); 245 1.1 haad 246 1.1 haad if ((cmd = libdm_task_get_cmd(task)) == NULL) 247 1.1 haad return ENOENT; 248 1.1 haad 249 1.1 haad iter = libdm_cmd_iter_create(cmd); 250 1.1 haad 251 1.1 haad while((target = libdm_cmd_get_target(iter)) != NULL){ 252 1.1 haad printf("Target name: %s\n", libdm_target_get_name(target)); 253 1.1 haad 254 1.1 haad libdm_target_get_version(target, ver, sizeof(ver)); 255 1.1 haad printf("Target version %d.%d.%d\n\n", ver[0], ver[1], ver[2]); 256 1.1 haad 257 1.1 haad libdm_target_destroy(target); 258 1.1 haad } 259 1.1 haad 260 1.1 haad libdm_iter_destroy(iter); 261 1.1 haad libdm_cmd_destroy(cmd); 262 1.1 haad libdm_task_destroy(task); 263 1.1 haad 264 1.1 haad return 0; 265 1.1 haad } 266 1.1 haad 267 1.1 haad /* 268 1.1 haad * Create device with name used as second parameter. 269 1.1 haad * TODO: Support for UUIDs here. 270 1.1 haad */ 271 1.1 haad static int 272 1.1 haad dmctl_create_dev(int argc __unused, char *argv[] __unused, libdm_task_t task) 273 1.1 haad { 274 1.1 haad 275 1.1 haad libdm_task_set_name(dvname, task); 276 1.1 haad 277 1.1 haad if (libdm_task_run(task) != 0) 278 1.1 haad err(EXIT_FAILURE, "dmctl_create_dev: libdm_task_run failed."); 279 1.1 haad 280 1.1 haad libdm_task_destroy(task); 281 1.1 haad return 0; 282 1.1 haad } 283 1.1 haad 284 1.1 haad /* 285 1.1 haad * Get basic device info from device-mapper driver. 286 1.1 haad */ 287 1.1 haad static int 288 1.1 haad dmctl_get_device_info(int argc __unused, char *argv[] __unused, libdm_task_t task) 289 1.1 haad { 290 1.1 haad 291 1.1 haad libdm_task_set_name(dvname, task); 292 1.1 haad 293 1.1 haad if (libdm_task_run(task) != 0) 294 1.5 christos err(EXIT_FAILURE, "%s: libdm_task_run failed", __func__); 295 1.1 haad 296 1.1 haad printf("Printing Device info for:\n"); 297 1.1 haad printf("Device name: \t\t%s\n", libdm_task_get_name(task)); 298 1.1 haad printf("Device uuid: \t\t%s\n", libdm_task_get_uuid(task)); 299 1.1 haad printf("Device minor: \t\t%d\n", libdm_task_get_minor(task)); 300 1.1 haad printf("Device target number: \t%d\n", libdm_task_get_target_num(task)); 301 1.1 haad printf("Device flags: \t\t%d\n", libdm_task_get_flags(task)); 302 1.1 haad 303 1.1 haad libdm_task_destroy(task); 304 1.1 haad return 0; 305 1.1 haad } 306 1.1 haad 307 1.1 haad /* 308 1.1 haad * List all device in device-mapper driver. 309 1.1 haad */ 310 1.1 haad static int 311 1.1 haad dmctl_list_devices(int argc __unused, char *argv[] __unused, libdm_task_t task) 312 1.1 haad { 313 1.1 haad libdm_cmd_t cmd; 314 1.1 haad libdm_iter_t iter; 315 1.1 haad libdm_dev_t dev; 316 1.1 haad 317 1.1 haad if (libdm_task_run(task) != 0) 318 1.1 haad err(EXIT_FAILURE, "dmctl_list_devices: libdm_task_run failed."); 319 1.1 haad 320 1.1 haad if ((cmd = libdm_task_get_cmd(task)) == NULL) 321 1.1 haad return ENOENT; 322 1.1 haad 323 1.1 haad iter = libdm_cmd_iter_create(cmd); 324 1.1 haad 325 1.1 haad while((dev = libdm_cmd_get_dev(iter)) != NULL){ 326 1.1 haad printf("Device name: %s, device minor: %d \n", 327 1.1 haad libdm_dev_get_name(dev), libdm_dev_get_minor(dev)); 328 1.1 haad libdm_dev_destroy(dev); 329 1.1 haad } 330 1.1 haad 331 1.1 haad libdm_iter_destroy(iter); 332 1.1 haad libdm_cmd_destroy(cmd); 333 1.1 haad libdm_task_destroy(task); 334 1.1 haad 335 1.1 haad return 0; 336 1.1 haad } 337 1.1 haad 338 1.1 haad /* 339 1.1 haad * Rename device to new name 340 1.1 haad */ 341 1.1 haad static int 342 1.1 haad dmctl_dev_rename(int argc __unused, char *argv[], libdm_task_t task) 343 1.1 haad { 344 1.1 haad libdm_cmd_t cmd; 345 1.1 haad 346 1.1 haad libdm_task_set_name(dvname, task); 347 1.1 haad 348 1.1 haad cmd = libdm_cmd_create(); 349 1.1 haad libdm_dev_set_newname(argv[0], cmd); 350 1.1 haad libdm_task_set_cmd(cmd, task); 351 1.1 haad 352 1.1 haad if (libdm_task_run(task) != 0) 353 1.1 haad err(EXIT_FAILURE, "dmctl_dev_rename: libdm_task_run failed."); 354 1.1 haad 355 1.1 haad libdm_cmd_destroy(cmd); 356 1.1 haad libdm_task_destroy(task); 357 1.1 haad 358 1.1 haad return 0; 359 1.1 haad } 360 1.1 haad 361 1.1 haad /* 362 1.1 haad * Remove device from dm device list. 363 1.1 haad */ 364 1.1 haad static int 365 1.1 haad dmctl_dev_remove(int argc __unused, char *argv[] __unused, libdm_task_t task) 366 1.1 haad { 367 1.1 haad 368 1.1 haad if (dvname == NULL) 369 1.1 haad return (ENOENT); 370 1.1 haad 371 1.1 haad libdm_task_set_name(dvname, task); 372 1.1 haad 373 1.1 haad if (libdm_task_run(task) != 0) 374 1.1 haad err(EXIT_FAILURE, "dmctl_dev_remove: libdm_task_run failed."); 375 1.1 haad 376 1.1 haad libdm_task_destroy(task); 377 1.1 haad return 0; 378 1.1 haad } 379 1.1 haad 380 1.1 haad /* 381 1.1 haad * Resume device which was suspended or created right now. 382 1.6 andvar * Replace table in "active slot" with table in "inactive slot". 383 1.1 haad */ 384 1.1 haad static int 385 1.1 haad dmctl_dev_resume(int argc __unused, char *argv[] __unused, libdm_task_t task) 386 1.1 haad { 387 1.1 haad 388 1.1 haad libdm_task_set_name(dvname, task); 389 1.1 haad 390 1.1 haad if (libdm_task_run(task) != 0) 391 1.1 haad err(EXIT_FAILURE, "dmctl_dev_resume: libdm_task_run failed."); 392 1.1 haad 393 1.1 haad libdm_task_destroy(task); 394 1.1 haad return 0; 395 1.1 haad } 396 1.1 haad 397 1.1 haad /* 398 1.1 haad * Resume device which was suspended or created right now. 399 1.1 haad * Replace table in "active slot" with table in "inactive slot". 400 1.1 haad */ 401 1.1 haad static int 402 1.1 haad dmctl_dev_suspend(int argc __unused, char *argv[] __unused, libdm_task_t task) 403 1.1 haad { 404 1.1 haad 405 1.1 haad libdm_task_set_name(dvname, task); 406 1.1 haad libdm_task_set_suspend_flag(task); 407 1.1 haad 408 1.1 haad if (libdm_task_run(task) != 0) 409 1.1 haad err(EXIT_FAILURE, "dmctl_dev_suspend: libdm_task_run failed."); 410 1.1 haad 411 1.1 haad libdm_task_destroy(task); 412 1.1 haad return 0; 413 1.1 haad } 414 1.1 haad 415 1.1 haad /* 416 1.6 andvar * Get device dependencies from device-mapper. Device dependency is physical 417 1.1 haad * device on which dm device depends. 418 1.1 haad */ 419 1.1 haad static int 420 1.1 haad dmctl_dev_deps(int argc __unused, char *argv[] __unused, libdm_task_t task) 421 1.1 haad { 422 1.1 haad libdm_cmd_t cmd; 423 1.1 haad libdm_iter_t iter; 424 1.1 haad dev_t dev_deps; 425 1.1 haad 426 1.1 haad libdm_task_set_name(dvname, task); 427 1.1 haad 428 1.1 haad if (libdm_task_run(task) != 0) 429 1.1 haad err(EXIT_FAILURE, "dmctl_dev_deps: libdm_task_run failed."); 430 1.1 haad 431 1.1 haad if ((cmd = libdm_task_get_cmd(task)) == NULL) 432 1.1 haad return ENOENT; 433 1.1 haad 434 1.1 haad iter = libdm_cmd_iter_create(cmd); 435 1.1 haad 436 1.6 andvar printf("Device %s dependencies \n", dvname); 437 1.1 haad 438 1.1 haad while((dev_deps = libdm_cmd_get_deps(iter)) != 0) 439 1.1 haad printf("major: %d minor: %d\n", major(dev_deps), minor(dev_deps)); 440 1.1 haad 441 1.1 haad libdm_iter_destroy(iter); 442 1.1 haad libdm_cmd_destroy(cmd); 443 1.1 haad libdm_task_destroy(task); 444 1.1 haad 445 1.1 haad return 0; 446 1.1 haad } 447 1.1 haad 448 1.1 haad /* 449 1.1 haad * Reload device table to get new one to use. 450 1.1 haad */ 451 1.1 haad static int 452 1.1 haad dmctl_table_reload(int argc, char *argv[], libdm_task_t task) 453 1.1 haad { 454 1.1 haad libdm_cmd_t cmd; 455 1.1 haad libdm_table_t table; 456 1.1 haad 457 1.1 haad char *params; 458 1.1 haad char *file_path; 459 1.1 haad char target[128]; 460 1.1 haad int len; 461 1.1 haad uint64_t start, length; 462 1.1 haad 463 1.1 haad file_path = NULL; 464 1.1 haad params = NULL; 465 1.1 haad 466 1.1 haad cmd = libdm_cmd_create(); 467 1.1 haad 468 1.1 haad libdm_task_set_name(dvname, task); 469 1.1 haad 470 1.1 haad if (argc != 0) 471 1.1 haad file_path = argv[0]; 472 1.1 haad 473 1.1 haad while ((params = parse_stdin(file_path)) != NULL) { 474 1.1 haad table = libdm_table_create(); 475 1.1 haad 476 1.2 pgoyette sscanf(params, "%"PRIu64" %"PRIu64" %s %n", &start, &length, target, &len); 477 1.1 haad 478 1.1 haad libdm_table_set_start(start, table); 479 1.1 haad libdm_table_set_length(length, table); 480 1.1 haad libdm_table_set_target(target, table); 481 1.1 haad libdm_table_set_params(params + len, table); 482 1.1 haad libdm_cmd_set_table(table, cmd); 483 1.1 haad 484 1.1 haad libdm_table_destroy(table); 485 1.1 haad 486 1.1 haad free(params); 487 1.1 haad } 488 1.1 haad 489 1.1 haad libdm_task_set_cmd(cmd, task); 490 1.1 haad 491 1.1 haad if (libdm_task_run(task) != 0) 492 1.1 haad err(EXIT_FAILURE, "libdm_task_run: from dmctl_table_reload failed."); 493 1.1 haad 494 1.1 haad libdm_cmd_destroy(cmd); 495 1.1 haad libdm_task_destroy(task); 496 1.1 haad free(params); 497 1.1 haad 498 1.1 haad return 0; 499 1.1 haad } 500 1.1 haad 501 1.1 haad /* 502 1.1 haad * Get table status from device. 503 1.1 haad */ 504 1.1 haad static int 505 1.1 haad dmctl_table_status(int argc __unused, char *argv[] __unused, libdm_task_t task) 506 1.1 haad { 507 1.1 haad libdm_cmd_t cmd; 508 1.1 haad libdm_table_t table; 509 1.1 haad libdm_iter_t iter; 510 1.1 haad 511 1.1 haad libdm_task_set_name(dvname, task); 512 1.1 haad libdm_task_set_status_flag(task); 513 1.1 haad 514 1.1 haad if (libdm_task_run(task) != 0) 515 1.1 haad err(EXIT_FAILURE, "libdm_task_run"); 516 1.1 haad 517 1.1 haad if ((cmd = libdm_task_get_cmd(task)) == NULL) 518 1.1 haad return ENOENT; 519 1.1 haad 520 1.1 haad iter = libdm_cmd_iter_create(cmd); 521 1.1 haad 522 1.1 haad printf("Getting device table for device %s\n", dvname); 523 1.1 haad 524 1.1 haad while ((table = libdm_cmd_get_table(iter)) != NULL) { 525 1.1 haad printf("%10"PRIu64" %10"PRIu64" %s\n", 526 1.1 haad libdm_table_get_start(table), 527 1.1 haad libdm_table_get_length(table), 528 1.1 haad libdm_table_get_target(table)); 529 1.1 haad libdm_table_destroy(table); 530 1.1 haad } 531 1.1 haad 532 1.1 haad libdm_iter_destroy(iter); 533 1.1 haad libdm_cmd_destroy(cmd); 534 1.1 haad libdm_task_destroy(task); 535 1.1 haad 536 1.1 haad return 0; 537 1.1 haad } 538 1.1 haad 539 1.3 joerg static void 540 1.1 haad usage(void) 541 1.1 haad { 542 1.1 haad int i; 543 1.1 haad 544 1.1 haad (void)fprintf(stderr, "usage: %s command [dm device name]\n" 545 1.1 haad "Available commands are:\n ", getprogname()); 546 1.1 haad for (i = 0; commands[i].cmd_name != NULL; i++) 547 1.1 haad (void)fprintf(stderr, "\t%s\t%s\n", commands[i].cmd_name, commands[i].cmd_help); 548 1.1 haad exit(EXIT_FAILURE); 549 1.1 haad } 550 1.1 haad 551 1.1 haad static char * 552 1.1 haad parse_stdin(char *file_path) 553 1.1 haad { 554 1.1 haad char *buf, *lbuf; 555 1.1 haad size_t len; 556 1.1 haad FILE *fp; 557 1.1 haad 558 1.1 haad lbuf = NULL; 559 1.1 haad 560 1.1 haad if (file_path) { 561 1.1 haad if ((fp = fopen(file_path, "r")) == NULL) 562 1.5 christos err(ENOENT, "Cannot open table file"); 563 1.1 haad } else 564 1.1 haad fp = stdin; 565 1.1 haad 566 1.1 haad if ((buf = fgetln(fp, &len)) == NULL) 567 1.1 haad return NULL; 568 1.1 haad 569 1.1 haad if (buf[len - 1] != '\n') 570 1.1 haad len++; 571 1.1 haad 572 1.1 haad if ((lbuf = malloc(len)) == NULL) 573 1.1 haad err(EXIT_FAILURE, "malloc"); 574 1.1 haad 575 1.1 haad memcpy(lbuf, buf, len); 576 1.1 haad lbuf[len - 1] = '\0'; 577 1.1 haad 578 1.1 haad return lbuf; 579 1.1 haad } 580