xref: /dragonfly/lib/libdm/dm_task.c (revision 98b7ab40)
10cdd1155SAlex Hornung /*
20cdd1155SAlex Hornung  * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
30cdd1155SAlex Hornung  * All rights reserved.
40cdd1155SAlex Hornung  *
50cdd1155SAlex Hornung  * This code is derived from software contributed to The NetBSD Foundation
60cdd1155SAlex Hornung  * by Adam Hamsik.
70cdd1155SAlex Hornung  *
80cdd1155SAlex Hornung  * Redistribution and use in source and binary forms, with or without
90cdd1155SAlex Hornung  * modification, are permitted provided that the following conditions
100cdd1155SAlex Hornung  * are met:
110cdd1155SAlex Hornung  *
120cdd1155SAlex Hornung  * 1. Redistributions of source code must retain the above copyright
130cdd1155SAlex Hornung  *    notice, this list of conditions and the following disclaimer.
140cdd1155SAlex Hornung  * 2. Redistributions in binary form must reproduce the above copyright
150cdd1155SAlex Hornung  *    notice, this list of conditions and the following disclaimer in
160cdd1155SAlex Hornung  *    the documentation and/or other materials provided with the
170cdd1155SAlex Hornung  *    distribution.
180cdd1155SAlex Hornung  *
190cdd1155SAlex Hornung  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
200cdd1155SAlex Hornung  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
210cdd1155SAlex Hornung  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
220cdd1155SAlex Hornung  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
230cdd1155SAlex Hornung  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
240cdd1155SAlex Hornung  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
250cdd1155SAlex Hornung  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
260cdd1155SAlex Hornung  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
270cdd1155SAlex Hornung  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
280cdd1155SAlex Hornung  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
290cdd1155SAlex Hornung  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
300cdd1155SAlex Hornung  * SUCH DAMAGE.
310cdd1155SAlex Hornung  */
320cdd1155SAlex Hornung #include <sys/types.h>
330cdd1155SAlex Hornung #include <sys/param.h>
340cdd1155SAlex Hornung #include <sys/ioctl.h>
350cdd1155SAlex Hornung #include <sys/stat.h>
360cdd1155SAlex Hornung #include <dev/disk/dm/netbsd-dm.h>
370cdd1155SAlex Hornung #include <stdlib.h>
380cdd1155SAlex Hornung #include <string.h>
390cdd1155SAlex Hornung #include <stdio.h>
400cdd1155SAlex Hornung #include <unistd.h>
410cdd1155SAlex Hornung #include <fcntl.h>
420cdd1155SAlex Hornung #include <errno.h>
430cdd1155SAlex Hornung 
440cdd1155SAlex Hornung #include <libprop/proplib.h>
450cdd1155SAlex Hornung #include "libdm.h"
460cdd1155SAlex Hornung 
470cdd1155SAlex Hornung struct dm_task {
480cdd1155SAlex Hornung 	int			task_type;
490cdd1155SAlex Hornung 	int			was_enoent;
500cdd1155SAlex Hornung 	prop_dictionary_t	dict;
510cdd1155SAlex Hornung 	void			*data_buffer;
520cdd1155SAlex Hornung };
530cdd1155SAlex Hornung 
540cdd1155SAlex Hornung struct dm_cmd {
550cdd1155SAlex Hornung 	int		task_type;
560cdd1155SAlex Hornung 	const char	*dm_cmd;
570cdd1155SAlex Hornung 	uint32_t	cmd_version[3];
580cdd1155SAlex Hornung };
590cdd1155SAlex Hornung 
600cdd1155SAlex Hornung struct dm_cmd dm_cmds[] = {
610cdd1155SAlex Hornung 	{ DM_DEVICE_REMOVE,		"remove",	{4, 0, 0} },
620cdd1155SAlex Hornung 	{ DM_DEVICE_REMOVE_ALL,		"remove_all",	{4, 0, 0} },
630cdd1155SAlex Hornung 	{ DM_DEVICE_CREATE,		"create",	{4, 0, 0} },
640cdd1155SAlex Hornung 	{ DM_DEVICE_RELOAD,		"reload",	{4, 0, 0} },
650cdd1155SAlex Hornung 	{ DM_DEVICE_RESUME,		"resume",	{4, 0, 0} },
660cdd1155SAlex Hornung 	{ DM_DEVICE_SUSPEND,		"suspend",	{4, 0, 0} },
670cdd1155SAlex Hornung 	{ DM_DEVICE_CLEAR,		"clear",	{4, 0, 0} },
680cdd1155SAlex Hornung 	{ DM_DEVICE_LIST_VERSIONS,	"targets",	{4, 1, 0} },
690cdd1155SAlex Hornung 	{ DM_DEVICE_STATUS,		"status",	{4, 0, 0} },
700cdd1155SAlex Hornung 	{ DM_DEVICE_TABLE,		"table",	{4, 0, 0} },
710cdd1155SAlex Hornung 	{ DM_DEVICE_INFO,		"info",		{4, 0, 0} },
720cdd1155SAlex Hornung 	{ DM_DEVICE_DEPS,		"deps",		{4, 0, 0} },
730cdd1155SAlex Hornung 	{ DM_DEVICE_VERSION,		"version",	{4, 0, 0} },
740cdd1155SAlex Hornung 	{ DM_DEVICE_TARGET_MSG,		"message",	{4, 2, 0} },
750cdd1155SAlex Hornung 	{ DM_DEVICE_RENAME,		"rename",	{4, 0, 0} },
760cdd1155SAlex Hornung 	{ DM_DEVICE_LIST,		"names",	{4, 0, 0} },
770cdd1155SAlex Hornung 	{ 0,				NULL,		{0, 0, 0} }
780cdd1155SAlex Hornung };
790cdd1155SAlex Hornung 
800cdd1155SAlex Hornung #define _LOG_DEBUG	0
810cdd1155SAlex Hornung #define _LOG_WARN	5
820cdd1155SAlex Hornung #define _LOG_ERR	10
830cdd1155SAlex Hornung 
_stderr_log(int level,const char * file,int line,const char * fmt,...)840cdd1155SAlex Hornung static void _stderr_log(int level, const char *file,
850cdd1155SAlex Hornung     int line, const char *fmt, ...)
860cdd1155SAlex Hornung {
870cdd1155SAlex Hornung 	const char *prefix;
880cdd1155SAlex Hornung 	__va_list ap;
890cdd1155SAlex Hornung 
900cdd1155SAlex Hornung 	switch (level) {
910cdd1155SAlex Hornung 	case _LOG_DEBUG:
920cdd1155SAlex Hornung 		prefix = "debug: ";
930cdd1155SAlex Hornung 		break;
940cdd1155SAlex Hornung 	case _LOG_WARN:
950cdd1155SAlex Hornung 		prefix = "warning: ";
960cdd1155SAlex Hornung 		break;
970cdd1155SAlex Hornung 	case _LOG_ERR:
980cdd1155SAlex Hornung 		prefix = "error: ";
990cdd1155SAlex Hornung 		break;
1000cdd1155SAlex Hornung 	default:
1010cdd1155SAlex Hornung 		prefix = "";
1020cdd1155SAlex Hornung 	}
1030cdd1155SAlex Hornung 
1040cdd1155SAlex Hornung 	fprintf(stderr, "libdm %s:%d: ", file, line);
1050cdd1155SAlex Hornung 	fprintf(stderr, "%s", prefix);
1060cdd1155SAlex Hornung 
1070cdd1155SAlex Hornung 	__va_start(ap, fmt);
1080cdd1155SAlex Hornung 	vfprintf(stderr, fmt, ap);
1090cdd1155SAlex Hornung 	__va_end(ap);
1100cdd1155SAlex Hornung 
1110cdd1155SAlex Hornung 	fprintf(stderr, "\n");
1120cdd1155SAlex Hornung 
1130cdd1155SAlex Hornung 	return;
1140cdd1155SAlex Hornung }
1150cdd1155SAlex Hornung 
1160cdd1155SAlex Hornung static dm_error_func_t dm_log = _stderr_log;
1170cdd1155SAlex Hornung 
1180cdd1155SAlex Hornung struct dm_task *
dm_task_create(int task_type)1190cdd1155SAlex Hornung dm_task_create(int task_type)
1200cdd1155SAlex Hornung {
1210cdd1155SAlex Hornung 	struct dm_task *dmt;
1220cdd1155SAlex Hornung 	struct dm_cmd *cmd = NULL;
1230cdd1155SAlex Hornung 	const char *task_cmd = NULL;
1240cdd1155SAlex Hornung 	prop_array_t pa;
1250cdd1155SAlex Hornung 	uint32_t flags = DM_EXISTS_FLAG;
1260cdd1155SAlex Hornung 	int i;
1270cdd1155SAlex Hornung 
1280cdd1155SAlex Hornung 	for (i = 0; dm_cmds[i].dm_cmd != NULL; i++) {
1290cdd1155SAlex Hornung 		if (dm_cmds[i].task_type == task_type) {
1300cdd1155SAlex Hornung 			cmd = &dm_cmds[i];
1310cdd1155SAlex Hornung 			task_cmd = dm_cmds[i].dm_cmd;
1320cdd1155SAlex Hornung 			break;
1330cdd1155SAlex Hornung 		}
1340cdd1155SAlex Hornung 	}
1350cdd1155SAlex Hornung 
1360cdd1155SAlex Hornung 	if (task_cmd == NULL)
1370cdd1155SAlex Hornung 		return NULL;
1380cdd1155SAlex Hornung 
1390cdd1155SAlex Hornung 	if (task_type == DM_DEVICE_TABLE)
1400cdd1155SAlex Hornung 		flags |= DM_STATUS_TABLE_FLAG;
1410cdd1155SAlex Hornung 
1420cdd1155SAlex Hornung 	if (task_type == DM_DEVICE_SUSPEND)
1430cdd1155SAlex Hornung 		flags |= DM_SUSPEND_FLAG;
1440cdd1155SAlex Hornung 
1450cdd1155SAlex Hornung 	if ((dmt = malloc(sizeof(*dmt))) == NULL)
1460cdd1155SAlex Hornung 		return NULL;
1470cdd1155SAlex Hornung 
1480cdd1155SAlex Hornung 	memset(dmt, 0, sizeof(*dmt));
1490cdd1155SAlex Hornung 
1500cdd1155SAlex Hornung 	dmt->task_type = task_type;
1510cdd1155SAlex Hornung 	dmt->was_enoent = 0;
1520cdd1155SAlex Hornung 
1530cdd1155SAlex Hornung 	if ((dmt->dict = prop_dictionary_create()) == NULL)
1540cdd1155SAlex Hornung 		goto err;
1550cdd1155SAlex Hornung 
1560cdd1155SAlex Hornung 	if ((pa = prop_array_create_with_capacity(3)) == NULL)
1570cdd1155SAlex Hornung 		goto err;
1580cdd1155SAlex Hornung 
1590cdd1155SAlex Hornung 	if (!prop_array_add_uint32(pa, cmd->cmd_version[0])) {
1600cdd1155SAlex Hornung 		prop_object_release(pa);
1610cdd1155SAlex Hornung 		goto err;
1620cdd1155SAlex Hornung 	}
1630cdd1155SAlex Hornung 
1640cdd1155SAlex Hornung 	if (!prop_array_add_uint32(pa, cmd->cmd_version[1])) {
1650cdd1155SAlex Hornung 		prop_object_release(pa);
1660cdd1155SAlex Hornung 		goto err;
1670cdd1155SAlex Hornung 	}
1680cdd1155SAlex Hornung 
1690cdd1155SAlex Hornung 	if (!prop_array_add_uint32(pa, cmd->cmd_version[2])) {
1700cdd1155SAlex Hornung 		prop_object_release(pa);
1710cdd1155SAlex Hornung 		goto err;
1720cdd1155SAlex Hornung 	}
1730cdd1155SAlex Hornung 
1740cdd1155SAlex Hornung 	if (!prop_dictionary_set(dmt->dict, DM_IOCTL_VERSION, pa)) {
1750cdd1155SAlex Hornung 		prop_object_release(pa);
1760cdd1155SAlex Hornung 		goto err;
1770cdd1155SAlex Hornung 	}
1780cdd1155SAlex Hornung 
1790cdd1155SAlex Hornung 	prop_object_release(pa);
1800cdd1155SAlex Hornung 
1810cdd1155SAlex Hornung 	if (!prop_dictionary_set_cstring(dmt->dict, DM_IOCTL_COMMAND,
1820cdd1155SAlex Hornung 	    task_cmd))
1830cdd1155SAlex Hornung 		goto err;
1840cdd1155SAlex Hornung 
1850cdd1155SAlex Hornung 	if (!prop_dictionary_set_uint32(dmt->dict, DM_IOCTL_FLAGS, flags))
1860cdd1155SAlex Hornung 		goto err;
1870cdd1155SAlex Hornung 
1880cdd1155SAlex Hornung 	if ((pa = prop_array_create_with_capacity(5)) == NULL)
1890cdd1155SAlex Hornung 		goto err;
1900cdd1155SAlex Hornung 
1910cdd1155SAlex Hornung 	if (!prop_dictionary_set(dmt->dict, DM_IOCTL_CMD_DATA, pa)) {
1920cdd1155SAlex Hornung 		prop_object_release(pa);
1930cdd1155SAlex Hornung 		goto err;
1940cdd1155SAlex Hornung 	}
1950cdd1155SAlex Hornung 
1960cdd1155SAlex Hornung 	prop_object_release(pa);
1970cdd1155SAlex Hornung 
1980cdd1155SAlex Hornung 	return dmt;
1990cdd1155SAlex Hornung 	/* NOT REACHED */
2000cdd1155SAlex Hornung 
2010cdd1155SAlex Hornung err:
2020cdd1155SAlex Hornung 	if (dmt->dict != NULL)
2030cdd1155SAlex Hornung 		prop_object_release(dmt->dict);
2040cdd1155SAlex Hornung 	if (dmt)
2050cdd1155SAlex Hornung 		free(dmt);
2060cdd1155SAlex Hornung 
2070cdd1155SAlex Hornung 	return NULL;
2080cdd1155SAlex Hornung }
2090cdd1155SAlex Hornung 
2100cdd1155SAlex Hornung 
2110cdd1155SAlex Hornung void
dm_task_destroy(struct dm_task * dmt)2120cdd1155SAlex Hornung dm_task_destroy(struct dm_task *dmt)
2130cdd1155SAlex Hornung {
2140cdd1155SAlex Hornung 	if (dmt) {
2150cdd1155SAlex Hornung 		if (dmt->data_buffer)
2160cdd1155SAlex Hornung 			free(dmt->data_buffer);
2170cdd1155SAlex Hornung 
2180cdd1155SAlex Hornung 		if (dmt->dict) {
2190cdd1155SAlex Hornung 			prop_object_release(dmt->dict);
2200cdd1155SAlex Hornung 			dmt->dict = NULL;
2210cdd1155SAlex Hornung 		}
2220cdd1155SAlex Hornung 
2230cdd1155SAlex Hornung 		free(dmt);
2240cdd1155SAlex Hornung 	}
2250cdd1155SAlex Hornung }
2260cdd1155SAlex Hornung 
2270cdd1155SAlex Hornung int
dm_task_run(struct dm_task * dmt)2280cdd1155SAlex Hornung dm_task_run(struct dm_task *dmt)
2290cdd1155SAlex Hornung {
2300cdd1155SAlex Hornung 	struct dm_task *dmt_internal = NULL;
2310cdd1155SAlex Hornung 	prop_dictionary_t ret_pd = NULL;
2320cdd1155SAlex Hornung 	prop_array_t pa;
2330cdd1155SAlex Hornung 	int error;
2340cdd1155SAlex Hornung 	int fd;
2350cdd1155SAlex Hornung 	int need_unroll = 0;
2360cdd1155SAlex Hornung 
2370cdd1155SAlex Hornung 	if ((fd = open("/dev/mapper/control", O_RDWR)) < -1)
2380cdd1155SAlex Hornung 		goto err;
2390cdd1155SAlex Hornung 
2400cdd1155SAlex Hornung 	pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA);
2410cdd1155SAlex Hornung 	if ((dmt->task_type == DM_DEVICE_CREATE) && (pa != NULL) &&
2420cdd1155SAlex Hornung 	    (prop_array_count(pa) > 0)) {
2430cdd1155SAlex Hornung 		/*
2440cdd1155SAlex Hornung 		 * Magic to separate a combined DM_DEVICE_CREATE+RELOAD int
2450cdd1155SAlex Hornung 		 * a DM_DEVICE_CREATE and a RELOAD with target table.
2460cdd1155SAlex Hornung 		 */
2470cdd1155SAlex Hornung 
2480cdd1155SAlex Hornung 		if ((dmt_internal = dm_task_create(DM_DEVICE_CREATE)) == NULL)
2490cdd1155SAlex Hornung 			goto err;
2500cdd1155SAlex Hornung 		if (!dm_task_set_name(dmt_internal, dm_task_get_name(dmt)))
2510cdd1155SAlex Hornung 			goto err;
2520cdd1155SAlex Hornung 		if (!dm_task_set_uuid(dmt_internal, dm_task_get_uuid(dmt)))
2530cdd1155SAlex Hornung 			goto err;
2540cdd1155SAlex Hornung 		if (!dm_task_run(dmt_internal))
2550cdd1155SAlex Hornung 			goto err;
2560cdd1155SAlex Hornung 		dm_task_destroy(dmt_internal);
2570cdd1155SAlex Hornung 		dmt_internal = NULL;
2580cdd1155SAlex Hornung 
2590cdd1155SAlex Hornung 		if (!prop_dictionary_set_cstring_nocopy(dmt->dict,
2600cdd1155SAlex Hornung 		    DM_IOCTL_COMMAND, "reload"))
2610cdd1155SAlex Hornung 			goto unroll;
2620cdd1155SAlex Hornung 		dmt->task_type = DM_DEVICE_RELOAD;
2630cdd1155SAlex Hornung 		if ((error = prop_dictionary_sendrecv_ioctl(dmt->dict, fd,
2640cdd1155SAlex Hornung 		    NETBSD_DM_IOCTL, &ret_pd)) != 0) {
2650cdd1155SAlex Hornung 			dm_log(_LOG_ERR, __FILE__, __LINE__, "ioctl failed: %d",
2660cdd1155SAlex Hornung 			    error);
2670cdd1155SAlex Hornung 			goto unroll;
2680cdd1155SAlex Hornung 		}
2690cdd1155SAlex Hornung 
2700cdd1155SAlex Hornung 		if (!prop_dictionary_set_cstring_nocopy(dmt->dict,
2710cdd1155SAlex Hornung 		    DM_IOCTL_COMMAND, "resume"))
2720cdd1155SAlex Hornung 			goto unroll;
2730cdd1155SAlex Hornung 		dmt->task_type = DM_DEVICE_RESUME;
2740cdd1155SAlex Hornung 		/* Remove superfluous stuff */
2750cdd1155SAlex Hornung 		prop_dictionary_remove(dmt->dict, DM_IOCTL_CMD_DATA);
2760cdd1155SAlex Hornung 
2770cdd1155SAlex Hornung 		need_unroll = 1;
2780cdd1155SAlex Hornung 	}
2790cdd1155SAlex Hornung 
2800cdd1155SAlex Hornung 	if ((error = prop_dictionary_sendrecv_ioctl(dmt->dict, fd,
2810cdd1155SAlex Hornung 	    NETBSD_DM_IOCTL, &ret_pd)) != 0) {
2820cdd1155SAlex Hornung 		if (((error == ENOENT) &&
2830cdd1155SAlex Hornung 		    ((dmt->task_type == DM_DEVICE_INFO) ||
2840cdd1155SAlex Hornung 		    (dmt->task_type == DM_DEVICE_STATUS)))) {
2850cdd1155SAlex Hornung 			dmt->was_enoent = 1;
2860cdd1155SAlex Hornung 			ret_pd = NULL;
2870cdd1155SAlex Hornung 		} else {
2880cdd1155SAlex Hornung 			dm_log(_LOG_ERR, __FILE__, __LINE__, "ioctl failed: %d",
2890cdd1155SAlex Hornung 			    error);
2900cdd1155SAlex Hornung 			if (need_unroll)
2910cdd1155SAlex Hornung 				goto unroll;
2920cdd1155SAlex Hornung 			else
2930cdd1155SAlex Hornung 				goto err;
2940cdd1155SAlex Hornung 		}
2950cdd1155SAlex Hornung 	}
2960cdd1155SAlex Hornung 
2970cdd1155SAlex Hornung 	if (ret_pd)
2980cdd1155SAlex Hornung 		prop_object_retain(ret_pd);
2990cdd1155SAlex Hornung 
3000cdd1155SAlex Hornung 	prop_object_release(dmt->dict);
3010cdd1155SAlex Hornung 	dmt->dict = ret_pd;
3020cdd1155SAlex Hornung 
3030cdd1155SAlex Hornung 	return 1;
3040cdd1155SAlex Hornung 	/* NOT REACHED */
3050cdd1155SAlex Hornung 
3060cdd1155SAlex Hornung unroll:
3070cdd1155SAlex Hornung 	prop_dictionary_remove(dmt->dict, DM_IOCTL_CMD_DATA);
3080cdd1155SAlex Hornung 
3090cdd1155SAlex Hornung 	if (!prop_dictionary_set_cstring_nocopy(dmt->dict, DM_IOCTL_COMMAND,
3100cdd1155SAlex Hornung 	    "remove")) {
3110cdd1155SAlex Hornung 		dm_log(_LOG_ERR, __FILE__, __LINE__, "couldn't unroll changes "
3120cdd1155SAlex Hornung 		    "in dm_task_run");
3130cdd1155SAlex Hornung 		goto err;
3140cdd1155SAlex Hornung 	}
3150cdd1155SAlex Hornung 
3160cdd1155SAlex Hornung 	if ((error = prop_dictionary_sendrecv_ioctl(dmt->dict, fd,
3170cdd1155SAlex Hornung 	    NETBSD_DM_IOCTL, &ret_pd)) != 0) {
3180cdd1155SAlex Hornung 		dm_log(_LOG_ERR, __FILE__, __LINE__, "ioctl failed: %d",
3190cdd1155SAlex Hornung 		    error);
3200cdd1155SAlex Hornung 		goto unroll;
3210cdd1155SAlex Hornung 	}
3220cdd1155SAlex Hornung 	dmt->task_type = DM_DEVICE_REMOVE;
3230cdd1155SAlex Hornung 	dm_task_run(dmt);
3240cdd1155SAlex Hornung 
3250cdd1155SAlex Hornung err:
3260cdd1155SAlex Hornung 	if (fd >= 0)
3270cdd1155SAlex Hornung 		close(fd);
3280cdd1155SAlex Hornung 
3290cdd1155SAlex Hornung 	if (dmt_internal)
3300cdd1155SAlex Hornung 		dm_task_destroy(dmt_internal);
3310cdd1155SAlex Hornung 
3320cdd1155SAlex Hornung 	return 0;
3330cdd1155SAlex Hornung }
3340cdd1155SAlex Hornung 
3350cdd1155SAlex Hornung int
dm_task_set_name(struct dm_task * dmt,const char * name)3360cdd1155SAlex Hornung dm_task_set_name(struct dm_task *dmt, const char *name)
3370cdd1155SAlex Hornung {
3380cdd1155SAlex Hornung 	return prop_dictionary_set_cstring(dmt->dict, DM_IOCTL_NAME,
3390cdd1155SAlex Hornung 	    __DECONST(char *, name));
3400cdd1155SAlex Hornung }
3410cdd1155SAlex Hornung 
3420cdd1155SAlex Hornung 
3430cdd1155SAlex Hornung const char *
dm_task_get_name(struct dm_task * dmt)3440cdd1155SAlex Hornung dm_task_get_name(struct dm_task *dmt)
3450cdd1155SAlex Hornung {
3460cdd1155SAlex Hornung 	const char *name = NULL;
3470cdd1155SAlex Hornung 
3480cdd1155SAlex Hornung 	prop_dictionary_get_cstring_nocopy(dmt->dict, DM_IOCTL_NAME, &name);
3490cdd1155SAlex Hornung 
3500cdd1155SAlex Hornung 	return name;
3510cdd1155SAlex Hornung }
3520cdd1155SAlex Hornung 
3530cdd1155SAlex Hornung int
dm_task_set_newname(struct dm_task * dmt,const char * newname)3540cdd1155SAlex Hornung dm_task_set_newname(struct dm_task *dmt, const char *newname)
3550cdd1155SAlex Hornung {
3560cdd1155SAlex Hornung 	return prop_dictionary_set_cstring(dmt->dict, DM_DEV_NEWNAME,
3570cdd1155SAlex Hornung 	    __DECONST(char *, newname));
3580cdd1155SAlex Hornung }
3590cdd1155SAlex Hornung 
3600cdd1155SAlex Hornung int
dm_task_set_major(struct dm_task * dmt __unused,int major __unused)3610cdd1155SAlex Hornung dm_task_set_major(struct dm_task *dmt __unused, int major __unused)
3620cdd1155SAlex Hornung {
3630cdd1155SAlex Hornung 	return 1;
3640cdd1155SAlex Hornung }
3650cdd1155SAlex Hornung 
3660cdd1155SAlex Hornung int
dm_task_set_minor(struct dm_task * dmt,int minor)3670cdd1155SAlex Hornung dm_task_set_minor(struct dm_task *dmt, int minor)
3680cdd1155SAlex Hornung {
3690cdd1155SAlex Hornung 	return prop_dictionary_set_int32(dmt->dict, DM_IOCTL_MINOR, minor);
3700cdd1155SAlex Hornung }
3710cdd1155SAlex Hornung 
3720cdd1155SAlex Hornung int
dm_task_get_minor(struct dm_task * dmt)3730cdd1155SAlex Hornung dm_task_get_minor(struct dm_task *dmt)
3740cdd1155SAlex Hornung {
3750cdd1155SAlex Hornung 	int minor = 0;
3760cdd1155SAlex Hornung 
3770cdd1155SAlex Hornung 	minor = prop_dictionary_get_int32(dmt->dict, DM_IOCTL_MINOR, &minor);
3780cdd1155SAlex Hornung 
3790cdd1155SAlex Hornung 	return minor;
3800cdd1155SAlex Hornung }
3810cdd1155SAlex Hornung 
3820cdd1155SAlex Hornung int
dm_task_set_uuid(struct dm_task * dmt,const char * uuid)3830cdd1155SAlex Hornung dm_task_set_uuid(struct dm_task *dmt, const char *uuid)
3840cdd1155SAlex Hornung {
3850cdd1155SAlex Hornung 	return prop_dictionary_set_cstring(dmt->dict, DM_IOCTL_UUID,
3860cdd1155SAlex Hornung 	    __DECONST(char *,uuid));
3870cdd1155SAlex Hornung }
3880cdd1155SAlex Hornung 
3890cdd1155SAlex Hornung const char *
dm_task_get_uuid(struct dm_task * dmt)3900cdd1155SAlex Hornung dm_task_get_uuid(struct dm_task *dmt)
3910cdd1155SAlex Hornung {
3920cdd1155SAlex Hornung 	const char *uuid = NULL;
3930cdd1155SAlex Hornung 
3940cdd1155SAlex Hornung 	prop_dictionary_get_cstring_nocopy(dmt->dict, DM_IOCTL_UUID, &uuid);
3950cdd1155SAlex Hornung 
3960cdd1155SAlex Hornung 	return uuid;
3970cdd1155SAlex Hornung }
3980cdd1155SAlex Hornung 
3990cdd1155SAlex Hornung int
dm_task_add_target(struct dm_task * dmt,uint64_t start,size_t size,const char * target,const char * params)4000cdd1155SAlex Hornung dm_task_add_target(struct dm_task *dmt, uint64_t start, size_t size,
4010cdd1155SAlex Hornung     const char *target, const char *params)
4020cdd1155SAlex Hornung {
4030cdd1155SAlex Hornung 	prop_dictionary_t target_dict = NULL;
4040cdd1155SAlex Hornung 	prop_array_t pa = NULL;
4050cdd1155SAlex Hornung 
4060cdd1155SAlex Hornung 	if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
4070cdd1155SAlex Hornung 		return 0;
4080cdd1155SAlex Hornung 
4090cdd1155SAlex Hornung 	if ((target_dict = prop_dictionary_create()) == NULL)
4100cdd1155SAlex Hornung 		return 0;
4110cdd1155SAlex Hornung 
4120cdd1155SAlex Hornung 	if (!prop_dictionary_set_uint64(target_dict, DM_TABLE_START, start))
4130cdd1155SAlex Hornung 		goto err;
4140cdd1155SAlex Hornung 
4150cdd1155SAlex Hornung 	if (!prop_dictionary_set_uint64(target_dict, DM_TABLE_LENGTH, size))
4160cdd1155SAlex Hornung 		goto err;
4170cdd1155SAlex Hornung 
4180cdd1155SAlex Hornung 	if (!prop_dictionary_set_cstring(target_dict, DM_TABLE_TYPE, target))
4190cdd1155SAlex Hornung 		goto err;
4200cdd1155SAlex Hornung 
4210cdd1155SAlex Hornung 	if (!prop_dictionary_set_cstring(target_dict, DM_TABLE_PARAMS, params))
4220cdd1155SAlex Hornung 		goto err;
4230cdd1155SAlex Hornung 
4240cdd1155SAlex Hornung 	if (!prop_array_add(pa, target_dict))
4250cdd1155SAlex Hornung 		goto err;
4260cdd1155SAlex Hornung 
4270cdd1155SAlex Hornung 	prop_object_release(target_dict);
4280cdd1155SAlex Hornung 
4290cdd1155SAlex Hornung 	return 1;
4300cdd1155SAlex Hornung 	/* NOT REACHED */
4310cdd1155SAlex Hornung 
4320cdd1155SAlex Hornung err:
4330cdd1155SAlex Hornung 	prop_object_release(target_dict);
4340cdd1155SAlex Hornung 	return 0;
4350cdd1155SAlex Hornung }
4360cdd1155SAlex Hornung 
4370cdd1155SAlex Hornung int
dm_task_set_sector(struct dm_task * dmt,uint64_t sector)4380cdd1155SAlex Hornung dm_task_set_sector(struct dm_task *dmt, uint64_t sector)
4390cdd1155SAlex Hornung {
4400cdd1155SAlex Hornung 	return prop_dictionary_set_uint64(dmt->dict, DM_MESSAGE_SECTOR,
4410cdd1155SAlex Hornung 	    sector);
4420cdd1155SAlex Hornung }
4430cdd1155SAlex Hornung 
4440cdd1155SAlex Hornung int
dm_task_set_message(struct dm_task * dmt,const char * msg)4450cdd1155SAlex Hornung dm_task_set_message(struct dm_task *dmt, const char *msg)
4460cdd1155SAlex Hornung {
4470cdd1155SAlex Hornung 	return prop_dictionary_set_cstring(dmt->dict, DM_MESSAGE_STR, msg);
4480cdd1155SAlex Hornung }
4490cdd1155SAlex Hornung 
4500cdd1155SAlex Hornung int
dm_task_set_ro(struct dm_task * dmt)4510cdd1155SAlex Hornung dm_task_set_ro(struct dm_task *dmt)
4520cdd1155SAlex Hornung {
4530cdd1155SAlex Hornung 	uint32_t flags = 0;
4540cdd1155SAlex Hornung 
4550cdd1155SAlex Hornung 	prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_FLAGS, &flags);
4560cdd1155SAlex Hornung 	flags |= DM_READONLY_FLAG;
4570cdd1155SAlex Hornung 
4580cdd1155SAlex Hornung 	return prop_dictionary_set_uint32(dmt->dict, DM_IOCTL_FLAGS, flags);
4590cdd1155SAlex Hornung }
4600cdd1155SAlex Hornung 
4610cdd1155SAlex Hornung int
dm_task_no_open_count(struct dm_task * dmt __unused)4620cdd1155SAlex Hornung dm_task_no_open_count(struct dm_task *dmt __unused)
4630cdd1155SAlex Hornung {
4640cdd1155SAlex Hornung 	/*
4650cdd1155SAlex Hornung 	 * nothing else needed, since we don't have performance problems when
4660cdd1155SAlex Hornung 	 * getting the open count.
4670cdd1155SAlex Hornung 	 */
4680cdd1155SAlex Hornung 	return 1;
4690cdd1155SAlex Hornung }
4700cdd1155SAlex Hornung 
4710cdd1155SAlex Hornung int
dm_task_query_inactive_table(struct dm_task * dmt)4720cdd1155SAlex Hornung dm_task_query_inactive_table(struct dm_task *dmt)
4730cdd1155SAlex Hornung {
4740cdd1155SAlex Hornung 	uint32_t flags = 0;
4750cdd1155SAlex Hornung 
4760cdd1155SAlex Hornung 	prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_FLAGS, &flags);
4770cdd1155SAlex Hornung 	flags |= DM_QUERY_INACTIVE_TABLE_FLAG;
4780cdd1155SAlex Hornung 
4790cdd1155SAlex Hornung 	return prop_dictionary_set_uint32(dmt->dict, DM_IOCTL_FLAGS, flags);
4800cdd1155SAlex Hornung }
4810cdd1155SAlex Hornung 
4820cdd1155SAlex Hornung int
dm_task_set_read_ahead(struct dm_task * dmt __unused,uint32_t read_ahead __unused)4830cdd1155SAlex Hornung dm_task_set_read_ahead(struct dm_task *dmt __unused,
4840cdd1155SAlex Hornung     uint32_t read_ahead __unused)
4850cdd1155SAlex Hornung {
4860cdd1155SAlex Hornung 	/* We don't support readahead */
4870cdd1155SAlex Hornung 	return 1;
4880cdd1155SAlex Hornung }
4890cdd1155SAlex Hornung 
4900cdd1155SAlex Hornung int
dm_task_get_read_ahead(struct dm_task * dmt __unused,uint32_t * read_ahead)4910cdd1155SAlex Hornung dm_task_get_read_ahead(struct dm_task *dmt __unused, uint32_t *read_ahead)
4920cdd1155SAlex Hornung {
4930cdd1155SAlex Hornung 	*read_ahead = 0;
4940cdd1155SAlex Hornung 
4950cdd1155SAlex Hornung 	return 1;
4960cdd1155SAlex Hornung }
4970cdd1155SAlex Hornung 
4980cdd1155SAlex Hornung int
dm_task_secure_data(struct dm_task * dmt)4990cdd1155SAlex Hornung dm_task_secure_data(struct dm_task *dmt)
5000cdd1155SAlex Hornung {
5010cdd1155SAlex Hornung 	/* XXX: needs kernel support */
5020cdd1155SAlex Hornung 	uint32_t flags = 0;
5030cdd1155SAlex Hornung 
5040cdd1155SAlex Hornung 	prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_FLAGS, &flags);
5050cdd1155SAlex Hornung 	flags |= DM_SECURE_DATA_FLAG;
5060cdd1155SAlex Hornung 
5070cdd1155SAlex Hornung 	return prop_dictionary_set_uint32(dmt->dict, DM_IOCTL_FLAGS, flags);
5080cdd1155SAlex Hornung }
5090cdd1155SAlex Hornung 
5100cdd1155SAlex Hornung int
dm_task_get_info(struct dm_task * dmt,struct dm_info * dmi)5110cdd1155SAlex Hornung dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi)
5120cdd1155SAlex Hornung {
5130cdd1155SAlex Hornung 	uint32_t flags = 0;
5140cdd1155SAlex Hornung 
5150cdd1155SAlex Hornung 	memset(dmi, 0, sizeof(struct dm_info));
5160cdd1155SAlex Hornung 
5170cdd1155SAlex Hornung 	/* Hack due to the way Linux dm works */
5180cdd1155SAlex Hornung 	if (dmt->was_enoent) {
5190cdd1155SAlex Hornung 		dmi->exists = 0;
5200cdd1155SAlex Hornung 		return 1;
5210cdd1155SAlex Hornung 		/* NOT REACHED */
5220cdd1155SAlex Hornung 	}
5230cdd1155SAlex Hornung 
5240cdd1155SAlex Hornung 	if (!prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_FLAGS,
5250cdd1155SAlex Hornung 	    &flags))
5260cdd1155SAlex Hornung 		return 0;
5270cdd1155SAlex Hornung 
5280cdd1155SAlex Hornung 	prop_dictionary_get_int32(dmt->dict, DM_IOCTL_OPEN, &dmi->open_count);
5290cdd1155SAlex Hornung 
5300cdd1155SAlex Hornung 	prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_TARGET_COUNT,
5310cdd1155SAlex Hornung 	    &dmi->target_count);
5320cdd1155SAlex Hornung 
5330cdd1155SAlex Hornung 	prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_EVENT, &dmi->event_nr);
5340cdd1155SAlex Hornung 
5350cdd1155SAlex Hornung 	prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_MINOR, &dmi->minor);
5360cdd1155SAlex Hornung 
5370cdd1155SAlex Hornung 	dmi->major = dm_get_major();
5380cdd1155SAlex Hornung 
5390cdd1155SAlex Hornung 	dmi->read_only = (flags & DM_READONLY_FLAG);
5400cdd1155SAlex Hornung 	dmi->exists = (flags & DM_EXISTS_FLAG);
5410cdd1155SAlex Hornung 	dmi->suspended = (flags & DM_SUSPEND_FLAG);
5420cdd1155SAlex Hornung 	dmi->live_table = (flags & DM_ACTIVE_PRESENT_FLAG);
5430cdd1155SAlex Hornung 	dmi->inactive_table = (flags & DM_INACTIVE_PRESENT_FLAG);
5440cdd1155SAlex Hornung 
5450cdd1155SAlex Hornung 	return 1;
5460cdd1155SAlex Hornung }
5470cdd1155SAlex Hornung 
5480cdd1155SAlex Hornung int
dm_task_get_driver_version(struct dm_task * dmt,char * ver,size_t ver_sz)5490cdd1155SAlex Hornung dm_task_get_driver_version(struct dm_task *dmt, char *ver, size_t ver_sz)
5500cdd1155SAlex Hornung {
5510cdd1155SAlex Hornung 	prop_array_t pa_ver;
5520cdd1155SAlex Hornung 	uint32_t maj = 0, min = 0, patch = 0;
5530cdd1155SAlex Hornung 
5540cdd1155SAlex Hornung 	if ((pa_ver = prop_dictionary_get(dmt->dict, DM_IOCTL_VERSION)) == NULL)
5550cdd1155SAlex Hornung 		return 0;
5560cdd1155SAlex Hornung 
5570cdd1155SAlex Hornung 	if (!prop_array_get_uint32(pa_ver, 0, &maj))
5580cdd1155SAlex Hornung 		return 0;
5590cdd1155SAlex Hornung 
5600cdd1155SAlex Hornung 	if (!prop_array_get_uint32(pa_ver, 1, &min))
5610cdd1155SAlex Hornung 		return 0;
5620cdd1155SAlex Hornung 
5630cdd1155SAlex Hornung 	if (!prop_array_get_uint32(pa_ver, 2, &patch))
5640cdd1155SAlex Hornung 		return 0;
5650cdd1155SAlex Hornung 
5660cdd1155SAlex Hornung 	snprintf(ver, ver_sz, "%u.%u.%u", maj, min, patch);
5670cdd1155SAlex Hornung 
5680cdd1155SAlex Hornung 	return 1;
5690cdd1155SAlex Hornung }
5700cdd1155SAlex Hornung 
5710cdd1155SAlex Hornung struct dm_deps *
dm_task_get_deps(struct dm_task * dmt)5720cdd1155SAlex Hornung dm_task_get_deps(struct dm_task *dmt)
5730cdd1155SAlex Hornung {
5740cdd1155SAlex Hornung 	prop_object_iterator_t iter;
5750cdd1155SAlex Hornung 	prop_array_t pa;
5760cdd1155SAlex Hornung 	prop_object_t po;
5770cdd1155SAlex Hornung 	struct dm_deps *deps;
5780cdd1155SAlex Hornung 
5790cdd1155SAlex Hornung 	unsigned int count;
5800cdd1155SAlex Hornung 	int i;
5810cdd1155SAlex Hornung 
5820cdd1155SAlex Hornung 	if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
5830cdd1155SAlex Hornung 		return NULL;
5840cdd1155SAlex Hornung 
5850cdd1155SAlex Hornung 	count = prop_array_count(pa);
5860cdd1155SAlex Hornung 
5870cdd1155SAlex Hornung 	if (dmt->data_buffer != NULL)
5880cdd1155SAlex Hornung 		free(dmt->data_buffer);
5890cdd1155SAlex Hornung 
5900cdd1155SAlex Hornung 	if ((dmt->data_buffer = malloc(sizeof(struct dm_deps) +
5910cdd1155SAlex Hornung 	    (count * sizeof(uint64_t)))) == NULL)
5920cdd1155SAlex Hornung 		return NULL;
5930cdd1155SAlex Hornung 
5940cdd1155SAlex Hornung 	if ((iter = prop_array_iterator(pa)) == NULL)
5950cdd1155SAlex Hornung 		return NULL;
5960cdd1155SAlex Hornung 
5970cdd1155SAlex Hornung 	deps = (struct dm_deps *)dmt->data_buffer;
5980cdd1155SAlex Hornung 	memset(deps, 0, sizeof(struct dm_deps) + (count * sizeof(uint64_t)));
5990cdd1155SAlex Hornung 	i = 0;
6000cdd1155SAlex Hornung 	while ((po = prop_object_iterator_next(iter)) != NULL)
6010cdd1155SAlex Hornung 		deps->deps[i++] = prop_number_unsigned_integer_value(po);
6020cdd1155SAlex Hornung 
6030cdd1155SAlex Hornung 	deps->count = (uint32_t)count;
6040cdd1155SAlex Hornung 
6050cdd1155SAlex Hornung 	prop_object_iterator_release(iter);
6060cdd1155SAlex Hornung 
6070cdd1155SAlex Hornung 	return deps;
6080cdd1155SAlex Hornung }
6090cdd1155SAlex Hornung 
6100cdd1155SAlex Hornung struct dm_versions *
dm_task_get_versions(struct dm_task * dmt)6110cdd1155SAlex Hornung dm_task_get_versions(struct dm_task *dmt)
6120cdd1155SAlex Hornung {
6130cdd1155SAlex Hornung 	prop_object_iterator_t iter;
6140cdd1155SAlex Hornung 	prop_dictionary_t target_dict;
6150cdd1155SAlex Hornung 	prop_array_t pa, pa_ver;
6160cdd1155SAlex Hornung 	struct dm_versions *vers;
6170cdd1155SAlex Hornung 
6180cdd1155SAlex Hornung 	unsigned int count;
6190cdd1155SAlex Hornung 	int i, j;
6200cdd1155SAlex Hornung 
6210cdd1155SAlex Hornung 	if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
6220cdd1155SAlex Hornung 		return NULL;
6230cdd1155SAlex Hornung 
6240cdd1155SAlex Hornung 	count = prop_array_count(pa);
6250cdd1155SAlex Hornung 
6260cdd1155SAlex Hornung 	if (dmt->data_buffer != NULL)
6270cdd1155SAlex Hornung 		free(dmt->data_buffer);
6280cdd1155SAlex Hornung 
6290cdd1155SAlex Hornung 	if ((dmt->data_buffer = malloc(sizeof(struct dm_versions) * count))
6300cdd1155SAlex Hornung 	    == NULL)
6310cdd1155SAlex Hornung 		return NULL;
6320cdd1155SAlex Hornung 
6330cdd1155SAlex Hornung 	if ((iter = prop_array_iterator(pa)) == NULL)
6340cdd1155SAlex Hornung 		return NULL;
6350cdd1155SAlex Hornung 
6360cdd1155SAlex Hornung 	vers = (struct dm_versions *)dmt->data_buffer;
6370cdd1155SAlex Hornung 	memset(vers, 0, sizeof(struct dm_versions) * count);
6380cdd1155SAlex Hornung 	i = 0;
6390cdd1155SAlex Hornung 	while ((target_dict = prop_object_iterator_next(iter)) != NULL) {
6400cdd1155SAlex Hornung 		vers[i].next = sizeof(struct dm_versions);
6410cdd1155SAlex Hornung 		prop_dictionary_get_cstring_nocopy(target_dict,
6420cdd1155SAlex Hornung 		    DM_TARGETS_NAME, &vers[i].name);
6430cdd1155SAlex Hornung 
6440cdd1155SAlex Hornung 		pa_ver = prop_dictionary_get(target_dict, DM_TARGETS_VERSION);
6450cdd1155SAlex Hornung 		for (j = 0; j < 3; j++)
6460cdd1155SAlex Hornung 			prop_array_get_uint32(pa_ver, j, &vers[i].version[j]);
6470cdd1155SAlex Hornung 
6480cdd1155SAlex Hornung 		++i;
6490cdd1155SAlex Hornung 	}
6500cdd1155SAlex Hornung 
6510cdd1155SAlex Hornung 	/* Finish the array */
6520cdd1155SAlex Hornung 	vers[i-1].next = 0;
6530cdd1155SAlex Hornung 
6540cdd1155SAlex Hornung 	prop_object_iterator_release(iter);
6550cdd1155SAlex Hornung 
6560cdd1155SAlex Hornung 	return (struct dm_versions *)dmt->data_buffer;
6570cdd1155SAlex Hornung }
6580cdd1155SAlex Hornung 
6590cdd1155SAlex Hornung struct dm_names *
dm_task_get_names(struct dm_task * dmt)6600cdd1155SAlex Hornung dm_task_get_names(struct dm_task *dmt)
6610cdd1155SAlex Hornung {
6620cdd1155SAlex Hornung 	prop_object_iterator_t iter;
6630cdd1155SAlex Hornung 	prop_dictionary_t devs_dict;
6640cdd1155SAlex Hornung 	prop_array_t pa;
6650cdd1155SAlex Hornung 	struct dm_names *names;
6660cdd1155SAlex Hornung 
6670cdd1155SAlex Hornung 	unsigned int count;
6680cdd1155SAlex Hornung 	int i;
6690cdd1155SAlex Hornung 
6700cdd1155SAlex Hornung 	if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
6710cdd1155SAlex Hornung 		return NULL;
6720cdd1155SAlex Hornung 
6730cdd1155SAlex Hornung 	count = prop_array_count(pa);
6740cdd1155SAlex Hornung 
6750cdd1155SAlex Hornung 	if (dmt->data_buffer != NULL)
6760cdd1155SAlex Hornung 		free(dmt->data_buffer);
6770cdd1155SAlex Hornung 
6780cdd1155SAlex Hornung 	if ((dmt->data_buffer = malloc(sizeof(struct dm_names) * count))
6790cdd1155SAlex Hornung 	    == NULL)
6800cdd1155SAlex Hornung 		return NULL;
6810cdd1155SAlex Hornung 
6820cdd1155SAlex Hornung 	if ((iter = prop_array_iterator(pa)) == NULL)
6830cdd1155SAlex Hornung 		return NULL;
6840cdd1155SAlex Hornung 
6850cdd1155SAlex Hornung 	names = (struct dm_names *)dmt->data_buffer;
6860cdd1155SAlex Hornung 	memset(names, 0, sizeof(struct dm_names) * count);
6870cdd1155SAlex Hornung 	i = 0;
6880cdd1155SAlex Hornung 	while ((devs_dict = prop_object_iterator_next(iter)) != NULL) {
6890cdd1155SAlex Hornung 		names[i].next = sizeof(struct dm_names);
6900cdd1155SAlex Hornung 
6910cdd1155SAlex Hornung 		prop_dictionary_get_cstring_nocopy(devs_dict,
6920cdd1155SAlex Hornung 		    DM_DEV_NAME, &names[i].name);
6930cdd1155SAlex Hornung 
6940cdd1155SAlex Hornung 		prop_dictionary_get_uint64(devs_dict, DM_DEV_DEV,
6950cdd1155SAlex Hornung 		    &names[i].dev);
6960cdd1155SAlex Hornung 
6970cdd1155SAlex Hornung 		++i;
6980cdd1155SAlex Hornung 	}
6990cdd1155SAlex Hornung 
7000cdd1155SAlex Hornung 	/* Finish the array */
7010cdd1155SAlex Hornung 	names[i-1].next = 0;
7020cdd1155SAlex Hornung 
7030cdd1155SAlex Hornung 	prop_object_iterator_release(iter);
7040cdd1155SAlex Hornung 
7050cdd1155SAlex Hornung 	return (struct dm_names *)dmt->data_buffer;
7060cdd1155SAlex Hornung }
7070cdd1155SAlex Hornung 
7080cdd1155SAlex Hornung int
dm_task_update_nodes(void)7090cdd1155SAlex Hornung dm_task_update_nodes(void)
7100cdd1155SAlex Hornung {
7110cdd1155SAlex Hornung 
7120cdd1155SAlex Hornung 	/* nothing else needed */
7130cdd1155SAlex Hornung 	return 1;
7140cdd1155SAlex Hornung }
7150cdd1155SAlex Hornung 
7160cdd1155SAlex Hornung void *
dm_get_next_target(struct dm_task * dmt,void * cur,uint64_t * startp,uint64_t * lengthp,char ** target_type,char ** params)7170cdd1155SAlex Hornung dm_get_next_target(struct dm_task *dmt, void *cur, uint64_t *startp,
7180cdd1155SAlex Hornung     uint64_t *lengthp, char **target_type, char **params)
7190cdd1155SAlex Hornung {
7200cdd1155SAlex Hornung 	prop_object_iterator_t  iter;
7210cdd1155SAlex Hornung 	prop_dictionary_t target_dict;
7220cdd1155SAlex Hornung 	prop_array_t pa;
7230cdd1155SAlex Hornung 	uint64_t ulength;
7240cdd1155SAlex Hornung 	unsigned int count;
7250cdd1155SAlex Hornung 
7260cdd1155SAlex Hornung 	if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
7270cdd1155SAlex Hornung 		return NULL;
7280cdd1155SAlex Hornung 
7290cdd1155SAlex Hornung 	count = prop_array_count(pa);
7300cdd1155SAlex Hornung 
7310cdd1155SAlex Hornung 	if (cur == NULL) {
7320cdd1155SAlex Hornung 		if ((iter = prop_array_iterator(pa)) == NULL)
7330cdd1155SAlex Hornung 			return NULL;
7340cdd1155SAlex Hornung 	} else {
7350cdd1155SAlex Hornung 		iter = (prop_object_iterator_t)cur;
7360cdd1155SAlex Hornung 	}
7370cdd1155SAlex Hornung 
7380cdd1155SAlex Hornung 	/* Get the next target dict */
7390cdd1155SAlex Hornung 	if ((target_dict = prop_object_iterator_next(iter)) == NULL) {
7400cdd1155SAlex Hornung 		/* If there are no more target dicts, release the iterator */
7410cdd1155SAlex Hornung 		goto err;
7420cdd1155SAlex Hornung 	}
7430cdd1155SAlex Hornung 
7440cdd1155SAlex Hornung 	if (!prop_dictionary_get_cstring_nocopy(target_dict, DM_TABLE_TYPE,
7450cdd1155SAlex Hornung 	    (const char **)target_type))
7460cdd1155SAlex Hornung 		goto err;
7470cdd1155SAlex Hornung 
7480cdd1155SAlex Hornung 	/*
7490cdd1155SAlex Hornung 	 * Ugly __DECONST and (const char **) casts due to the linux prototype
7500cdd1155SAlex Hornung 	 * of this function.
7510cdd1155SAlex Hornung 	 */
7520cdd1155SAlex Hornung 	*params = __DECONST(char *, "");
7530cdd1155SAlex Hornung 	prop_dictionary_get_cstring_nocopy(target_dict, DM_TABLE_PARAMS,
7540cdd1155SAlex Hornung 	    (const char **)params);
7550cdd1155SAlex Hornung 
7560cdd1155SAlex Hornung 	if (!prop_dictionary_get_uint64(target_dict, DM_TABLE_START, startp))
7570cdd1155SAlex Hornung 		goto err;
7580cdd1155SAlex Hornung 
7590cdd1155SAlex Hornung 	if (!prop_dictionary_get_uint64(target_dict, DM_TABLE_LENGTH, &ulength))
7600cdd1155SAlex Hornung 		goto err;
7610cdd1155SAlex Hornung 
7620cdd1155SAlex Hornung 	*lengthp = (size_t)ulength;
7630cdd1155SAlex Hornung 
7640cdd1155SAlex Hornung 	/* If we are at the last element, make sure we return NULL */
7650cdd1155SAlex Hornung 	if (target_dict == prop_array_get(pa, count-1))
7660cdd1155SAlex Hornung 		goto err;
7670cdd1155SAlex Hornung 
7680cdd1155SAlex Hornung 	return (void *)iter;
7690cdd1155SAlex Hornung 	/* NOT REACHED */
7700cdd1155SAlex Hornung 
7710cdd1155SAlex Hornung err:
7720cdd1155SAlex Hornung 	if (iter != NULL)
7730cdd1155SAlex Hornung 		prop_object_iterator_release(iter);
7740cdd1155SAlex Hornung 
7750cdd1155SAlex Hornung 	return NULL;
7760cdd1155SAlex Hornung }
7770cdd1155SAlex Hornung 
7780cdd1155SAlex Hornung uint32_t
dm_get_major(void)7790cdd1155SAlex Hornung dm_get_major(void)
7800cdd1155SAlex Hornung {
7810cdd1155SAlex Hornung 	struct stat sb;
7820cdd1155SAlex Hornung 
7830cdd1155SAlex Hornung 	if (stat("/dev/mapper/control", &sb) < 0)
7840cdd1155SAlex Hornung 		return 0;
7850cdd1155SAlex Hornung 
7860cdd1155SAlex Hornung 	return (uint32_t)major(sb.st_dev);
7870cdd1155SAlex Hornung }
7880cdd1155SAlex Hornung 
7890cdd1155SAlex Hornung int
dm_is_dm_major(uint32_t major)7900cdd1155SAlex Hornung dm_is_dm_major(uint32_t major)
7910cdd1155SAlex Hornung {
7920cdd1155SAlex Hornung 	return (major == dm_get_major());
7930cdd1155SAlex Hornung }
7940cdd1155SAlex Hornung 
7950cdd1155SAlex Hornung const char *
dm_dir(void)7960cdd1155SAlex Hornung dm_dir(void)
7970cdd1155SAlex Hornung {
7980cdd1155SAlex Hornung 	return "/dev/mapper";
7990cdd1155SAlex Hornung }
8000cdd1155SAlex Hornung 
801*df3bdaafSAlex Hornung void
dm_udev_set_sync_support(int sync_udev __unused)802*df3bdaafSAlex Hornung dm_udev_set_sync_support(int sync_udev __unused)
803*df3bdaafSAlex Hornung {
804*df3bdaafSAlex Hornung 	return;
805*df3bdaafSAlex Hornung }
806*df3bdaafSAlex Hornung 
8070cdd1155SAlex Hornung int
dm_task_set_cookie(struct dm_task * dmt __unused,uint32_t * cookie __unused,uint16_t udev_flags __unused)8080cdd1155SAlex Hornung dm_task_set_cookie(struct dm_task *dmt __unused, uint32_t *cookie __unused,
8090cdd1155SAlex Hornung     uint16_t udev_flags __unused)
8100cdd1155SAlex Hornung {
8110cdd1155SAlex Hornung 	return 1;
8120cdd1155SAlex Hornung }
8130cdd1155SAlex Hornung 
8140cdd1155SAlex Hornung int
dm_udev_wait(uint32_t cookie __unused)8150cdd1155SAlex Hornung dm_udev_wait(uint32_t cookie __unused)
8160cdd1155SAlex Hornung {
8170cdd1155SAlex Hornung 	return 1;
8180cdd1155SAlex Hornung }
8190cdd1155SAlex Hornung 
8200cdd1155SAlex Hornung void
dm_lib_release(void)8210cdd1155SAlex Hornung dm_lib_release(void)
8220cdd1155SAlex Hornung {
8230cdd1155SAlex Hornung 	return;
8240cdd1155SAlex Hornung }
8250cdd1155SAlex Hornung 
8260cdd1155SAlex Hornung int
dm_log_init(dm_error_func_t fn)8270cdd1155SAlex Hornung dm_log_init(dm_error_func_t fn)
8280cdd1155SAlex Hornung {
8290cdd1155SAlex Hornung 	if (fn)
8300cdd1155SAlex Hornung 		dm_log = fn;
8310cdd1155SAlex Hornung 	return 1;
8320cdd1155SAlex Hornung }
8330cdd1155SAlex Hornung 
8340cdd1155SAlex Hornung int
dm_log_init_verbose(int verbose __unused)8350cdd1155SAlex Hornung dm_log_init_verbose(int verbose __unused)
8360cdd1155SAlex Hornung {
8370cdd1155SAlex Hornung 	return 1;
8380cdd1155SAlex Hornung }
8390cdd1155SAlex Hornung 
8400cdd1155SAlex Hornung /* XXX: unused in kernel */
8410cdd1155SAlex Hornung int
dm_task_set_uid(struct dm_task * dmt,uid_t uid)8420cdd1155SAlex Hornung dm_task_set_uid(struct dm_task *dmt, uid_t uid)
8430cdd1155SAlex Hornung {
8440cdd1155SAlex Hornung 	return prop_dictionary_set_uint32(dmt->dict, DM_DEV_UID,
8450cdd1155SAlex Hornung 	    (uint32_t)uid);
8460cdd1155SAlex Hornung }
8470cdd1155SAlex Hornung 
8480cdd1155SAlex Hornung int
dm_task_set_gid(struct dm_task * dmt,gid_t gid)8490cdd1155SAlex Hornung dm_task_set_gid(struct dm_task *dmt, gid_t gid)
8500cdd1155SAlex Hornung {
8510cdd1155SAlex Hornung 	return prop_dictionary_set_uint32(dmt->dict, DM_DEV_GID,
8520cdd1155SAlex Hornung 	    (uint32_t)gid);
8530cdd1155SAlex Hornung }
8540cdd1155SAlex Hornung 
8550cdd1155SAlex Hornung int
dm_task_set_mode(struct dm_task * dmt,mode_t mode)8560cdd1155SAlex Hornung dm_task_set_mode(struct dm_task *dmt, mode_t mode)
8570cdd1155SAlex Hornung {
8580cdd1155SAlex Hornung 	return prop_dictionary_set_uint32(dmt->dict, DM_DEV_MODE,
8590cdd1155SAlex Hornung 	    (uint32_t)mode);
8600cdd1155SAlex Hornung }
8610cdd1155SAlex Hornung 
8620cdd1155SAlex Hornung int
dm_task_no_flush(struct dm_task * dmt __unused)8630cdd1155SAlex Hornung dm_task_no_flush(struct dm_task *dmt __unused)
8640cdd1155SAlex Hornung {
8650cdd1155SAlex Hornung 	uint32_t flags = 0;
8660cdd1155SAlex Hornung 
8670cdd1155SAlex Hornung 	prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_FLAGS, &flags);
8680cdd1155SAlex Hornung 	flags |= DM_NOFLUSH_FLAG;
8690cdd1155SAlex Hornung 
8700cdd1155SAlex Hornung 	return prop_dictionary_set_uint32(dmt->dict, DM_IOCTL_FLAGS, flags);
8710cdd1155SAlex Hornung }
8720cdd1155SAlex Hornung 
8730cdd1155SAlex Hornung int
dm_task_skip_lockfs(struct dm_task * dmt __unused)8740cdd1155SAlex Hornung dm_task_skip_lockfs(struct dm_task *dmt __unused)
8750cdd1155SAlex Hornung {
8760cdd1155SAlex Hornung 	uint32_t flags = 0;
8770cdd1155SAlex Hornung 
8780cdd1155SAlex Hornung 	prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_FLAGS, &flags);
8790cdd1155SAlex Hornung 	flags |= DM_SKIP_LOCKFS_FLAG;
8800cdd1155SAlex Hornung 
8810cdd1155SAlex Hornung 	return prop_dictionary_set_uint32(dmt->dict, DM_IOCTL_FLAGS, flags);
8820cdd1155SAlex Hornung }
8830cdd1155SAlex Hornung 
dm_task_set_geometry(struct dm_task * dmt __unused,const char * cylinders __unused,const char * heads __unused,const char * sectors __unused,const char * start __unused)8840cdd1155SAlex Hornung int dm_task_set_geometry(struct dm_task *dmt __unused,
8850cdd1155SAlex Hornung     const char *cylinders __unused, const char *heads __unused,
8860cdd1155SAlex Hornung     const char *sectors __unused, const char *start __unused)
8870cdd1155SAlex Hornung {
8880cdd1155SAlex Hornung 	return 1;
8890cdd1155SAlex Hornung }
8900cdd1155SAlex Hornung 
8910cdd1155SAlex Hornung /*****************************************************************************/
8920cdd1155SAlex Hornung /********************** DragonFly-specific extensions ************************/
8930cdd1155SAlex Hornung /*****************************************************************************/
8940cdd1155SAlex Hornung void *
dm_get_next_version(struct dm_task * dmt,void * cur,const char ** target_type,uint32_t * target_ver)8950cdd1155SAlex Hornung dm_get_next_version(struct dm_task *dmt, void *cur, const char **target_type,
8960cdd1155SAlex Hornung     uint32_t *target_ver)
8970cdd1155SAlex Hornung {
8980cdd1155SAlex Hornung 	prop_object_iterator_t iter;
8990cdd1155SAlex Hornung 	prop_dictionary_t target_dict;
9000cdd1155SAlex Hornung 	prop_array_t pa, pa_ver;
9010cdd1155SAlex Hornung 	unsigned int count;
9020cdd1155SAlex Hornung 	int j;
9030cdd1155SAlex Hornung 
9040cdd1155SAlex Hornung 	if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
9050cdd1155SAlex Hornung 		return NULL;
9060cdd1155SAlex Hornung 
9070cdd1155SAlex Hornung 	count = prop_array_count(pa);
9080cdd1155SAlex Hornung 
9090cdd1155SAlex Hornung 	if (cur == NULL) {
9100cdd1155SAlex Hornung 		if ((iter = prop_array_iterator(pa)) == NULL)
9110cdd1155SAlex Hornung 			return NULL;
9120cdd1155SAlex Hornung 	} else {
9130cdd1155SAlex Hornung 		iter = (prop_object_iterator_t)cur;
9140cdd1155SAlex Hornung 	}
9150cdd1155SAlex Hornung 
9160cdd1155SAlex Hornung 	/* Get the next target dict */
9170cdd1155SAlex Hornung 	if ((target_dict = prop_object_iterator_next(iter)) == NULL) {
9180cdd1155SAlex Hornung 		/* If there are no more target dicts, release the iterator */
9190cdd1155SAlex Hornung 		goto err;
9200cdd1155SAlex Hornung 	}
9210cdd1155SAlex Hornung 
9220cdd1155SAlex Hornung 	if (!prop_dictionary_get_cstring_nocopy(target_dict, DM_TARGETS_NAME,
9230cdd1155SAlex Hornung 	    target_type))
9240cdd1155SAlex Hornung 		goto err;
9250cdd1155SAlex Hornung 
9260cdd1155SAlex Hornung 	if ((pa_ver = prop_dictionary_get(target_dict, DM_TARGETS_VERSION))
9270cdd1155SAlex Hornung 	    == NULL)
9280cdd1155SAlex Hornung 		goto err;
9290cdd1155SAlex Hornung 
9300cdd1155SAlex Hornung 	for (j = 0; j < 3; j++) {
9310cdd1155SAlex Hornung 		if (!prop_array_get_uint32(pa_ver, j, &target_ver[j]))
9320cdd1155SAlex Hornung 			goto err;
9330cdd1155SAlex Hornung 	}
9340cdd1155SAlex Hornung 
9350cdd1155SAlex Hornung 	/* If we are at the last element, make sure we return NULL */
9360cdd1155SAlex Hornung 	if (target_dict == prop_array_get(pa, count-1))
9370cdd1155SAlex Hornung 		goto err;
9380cdd1155SAlex Hornung 
9390cdd1155SAlex Hornung 	return (void *)iter;
9400cdd1155SAlex Hornung 	/* NOT REACHED */
9410cdd1155SAlex Hornung 
9420cdd1155SAlex Hornung err:
9430cdd1155SAlex Hornung 	if (iter != NULL)
9440cdd1155SAlex Hornung 		prop_object_iterator_release(iter);
9450cdd1155SAlex Hornung 
9460cdd1155SAlex Hornung 	return NULL;
9470cdd1155SAlex Hornung }
9480cdd1155SAlex Hornung 
9490cdd1155SAlex Hornung void *
dm_get_next_dep(struct dm_task * dmt,void * cur,uint64_t * dep)9500cdd1155SAlex Hornung dm_get_next_dep(struct dm_task *dmt, void *cur, uint64_t *dep)
9510cdd1155SAlex Hornung {
9520cdd1155SAlex Hornung 	prop_object_iterator_t iter;
9530cdd1155SAlex Hornung 	prop_object_t po;
9540cdd1155SAlex Hornung 	prop_array_t pa;
9550cdd1155SAlex Hornung 	unsigned int count;
9560cdd1155SAlex Hornung 
9570cdd1155SAlex Hornung 	*dep = 0;
9580cdd1155SAlex Hornung 
9590cdd1155SAlex Hornung 	if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
9600cdd1155SAlex Hornung 		return NULL;
9610cdd1155SAlex Hornung 
9620cdd1155SAlex Hornung 	count = prop_array_count(pa);
9630cdd1155SAlex Hornung 
9640cdd1155SAlex Hornung 	if (cur == NULL) {
9650cdd1155SAlex Hornung 		if ((iter = prop_array_iterator(pa)) == NULL)
9660cdd1155SAlex Hornung 			return NULL;
9670cdd1155SAlex Hornung 	} else {
9680cdd1155SAlex Hornung 		iter = (prop_object_iterator_t)cur;
9690cdd1155SAlex Hornung 	}
9700cdd1155SAlex Hornung 
9710cdd1155SAlex Hornung 	/* Get the next target dict */
9720cdd1155SAlex Hornung 	if ((po = prop_object_iterator_next(iter)) == NULL) {
9730cdd1155SAlex Hornung 		/* If there are no more target dicts, release the iterator */
9740cdd1155SAlex Hornung 		goto err;
9750cdd1155SAlex Hornung 	}
9760cdd1155SAlex Hornung 
9770cdd1155SAlex Hornung 	*dep = prop_number_unsigned_integer_value(po);
9780cdd1155SAlex Hornung 
9790cdd1155SAlex Hornung 	/* If we are at the last element, make sure we return NULL */
9800cdd1155SAlex Hornung 	if (po == prop_array_get(pa, count-1))
9810cdd1155SAlex Hornung 		goto err;
9820cdd1155SAlex Hornung 
9830cdd1155SAlex Hornung 	return (void *)iter;
9840cdd1155SAlex Hornung 	/* NOT REACHED */
9850cdd1155SAlex Hornung 
9860cdd1155SAlex Hornung err:
9870cdd1155SAlex Hornung 	if (iter != NULL)
9880cdd1155SAlex Hornung 		prop_object_iterator_release(iter);
9890cdd1155SAlex Hornung 
9900cdd1155SAlex Hornung 	return NULL;
9910cdd1155SAlex Hornung }
9920cdd1155SAlex Hornung 
9930cdd1155SAlex Hornung void *
dm_get_next_name(struct dm_task * dmt,void * cur,const char ** name,uint64_t * dev)9940cdd1155SAlex Hornung dm_get_next_name(struct dm_task *dmt, void *cur, const char **name,
9950cdd1155SAlex Hornung     uint64_t *dev)
9960cdd1155SAlex Hornung {
9970cdd1155SAlex Hornung 	prop_object_iterator_t iter;
9980cdd1155SAlex Hornung 	prop_dictionary_t devs_dict;
9990cdd1155SAlex Hornung 	prop_array_t pa;
10000cdd1155SAlex Hornung 	unsigned int count;
10010cdd1155SAlex Hornung 
10020cdd1155SAlex Hornung 	if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
10030cdd1155SAlex Hornung 		return NULL;
10040cdd1155SAlex Hornung 
10050cdd1155SAlex Hornung 	count = prop_array_count(pa);
10060cdd1155SAlex Hornung 
10070cdd1155SAlex Hornung 
10080cdd1155SAlex Hornung 	if (cur == NULL) {
10090cdd1155SAlex Hornung 		if ((iter = prop_array_iterator(pa)) == NULL)
10100cdd1155SAlex Hornung 			return NULL;
10110cdd1155SAlex Hornung 	} else {
10120cdd1155SAlex Hornung 		iter = (prop_object_iterator_t)cur;
10130cdd1155SAlex Hornung 	}
10140cdd1155SAlex Hornung 
10150cdd1155SAlex Hornung 	/* Get the next dev dict */
10160cdd1155SAlex Hornung 	if ((devs_dict = prop_object_iterator_next(iter)) == NULL) {
10170cdd1155SAlex Hornung 		/* If there are no more dev dicts, release the iterator */
10180cdd1155SAlex Hornung 		goto err;
10190cdd1155SAlex Hornung 	}
10200cdd1155SAlex Hornung 
10210cdd1155SAlex Hornung 	if (!prop_dictionary_get_cstring_nocopy(devs_dict, DM_DEV_NAME, name))
10220cdd1155SAlex Hornung 		goto err;
10230cdd1155SAlex Hornung 
10240cdd1155SAlex Hornung 	if (!prop_dictionary_get_uint64(devs_dict, DM_DEV_DEV, dev))
10250cdd1155SAlex Hornung 		goto err;
10260cdd1155SAlex Hornung 
10270cdd1155SAlex Hornung 	/* If we are at the last element, make sure we return NULL */
10280cdd1155SAlex Hornung 	if (devs_dict == prop_array_get(pa, count-1))
10290cdd1155SAlex Hornung 		goto err;
10300cdd1155SAlex Hornung 
10310cdd1155SAlex Hornung 	return (void *)iter;
10320cdd1155SAlex Hornung 	/* NOT REACHED */
10330cdd1155SAlex Hornung 
10340cdd1155SAlex Hornung err:
10350cdd1155SAlex Hornung 	if (iter != NULL)
10360cdd1155SAlex Hornung 		prop_object_iterator_release(iter);
10370cdd1155SAlex Hornung 
10380cdd1155SAlex Hornung 	return NULL;
10390cdd1155SAlex Hornung 
10400cdd1155SAlex Hornung }
1041