xref: /netbsd-src/sbin/dmctl/dmctl.c (revision 100a3398b8d3c64e571cff36b46c23431b410e09)
183425a0fShaad /*
283425a0fShaad  * Copyright (c) 2010 The NetBSD Foundation, Inc.
383425a0fShaad  * All rights reserved.
483425a0fShaad  *
583425a0fShaad  * This code is derived from software contributed to The NetBSD Foundation
683425a0fShaad  * by Adam Hamsik.
783425a0fShaad  *
883425a0fShaad  * Redistribution and use in source and binary forms, with or without
983425a0fShaad  * modification, are permitted provided that the following conditions
1083425a0fShaad  * are met:
1183425a0fShaad  * 1. Redistributions of source code must retain the above copyright
1283425a0fShaad  *    notice, this list of conditions and the following disclaimer.
1383425a0fShaad  * 2. Redistributions in binary form must reproduce the above copyright
1483425a0fShaad  *    notice, this list of conditions and the following disclaimer in the
1583425a0fShaad  *    documentation and/or other materials provided with the distribution.
1683425a0fShaad  *
1783425a0fShaad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1883425a0fShaad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1983425a0fShaad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2083425a0fShaad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2183425a0fShaad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2283425a0fShaad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2383425a0fShaad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2483425a0fShaad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2583425a0fShaad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2683425a0fShaad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2783425a0fShaad  * POSSIBILITY OF SUCH DAMAGE.
2883425a0fShaad  */
2983425a0fShaad 
3083425a0fShaad #include <sys/types.h>
3183425a0fShaad #include <sys/param.h>
3283425a0fShaad 
3383425a0fShaad #include <ctype.h>
3483425a0fShaad #include <err.h>
3583425a0fShaad #include <errno.h>
3683425a0fShaad #include <stdio.h>
3783425a0fShaad #include <stdlib.h>
3883425a0fShaad #include <string.h>
3983425a0fShaad 
4083425a0fShaad #include <prop/proplib.h>
4183425a0fShaad 
4283425a0fShaad #include <dm.h>
4383425a0fShaad 
4483425a0fShaad #ifdef RUMP_ACTION
4583425a0fShaad #include <rump/rump.h>
4683425a0fShaad #include <rump/rumpclient.h>
4783425a0fShaad #include <rump/rump_syscalls.h>
4883425a0fShaad #endif
4983425a0fShaad 
5083425a0fShaad /* dmctl command is used to communicate with device-mapper driver in NetBSD
5183425a0fShaad  * it uses libdm library to create and send required data to kernel.
5283425a0fShaad  *
53*100a3398Sandvar  * Main purpose of dmctl is to add possibility to use device-mapper driver
5483425a0fShaad  * from outside of LVM scope.
5583425a0fShaad  */
5683425a0fShaad 
5783425a0fShaad #define DMCTL_CMD_REQ_NODEVNAME 0	/* Command do not require device name */
5883425a0fShaad #define DMCTL_CMD_REQ_DEVNAME	1	/* Command require device name to work */
5983425a0fShaad #define DMCTL_CMD_REQ_NEWNAME	2	/* Command require device name and
6083425a0fShaad 					   newname to work */
6183425a0fShaad struct command {
6283425a0fShaad 	const char *cmd_name;
6383425a0fShaad 	const char *cmd_help;
6483425a0fShaad 	const char *ioctl_cmd_name;
6583425a0fShaad 	int min_args;
6683425a0fShaad 	int (*cmd_func)(int, char *[], libdm_task_t);
6783425a0fShaad };
6883425a0fShaad 
699f300e34Sjoerg static const   char *dvname;            /* device name */
709f300e34Sjoerg static const   char *cmdname;           /* command user issued */
7183425a0fShaad 
7283425a0fShaad static char * parse_stdin(char *);
7383425a0fShaad 
7483425a0fShaad static int dmctl_get_version(int, char *[], libdm_task_t);
7583425a0fShaad static int dmctl_get_targets(int, char *[], libdm_task_t);
7683425a0fShaad static int dmctl_get_device_info(int, char *[], libdm_task_t);
7783425a0fShaad static int dmctl_create_dev(int, char *[], libdm_task_t);
7883425a0fShaad static int dmctl_dev_rename(int, char *[], libdm_task_t);
7983425a0fShaad static int dmctl_dev_remove(int, char *[], libdm_task_t);
8083425a0fShaad static int dmctl_dev_resume(int, char *[], libdm_task_t);
8183425a0fShaad static int dmctl_dev_suspend(int, char *[], libdm_task_t);
8283425a0fShaad static int dmctl_dev_deps(int, char *[], libdm_task_t);
8383425a0fShaad static int dmctl_list_devices(int, char *[], libdm_task_t);
8483425a0fShaad static int dmctl_table_reload(int, char *[], libdm_task_t);
8583425a0fShaad static int dmctl_table_status(int, char *[], libdm_task_t);
869f300e34Sjoerg __dead static void usage(void);
8783425a0fShaad 
889f300e34Sjoerg static struct command commands[] = {
8983425a0fShaad 	{ "version",
9083425a0fShaad 	  "Print driver and lib version.",
9183425a0fShaad 	  NULL, DMCTL_CMD_REQ_NODEVNAME,
9283425a0fShaad 	  dmctl_get_version },
9383425a0fShaad 	{ "targets",
9483425a0fShaad 	  "List available kernel targets.",
9583425a0fShaad 	  NULL, DMCTL_CMD_REQ_NODEVNAME,
9683425a0fShaad 	  dmctl_get_targets },
9783425a0fShaad 	{ "create",
9883425a0fShaad 	  "Create device with [dm device name].",
9983425a0fShaad 	  NULL, DMCTL_CMD_REQ_DEVNAME,
10083425a0fShaad 	  dmctl_create_dev },
10183425a0fShaad 	{ "ls",
10283425a0fShaad 	  "List existing dm devices.",
10383425a0fShaad 	  "names", DMCTL_CMD_REQ_NODEVNAME,
10483425a0fShaad 	  dmctl_list_devices },
10583425a0fShaad 	{ "info",
10683425a0fShaad 	  "Get info about device with [dm device name].",
10783425a0fShaad 	  NULL, DMCTL_CMD_REQ_DEVNAME,
10883425a0fShaad 	  dmctl_get_device_info },
10983425a0fShaad 	{ "rename",
11083425a0fShaad 	  "Rename device with [dm device name] to  [dm device new name].",
11183425a0fShaad 	  NULL, DMCTL_CMD_REQ_NEWNAME,
11283425a0fShaad 	  dmctl_dev_rename },
11383425a0fShaad 	{ "remove",
11483425a0fShaad 	  "Remove device with [dm device name].",
11583425a0fShaad 	  NULL, DMCTL_CMD_REQ_DEVNAME,
11683425a0fShaad 	  dmctl_dev_remove },
11783425a0fShaad 	{ "resume",
11883425a0fShaad 	  "Resume IO on dm device [dm device name].",
11983425a0fShaad 	  NULL, DMCTL_CMD_REQ_DEVNAME,
12083425a0fShaad 	  dmctl_dev_resume },
12183425a0fShaad 	{ "suspend",
12283425a0fShaad 	  "Suspend IO on dm device [dm device name].",
12383425a0fShaad 	  NULL, DMCTL_CMD_REQ_DEVNAME,
12483425a0fShaad 	  dmctl_dev_suspend },
12583425a0fShaad 	{ "deps",
126*100a3398Sandvar 	  "Print physical dependencies for dm device [dm device name].",
12783425a0fShaad 	  NULL, DMCTL_CMD_REQ_DEVNAME,
12883425a0fShaad 	  dmctl_dev_deps },
12983425a0fShaad 	{ "reload",
13083425a0fShaad 	  "Switch active and passive tables for device with [dm device name].",
13183425a0fShaad 	  NULL, DMCTL_CMD_REQ_DEVNAME,
13283425a0fShaad 	  dmctl_table_reload },
13383425a0fShaad 	{ "status",
13483425a0fShaad 	  "Print status for device with [dm device name].",
13583425a0fShaad 	  "table", DMCTL_CMD_REQ_DEVNAME,
13683425a0fShaad 	  dmctl_table_status },
13783425a0fShaad 	{ "table",
13883425a0fShaad 	  "Print active table for device with [dm device name].",
13983425a0fShaad 	  NULL, DMCTL_CMD_REQ_DEVNAME,
14083425a0fShaad 	  dmctl_table_status },
14183425a0fShaad 	{ NULL,
14283425a0fShaad 	  NULL,
14383425a0fShaad 	  NULL, 0,
14483425a0fShaad 	  NULL },
14583425a0fShaad };
14683425a0fShaad 
14783425a0fShaad int
main(int argc,char * argv[])14883425a0fShaad main(int argc, char *argv[])
14983425a0fShaad {
15083425a0fShaad 	int i;
15183425a0fShaad 	int oargc;
15283425a0fShaad 	libdm_task_t task;
15383425a0fShaad 
15483425a0fShaad 	oargc = 0;
15583425a0fShaad 
15683425a0fShaad #ifdef RUMP_ACTION
15783425a0fShaad 	if (rumpclient_init() == -1)
15883425a0fShaad 	  err(EXIT_FAILURE, "rump client init failed");
15983425a0fShaad #endif
16083425a0fShaad 
16183425a0fShaad 	/* Must have at least: device command */
16283425a0fShaad 	if (argc < 2)
16383425a0fShaad 		usage();
16483425a0fShaad 
16583425a0fShaad 	/* Skip program name, get and skip device name and command. */
16683425a0fShaad 	cmdname = argv[1];
16783425a0fShaad 	if (argc > 2) {
16883425a0fShaad 		oargc = 1;
16983425a0fShaad 		dvname = argv[2];
17083425a0fShaad 	}
17183425a0fShaad 
17283425a0fShaad 	if (argc > 3) {
17383425a0fShaad 		argv += 3;
17483425a0fShaad 		argc -= 3;
17583425a0fShaad 		oargc = 2;
17683425a0fShaad 	} else {
17783425a0fShaad 		argv = 0;
17883425a0fShaad 		argc = 0;
17983425a0fShaad 	}
18083425a0fShaad 
18183425a0fShaad 	for (i = 0; commands[i].cmd_name != NULL; i++)
18283425a0fShaad 		if (strcmp(cmdname, commands[i].cmd_name) == 0)
18383425a0fShaad 			break;
18483425a0fShaad 
18583425a0fShaad 	if (commands[i].cmd_name == NULL)
18683425a0fShaad 		errx(EXIT_FAILURE, "unknown command: %s", cmdname);
18783425a0fShaad 
18883425a0fShaad 	if (commands[i].ioctl_cmd_name != NULL)
18983425a0fShaad 		cmdname = commands[i].ioctl_cmd_name;
19083425a0fShaad 
19183425a0fShaad 	if (oargc != commands[i].min_args) {
19283425a0fShaad 		(void)fprintf(stderr, "Insufficient number of arguments for "
19383425a0fShaad 		    "command: %s specified\n", commands[i].cmd_name);
19483425a0fShaad 		usage();
19583425a0fShaad 	}
19683425a0fShaad 
19783425a0fShaad 	/*
19883425a0fShaad 	 * Create libdm task, and pass it to command handler later.
19983425a0fShaad 	 * Don't release it here because it will be replaced by different
20083425a0fShaad 	 * dictionary received from kernel after libdm_task_run.
20183425a0fShaad 	 */
20283425a0fShaad 	task = libdm_task_create(cmdname);
20383425a0fShaad 
20483425a0fShaad 	(*commands[i].cmd_func)(argc, argv, task);
20583425a0fShaad 
20683425a0fShaad 	return 0;
20783425a0fShaad }
20883425a0fShaad 
20983425a0fShaad /*
21083425a0fShaad  * Print library and kernel driver versions if command can be used only when
21183425a0fShaad  * major, minor number of library version is <= kernel.
21283425a0fShaad  */
21383425a0fShaad static int
dmctl_get_version(int argc __unused,char * argv[]__unused,libdm_task_t task)21483425a0fShaad dmctl_get_version(int argc __unused, char *argv[] __unused, libdm_task_t task)
21583425a0fShaad {
2163e4993b3Schristos 	uint32_t ver[3];
21783425a0fShaad 
2183e4993b3Schristos 	(void)libdm_task_get_cmd_version(task, ver, sizeof(ver));
21983425a0fShaad 
22083425a0fShaad 	printf("Library protocol version %d:%d:%d\n", ver[0], ver[1], ver[2]);
22183425a0fShaad 
22283425a0fShaad 	if (libdm_task_run(task) != 0)
22383425a0fShaad 		err(EXIT_FAILURE, "dmctl_get_version: libdm_task_run failed.");
22483425a0fShaad 
2253e4993b3Schristos 	(void)libdm_task_get_cmd_version(task, ver, 3);
22683425a0fShaad 	printf("Kernel protocol version %d:%d:%d\n",ver[0], ver[1], ver[2]);
22783425a0fShaad 
22883425a0fShaad 	libdm_task_destroy(task);
22983425a0fShaad 	return 0;
23083425a0fShaad }
23183425a0fShaad 
23283425a0fShaad /*
23383425a0fShaad  * Get list of available targets from kernel and print them.
23483425a0fShaad  */
23583425a0fShaad static int
dmctl_get_targets(int argc __unused,char * argv[]__unused,libdm_task_t task)23683425a0fShaad dmctl_get_targets(int argc __unused, char *argv[] __unused, libdm_task_t task)
23783425a0fShaad {
23883425a0fShaad 	libdm_cmd_t cmd;
23983425a0fShaad 	libdm_iter_t iter;
24083425a0fShaad 	libdm_target_t target;
24183425a0fShaad 	uint32_t ver[3];
24283425a0fShaad 
24383425a0fShaad 	if (libdm_task_run(task) != 0)
24483425a0fShaad 		err(EXIT_FAILURE, "dmctl_get_targets: libdm_task_run failed.");
24583425a0fShaad 
24683425a0fShaad 	if ((cmd = libdm_task_get_cmd(task)) == NULL)
24783425a0fShaad 		return ENOENT;
24883425a0fShaad 
24983425a0fShaad 	iter = libdm_cmd_iter_create(cmd);
25083425a0fShaad 
25183425a0fShaad 	while((target = libdm_cmd_get_target(iter)) != NULL){
25283425a0fShaad 		printf("Target name: %s\n", libdm_target_get_name(target));
25383425a0fShaad 
25483425a0fShaad 		libdm_target_get_version(target, ver, sizeof(ver));
25583425a0fShaad 		printf("Target version %d.%d.%d\n\n", ver[0], ver[1], ver[2]);
25683425a0fShaad 
25783425a0fShaad 		libdm_target_destroy(target);
25883425a0fShaad 	}
25983425a0fShaad 
26083425a0fShaad 	libdm_iter_destroy(iter);
26183425a0fShaad 	libdm_cmd_destroy(cmd);
26283425a0fShaad 	libdm_task_destroy(task);
26383425a0fShaad 
26483425a0fShaad 	return 0;
26583425a0fShaad }
26683425a0fShaad 
26783425a0fShaad /*
26883425a0fShaad  * Create device with name used as second parameter.
26983425a0fShaad  * TODO: Support for UUIDs here.
27083425a0fShaad  */
27183425a0fShaad static int
dmctl_create_dev(int argc __unused,char * argv[]__unused,libdm_task_t task)27283425a0fShaad dmctl_create_dev(int argc __unused, char *argv[] __unused, libdm_task_t task)
27383425a0fShaad {
27483425a0fShaad 
27583425a0fShaad 	libdm_task_set_name(dvname, task);
27683425a0fShaad 
27783425a0fShaad 	if (libdm_task_run(task) != 0)
27883425a0fShaad 		err(EXIT_FAILURE, "dmctl_create_dev: libdm_task_run failed.");
27983425a0fShaad 
28083425a0fShaad 	libdm_task_destroy(task);
28183425a0fShaad 	return 0;
28283425a0fShaad }
28383425a0fShaad 
28483425a0fShaad /*
28583425a0fShaad  * Get basic device info from device-mapper driver.
28683425a0fShaad  */
28783425a0fShaad static int
dmctl_get_device_info(int argc __unused,char * argv[]__unused,libdm_task_t task)28883425a0fShaad dmctl_get_device_info(int argc __unused, char *argv[] __unused, libdm_task_t task)
28983425a0fShaad {
29083425a0fShaad 
29183425a0fShaad 	libdm_task_set_name(dvname, task);
29283425a0fShaad 
29383425a0fShaad 	if (libdm_task_run(task) != 0)
294d3037dbaSchristos 		err(EXIT_FAILURE, "%s: libdm_task_run failed", __func__);
29583425a0fShaad 
29683425a0fShaad 	printf("Printing Device info for:\n");
29783425a0fShaad 	printf("Device name: \t\t%s\n", libdm_task_get_name(task));
29883425a0fShaad 	printf("Device uuid: \t\t%s\n", libdm_task_get_uuid(task));
29983425a0fShaad 	printf("Device minor: \t\t%d\n", libdm_task_get_minor(task));
30083425a0fShaad 	printf("Device target number: \t%d\n", libdm_task_get_target_num(task));
30183425a0fShaad 	printf("Device flags: \t\t%d\n", libdm_task_get_flags(task));
30283425a0fShaad 
30383425a0fShaad 	libdm_task_destroy(task);
30483425a0fShaad 	return 0;
30583425a0fShaad }
30683425a0fShaad 
30783425a0fShaad /*
30883425a0fShaad  * List all device in device-mapper driver.
30983425a0fShaad  */
31083425a0fShaad static int
dmctl_list_devices(int argc __unused,char * argv[]__unused,libdm_task_t task)31183425a0fShaad dmctl_list_devices(int argc __unused, char *argv[] __unused, libdm_task_t task)
31283425a0fShaad {
31383425a0fShaad 	libdm_cmd_t cmd;
31483425a0fShaad 	libdm_iter_t iter;
31583425a0fShaad 	libdm_dev_t dev;
31683425a0fShaad 
31783425a0fShaad 	if (libdm_task_run(task) != 0)
31883425a0fShaad 		err(EXIT_FAILURE, "dmctl_list_devices: libdm_task_run failed.");
31983425a0fShaad 
32083425a0fShaad 	if ((cmd = libdm_task_get_cmd(task)) == NULL)
32183425a0fShaad 		return ENOENT;
32283425a0fShaad 
32383425a0fShaad 	iter = libdm_cmd_iter_create(cmd);
32483425a0fShaad 
32583425a0fShaad 	while((dev = libdm_cmd_get_dev(iter)) != NULL){
32683425a0fShaad 		printf("Device name: %s, device minor: %d \n",
32783425a0fShaad 		    libdm_dev_get_name(dev), libdm_dev_get_minor(dev));
32883425a0fShaad 		libdm_dev_destroy(dev);
32983425a0fShaad 	}
33083425a0fShaad 
33183425a0fShaad 	libdm_iter_destroy(iter);
33283425a0fShaad 	libdm_cmd_destroy(cmd);
33383425a0fShaad 	libdm_task_destroy(task);
33483425a0fShaad 
33583425a0fShaad 	return 0;
33683425a0fShaad }
33783425a0fShaad 
33883425a0fShaad /*
33983425a0fShaad  * Rename device to new name
34083425a0fShaad  */
34183425a0fShaad static int
dmctl_dev_rename(int argc __unused,char * argv[],libdm_task_t task)34283425a0fShaad dmctl_dev_rename(int argc __unused, char *argv[], libdm_task_t task)
34383425a0fShaad {
34483425a0fShaad 	libdm_cmd_t cmd;
34583425a0fShaad 
34683425a0fShaad 	libdm_task_set_name(dvname, task);
34783425a0fShaad 
34883425a0fShaad 	cmd = libdm_cmd_create();
34983425a0fShaad 	libdm_dev_set_newname(argv[0], cmd);
35083425a0fShaad 	libdm_task_set_cmd(cmd, task);
35183425a0fShaad 
35283425a0fShaad 	if (libdm_task_run(task) != 0)
35383425a0fShaad 		err(EXIT_FAILURE, "dmctl_dev_rename: libdm_task_run failed.");
35483425a0fShaad 
35583425a0fShaad 	libdm_cmd_destroy(cmd);
35683425a0fShaad 	libdm_task_destroy(task);
35783425a0fShaad 
35883425a0fShaad 	return 0;
35983425a0fShaad }
36083425a0fShaad 
36183425a0fShaad /*
36283425a0fShaad  * Remove device from dm device list.
36383425a0fShaad  */
36483425a0fShaad static int
dmctl_dev_remove(int argc __unused,char * argv[]__unused,libdm_task_t task)36583425a0fShaad dmctl_dev_remove(int argc __unused, char *argv[] __unused, libdm_task_t task)
36683425a0fShaad {
36783425a0fShaad 
36883425a0fShaad 	if (dvname == NULL)
36983425a0fShaad 		return (ENOENT);
37083425a0fShaad 
37183425a0fShaad 	libdm_task_set_name(dvname, task);
37283425a0fShaad 
37383425a0fShaad 	if (libdm_task_run(task) != 0)
37483425a0fShaad 		err(EXIT_FAILURE, "dmctl_dev_remove: libdm_task_run failed.");
37583425a0fShaad 
37683425a0fShaad 	libdm_task_destroy(task);
37783425a0fShaad 	return 0;
37883425a0fShaad }
37983425a0fShaad 
38083425a0fShaad /*
38183425a0fShaad  * Resume device which was suspended or created right now.
382*100a3398Sandvar  * Replace table in "active slot" with table in "inactive slot".
38383425a0fShaad  */
38483425a0fShaad static int
dmctl_dev_resume(int argc __unused,char * argv[]__unused,libdm_task_t task)38583425a0fShaad dmctl_dev_resume(int argc __unused, char *argv[] __unused, libdm_task_t task)
38683425a0fShaad {
38783425a0fShaad 
38883425a0fShaad 	libdm_task_set_name(dvname, task);
38983425a0fShaad 
39083425a0fShaad 	if (libdm_task_run(task) != 0)
39183425a0fShaad 		err(EXIT_FAILURE, "dmctl_dev_resume: libdm_task_run failed.");
39283425a0fShaad 
39383425a0fShaad 	libdm_task_destroy(task);
39483425a0fShaad 	return 0;
39583425a0fShaad }
39683425a0fShaad 
39783425a0fShaad /*
39883425a0fShaad  * Resume device which was suspended or created right now.
39983425a0fShaad  * Replace table in "active slot" with table in "inactive slot".
40083425a0fShaad  */
40183425a0fShaad static int
dmctl_dev_suspend(int argc __unused,char * argv[]__unused,libdm_task_t task)40283425a0fShaad dmctl_dev_suspend(int argc __unused, char *argv[] __unused, libdm_task_t task)
40383425a0fShaad {
40483425a0fShaad 
40583425a0fShaad 	libdm_task_set_name(dvname, task);
40683425a0fShaad 	libdm_task_set_suspend_flag(task);
40783425a0fShaad 
40883425a0fShaad 	if (libdm_task_run(task) != 0)
40983425a0fShaad 		err(EXIT_FAILURE, "dmctl_dev_suspend: libdm_task_run failed.");
41083425a0fShaad 
41183425a0fShaad 	libdm_task_destroy(task);
41283425a0fShaad 	return 0;
41383425a0fShaad }
41483425a0fShaad 
41583425a0fShaad /*
416*100a3398Sandvar  * Get device dependencies from device-mapper. Device dependency is physical
41783425a0fShaad  * device on which dm device depends.
41883425a0fShaad  */
41983425a0fShaad static int
dmctl_dev_deps(int argc __unused,char * argv[]__unused,libdm_task_t task)42083425a0fShaad dmctl_dev_deps(int argc __unused, char *argv[] __unused, libdm_task_t task)
42183425a0fShaad {
42283425a0fShaad 	libdm_cmd_t cmd;
42383425a0fShaad 	libdm_iter_t iter;
42483425a0fShaad 	dev_t dev_deps;
42583425a0fShaad 
42683425a0fShaad 	libdm_task_set_name(dvname, task);
42783425a0fShaad 
42883425a0fShaad 	if (libdm_task_run(task) != 0)
42983425a0fShaad 		err(EXIT_FAILURE, "dmctl_dev_deps: libdm_task_run failed.");
43083425a0fShaad 
43183425a0fShaad 	if ((cmd = libdm_task_get_cmd(task)) == NULL)
43283425a0fShaad 		return ENOENT;
43383425a0fShaad 
43483425a0fShaad 	iter = libdm_cmd_iter_create(cmd);
43583425a0fShaad 
436*100a3398Sandvar 	printf("Device %s dependencies \n", dvname);
43783425a0fShaad 
43883425a0fShaad 	while((dev_deps = libdm_cmd_get_deps(iter)) != 0)
43983425a0fShaad 		printf("major: %d minor: %d\n", major(dev_deps), minor(dev_deps));
44083425a0fShaad 
44183425a0fShaad 	libdm_iter_destroy(iter);
44283425a0fShaad 	libdm_cmd_destroy(cmd);
44383425a0fShaad 	libdm_task_destroy(task);
44483425a0fShaad 
44583425a0fShaad 	return 0;
44683425a0fShaad }
44783425a0fShaad 
44883425a0fShaad /*
44983425a0fShaad  * Reload device table to get new one to use.
45083425a0fShaad  */
45183425a0fShaad static int
dmctl_table_reload(int argc,char * argv[],libdm_task_t task)45283425a0fShaad dmctl_table_reload(int argc, char *argv[], libdm_task_t task)
45383425a0fShaad {
45483425a0fShaad 	libdm_cmd_t cmd;
45583425a0fShaad 	libdm_table_t table;
45683425a0fShaad 
45783425a0fShaad 	char *params;
45883425a0fShaad 	char *file_path;
45983425a0fShaad 	char target[128];
46083425a0fShaad 	int len;
46183425a0fShaad 	uint64_t start, length;
46283425a0fShaad 
46383425a0fShaad 	file_path = NULL;
46483425a0fShaad 	params = NULL;
46583425a0fShaad 
46683425a0fShaad 	cmd = libdm_cmd_create();
46783425a0fShaad 
46883425a0fShaad 	libdm_task_set_name(dvname, task);
46983425a0fShaad 
47083425a0fShaad 	if (argc != 0)
47183425a0fShaad 		file_path = argv[0];
47283425a0fShaad 
47383425a0fShaad 	while ((params = parse_stdin(file_path)) != NULL) {
47483425a0fShaad 		table = libdm_table_create();
47583425a0fShaad 
4764f8abcabSpgoyette 		sscanf(params, "%"PRIu64" %"PRIu64" %s %n", &start, &length, target, &len);
47783425a0fShaad 
47883425a0fShaad 		libdm_table_set_start(start, table);
47983425a0fShaad 		libdm_table_set_length(length, table);
48083425a0fShaad 		libdm_table_set_target(target, table);
48183425a0fShaad 		libdm_table_set_params(params + len, table);
48283425a0fShaad 		libdm_cmd_set_table(table, cmd);
48383425a0fShaad 
48483425a0fShaad 		libdm_table_destroy(table);
48583425a0fShaad 
48683425a0fShaad 		free(params);
48783425a0fShaad 	}
48883425a0fShaad 
48983425a0fShaad 	libdm_task_set_cmd(cmd, task);
49083425a0fShaad 
49183425a0fShaad 	if (libdm_task_run(task) != 0)
49283425a0fShaad 		err(EXIT_FAILURE, "libdm_task_run: from dmctl_table_reload failed.");
49383425a0fShaad 
49483425a0fShaad 	libdm_cmd_destroy(cmd);
49583425a0fShaad 	libdm_task_destroy(task);
49683425a0fShaad 	free(params);
49783425a0fShaad 
49883425a0fShaad 	return 0;
49983425a0fShaad }
50083425a0fShaad 
50183425a0fShaad /*
50283425a0fShaad  * Get table status from device.
50383425a0fShaad  */
50483425a0fShaad static int
dmctl_table_status(int argc __unused,char * argv[]__unused,libdm_task_t task)50583425a0fShaad dmctl_table_status(int argc __unused, char *argv[] __unused, libdm_task_t task)
50683425a0fShaad {
50783425a0fShaad 	libdm_cmd_t cmd;
50883425a0fShaad 	libdm_table_t table;
50983425a0fShaad 	libdm_iter_t iter;
51083425a0fShaad 
51183425a0fShaad 	libdm_task_set_name(dvname, task);
51283425a0fShaad 	libdm_task_set_status_flag(task);
51383425a0fShaad 
51483425a0fShaad 	if (libdm_task_run(task) != 0)
51583425a0fShaad 		err(EXIT_FAILURE, "libdm_task_run");
51683425a0fShaad 
51783425a0fShaad 	if ((cmd = libdm_task_get_cmd(task)) == NULL)
51883425a0fShaad 		return ENOENT;
51983425a0fShaad 
52083425a0fShaad 	iter = libdm_cmd_iter_create(cmd);
52183425a0fShaad 
52283425a0fShaad 	printf("Getting device table for device %s\n", dvname);
52383425a0fShaad 
52483425a0fShaad 	while ((table = libdm_cmd_get_table(iter)) != NULL) {
52583425a0fShaad 		printf("%10"PRIu64" %10"PRIu64" %s\n",
52683425a0fShaad 			libdm_table_get_start(table),
52783425a0fShaad 			libdm_table_get_length(table),
52883425a0fShaad 			libdm_table_get_target(table));
52983425a0fShaad 		libdm_table_destroy(table);
53083425a0fShaad 	}
53183425a0fShaad 
53283425a0fShaad 	libdm_iter_destroy(iter);
53383425a0fShaad 	libdm_cmd_destroy(cmd);
53483425a0fShaad 	libdm_task_destroy(task);
53583425a0fShaad 
53683425a0fShaad 	return 0;
53783425a0fShaad }
53883425a0fShaad 
5399f300e34Sjoerg static void
usage(void)54083425a0fShaad usage(void)
54183425a0fShaad {
54283425a0fShaad 	int i;
54383425a0fShaad 
54483425a0fShaad 	(void)fprintf(stderr, "usage: %s command [dm device name]\n"
54583425a0fShaad 	    "Available commands are:\n ", getprogname());
54683425a0fShaad 	for (i = 0; commands[i].cmd_name != NULL; i++)
54783425a0fShaad 		(void)fprintf(stderr, "\t%s\t%s\n", commands[i].cmd_name, commands[i].cmd_help);
54883425a0fShaad 	exit(EXIT_FAILURE);
54983425a0fShaad }
55083425a0fShaad 
55183425a0fShaad static char *
parse_stdin(char * file_path)55283425a0fShaad parse_stdin(char *file_path)
55383425a0fShaad {
55483425a0fShaad 	char *buf, *lbuf;
55583425a0fShaad 	size_t len;
55683425a0fShaad 	FILE *fp;
55783425a0fShaad 
55883425a0fShaad 	lbuf = NULL;
55983425a0fShaad 
56083425a0fShaad 	if (file_path) {
56183425a0fShaad 		if ((fp = fopen(file_path, "r")) == NULL)
562d3037dbaSchristos 			err(ENOENT, "Cannot open table file");
56383425a0fShaad 	} else
56483425a0fShaad 		fp = stdin;
56583425a0fShaad 
56683425a0fShaad 	if ((buf = fgetln(fp, &len)) == NULL)
56783425a0fShaad 		return NULL;
56883425a0fShaad 
56983425a0fShaad 	if (buf[len - 1] != '\n')
57083425a0fShaad 		len++;
57183425a0fShaad 
57283425a0fShaad 	if ((lbuf = malloc(len)) == NULL)
57383425a0fShaad 		err(EXIT_FAILURE, "malloc");
57483425a0fShaad 
57583425a0fShaad 	memcpy(lbuf, buf, len);
57683425a0fShaad 	lbuf[len - 1] = '\0';
57783425a0fShaad 
57883425a0fShaad 	return lbuf;
57983425a0fShaad }
580