usched: Allow process to change self cpu affinity
[dragonfly.git] / lib / libdm / dm_task.c
blobcbe2be5b9dd5b9da40f48d8c5deea5c09c1ff899
1 /*
2 * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
3 * All rights reserved.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Adam Hamsik.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/ioctl.h>
35 #include <sys/stat.h>
36 #include <machine/inttypes.h>
37 #include <dev/disk/dm/netbsd-dm.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <stdio.h>
41 #include <unistd.h>
42 #include <fcntl.h>
43 #include <errno.h>
45 #include <libprop/proplib.h>
46 #include "libdm.h"
48 struct dm_task {
49 int task_type;
50 int was_enoent;
51 prop_dictionary_t dict;
52 void *data_buffer;
55 struct dm_cmd {
56 int task_type;
57 const char *dm_cmd;
58 uint32_t cmd_version[3];
61 struct dm_cmd dm_cmds[] = {
62 { DM_DEVICE_REMOVE, "remove", {4, 0, 0} },
63 { DM_DEVICE_REMOVE_ALL, "remove_all", {4, 0, 0} },
64 { DM_DEVICE_CREATE, "create", {4, 0, 0} },
65 { DM_DEVICE_RELOAD, "reload", {4, 0, 0} },
66 { DM_DEVICE_RESUME, "resume", {4, 0, 0} },
67 { DM_DEVICE_SUSPEND, "suspend", {4, 0, 0} },
68 { DM_DEVICE_CLEAR, "clear", {4, 0, 0} },
69 { DM_DEVICE_LIST_VERSIONS, "targets", {4, 1, 0} },
70 { DM_DEVICE_STATUS, "status", {4, 0, 0} },
71 { DM_DEVICE_TABLE, "table", {4, 0, 0} },
72 { DM_DEVICE_INFO, "info", {4, 0, 0} },
73 { DM_DEVICE_DEPS, "deps", {4, 0, 0} },
74 { DM_DEVICE_VERSION, "version", {4, 0, 0} },
75 { DM_DEVICE_TARGET_MSG, "message", {4, 2, 0} },
76 { DM_DEVICE_RENAME, "rename", {4, 0, 0} },
77 { DM_DEVICE_LIST, "names", {4, 0, 0} },
78 { 0, NULL, {0, 0, 0} }
81 #define _LOG_DEBUG 0
82 #define _LOG_WARN 5
83 #define _LOG_ERR 10
85 static void _stderr_log(int level, const char *file,
86 int line, const char *fmt, ...)
88 const char *prefix;
89 __va_list ap;
91 switch (level) {
92 case _LOG_DEBUG:
93 prefix = "debug: ";
94 break;
95 case _LOG_WARN:
96 prefix = "warning: ";
97 break;
98 case _LOG_ERR:
99 prefix = "error: ";
100 break;
101 default:
102 prefix = "";
105 fprintf(stderr, "libdm %s:%d: ", file, line);
106 fprintf(stderr, "%s", prefix);
108 __va_start(ap, fmt);
109 vfprintf(stderr, fmt, ap);
110 __va_end(ap);
112 fprintf(stderr, "\n");
114 return;
117 static dm_error_func_t dm_log = _stderr_log;
119 struct dm_task *
120 dm_task_create(int task_type)
122 struct dm_task *dmt;
123 struct dm_cmd *cmd = NULL;
124 const char *task_cmd = NULL;
125 prop_array_t pa;
126 uint32_t flags = DM_EXISTS_FLAG;
127 int i;
129 for (i = 0; dm_cmds[i].dm_cmd != NULL; i++) {
130 if (dm_cmds[i].task_type == task_type) {
131 cmd = &dm_cmds[i];
132 task_cmd = dm_cmds[i].dm_cmd;
133 break;
137 if (task_cmd == NULL)
138 return NULL;
140 if (task_type == DM_DEVICE_TABLE)
141 flags |= DM_STATUS_TABLE_FLAG;
143 if (task_type == DM_DEVICE_SUSPEND)
144 flags |= DM_SUSPEND_FLAG;
146 if ((dmt = malloc(sizeof(*dmt))) == NULL)
147 return NULL;
149 memset(dmt, 0, sizeof(*dmt));
151 dmt->task_type = task_type;
152 dmt->was_enoent = 0;
154 if ((dmt->dict = prop_dictionary_create()) == NULL)
155 goto err;
157 if ((pa = prop_array_create_with_capacity(3)) == NULL)
158 goto err;
160 if (!prop_array_add_uint32(pa, cmd->cmd_version[0])) {
161 prop_object_release(pa);
162 goto err;
165 if (!prop_array_add_uint32(pa, cmd->cmd_version[1])) {
166 prop_object_release(pa);
167 goto err;
170 if (!prop_array_add_uint32(pa, cmd->cmd_version[2])) {
171 prop_object_release(pa);
172 goto err;
175 if (!prop_dictionary_set(dmt->dict, DM_IOCTL_VERSION, pa)) {
176 prop_object_release(pa);
177 goto err;
180 prop_object_release(pa);
182 if (!prop_dictionary_set_cstring(dmt->dict, DM_IOCTL_COMMAND,
183 task_cmd))
184 goto err;
186 if (!prop_dictionary_set_uint32(dmt->dict, DM_IOCTL_FLAGS, flags))
187 goto err;
189 if ((pa = prop_array_create_with_capacity(5)) == NULL)
190 goto err;
192 if (!prop_dictionary_set(dmt->dict, DM_IOCTL_CMD_DATA, pa)) {
193 prop_object_release(pa);
194 goto err;
197 prop_object_release(pa);
199 return dmt;
200 /* NOT REACHED */
202 err:
203 if (dmt->dict != NULL)
204 prop_object_release(dmt->dict);
205 if (dmt)
206 free(dmt);
208 return NULL;
212 void
213 dm_task_destroy(struct dm_task *dmt)
215 if (dmt) {
216 if (dmt->data_buffer)
217 free(dmt->data_buffer);
219 if (dmt->dict) {
220 prop_object_release(dmt->dict);
221 dmt->dict = NULL;
224 free(dmt);
229 dm_task_run(struct dm_task *dmt)
231 struct dm_task *dmt_internal = NULL;
232 prop_dictionary_t ret_pd = NULL;
233 prop_array_t pa;
234 int error;
235 int fd;
236 int need_unroll = 0;
238 if ((fd = open("/dev/mapper/control", O_RDWR)) < -1)
239 goto err;
241 pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA);
242 if ((dmt->task_type == DM_DEVICE_CREATE) && (pa != NULL) &&
243 (prop_array_count(pa) > 0)) {
245 * Magic to separate a combined DM_DEVICE_CREATE+RELOAD int
246 * a DM_DEVICE_CREATE and a RELOAD with target table.
249 if ((dmt_internal = dm_task_create(DM_DEVICE_CREATE)) == NULL)
250 goto err;
251 if (!dm_task_set_name(dmt_internal, dm_task_get_name(dmt)))
252 goto err;
253 if (!dm_task_set_uuid(dmt_internal, dm_task_get_uuid(dmt)))
254 goto err;
255 if (!dm_task_run(dmt_internal))
256 goto err;
257 dm_task_destroy(dmt_internal);
258 dmt_internal = NULL;
260 if (!prop_dictionary_set_cstring_nocopy(dmt->dict,
261 DM_IOCTL_COMMAND, "reload"))
262 goto unroll;
263 dmt->task_type = DM_DEVICE_RELOAD;
264 if ((error = prop_dictionary_sendrecv_ioctl(dmt->dict, fd,
265 NETBSD_DM_IOCTL, &ret_pd)) != 0) {
266 dm_log(_LOG_ERR, __FILE__, __LINE__, "ioctl failed: %d",
267 error);
268 goto unroll;
271 if (!prop_dictionary_set_cstring_nocopy(dmt->dict,
272 DM_IOCTL_COMMAND, "resume"))
273 goto unroll;
274 dmt->task_type = DM_DEVICE_RESUME;
275 /* Remove superfluous stuff */
276 prop_dictionary_remove(dmt->dict, DM_IOCTL_CMD_DATA);
278 need_unroll = 1;
281 if ((error = prop_dictionary_sendrecv_ioctl(dmt->dict, fd,
282 NETBSD_DM_IOCTL, &ret_pd)) != 0) {
283 if (((error == ENOENT) &&
284 ((dmt->task_type == DM_DEVICE_INFO) ||
285 (dmt->task_type == DM_DEVICE_STATUS)))) {
286 dmt->was_enoent = 1;
287 ret_pd = NULL;
288 } else {
289 dm_log(_LOG_ERR, __FILE__, __LINE__, "ioctl failed: %d",
290 error);
291 if (need_unroll)
292 goto unroll;
293 else
294 goto err;
298 if (ret_pd)
299 prop_object_retain(ret_pd);
301 prop_object_release(dmt->dict);
302 dmt->dict = ret_pd;
304 return 1;
305 /* NOT REACHED */
307 unroll:
308 prop_dictionary_remove(dmt->dict, DM_IOCTL_CMD_DATA);
310 if (!prop_dictionary_set_cstring_nocopy(dmt->dict, DM_IOCTL_COMMAND,
311 "remove")) {
312 dm_log(_LOG_ERR, __FILE__, __LINE__, "couldn't unroll changes "
313 "in dm_task_run");
314 goto err;
317 if ((error = prop_dictionary_sendrecv_ioctl(dmt->dict, fd,
318 NETBSD_DM_IOCTL, &ret_pd)) != 0) {
319 dm_log(_LOG_ERR, __FILE__, __LINE__, "ioctl failed: %d",
320 error);
321 goto unroll;
323 dmt->task_type = DM_DEVICE_REMOVE;
324 dm_task_run(dmt);
326 err:
327 if (fd >= 0)
328 close(fd);
330 if (dmt_internal)
331 dm_task_destroy(dmt_internal);
333 return 0;
337 dm_task_set_name(struct dm_task *dmt, const char *name)
339 return prop_dictionary_set_cstring(dmt->dict, DM_IOCTL_NAME,
340 __DECONST(char *, name));
344 const char *
345 dm_task_get_name(struct dm_task *dmt)
347 const char *name = NULL;
349 prop_dictionary_get_cstring_nocopy(dmt->dict, DM_IOCTL_NAME, &name);
351 return name;
355 dm_task_set_newname(struct dm_task *dmt, const char *newname)
357 return prop_dictionary_set_cstring(dmt->dict, DM_DEV_NEWNAME,
358 __DECONST(char *, newname));
362 dm_task_set_major(struct dm_task *dmt __unused, int major __unused)
364 return 1;
368 dm_task_set_minor(struct dm_task *dmt, int minor)
370 return prop_dictionary_set_int32(dmt->dict, DM_IOCTL_MINOR, minor);
374 dm_task_get_minor(struct dm_task *dmt)
376 int minor = 0;
378 minor = prop_dictionary_get_int32(dmt->dict, DM_IOCTL_MINOR, &minor);
380 return minor;
384 dm_task_set_uuid(struct dm_task *dmt, const char *uuid)
386 return prop_dictionary_set_cstring(dmt->dict, DM_IOCTL_UUID,
387 __DECONST(char *,uuid));
390 const char *
391 dm_task_get_uuid(struct dm_task *dmt)
393 const char *uuid = NULL;
395 prop_dictionary_get_cstring_nocopy(dmt->dict, DM_IOCTL_UUID, &uuid);
397 return uuid;
401 dm_task_add_target(struct dm_task *dmt, uint64_t start, size_t size,
402 const char *target, const char *params)
404 prop_dictionary_t target_dict = NULL;
405 prop_array_t pa = NULL;
407 if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
408 return 0;
410 if ((target_dict = prop_dictionary_create()) == NULL)
411 return 0;
413 if (!prop_dictionary_set_uint64(target_dict, DM_TABLE_START, start))
414 goto err;
416 if (!prop_dictionary_set_uint64(target_dict, DM_TABLE_LENGTH, size))
417 goto err;
419 if (!prop_dictionary_set_cstring(target_dict, DM_TABLE_TYPE, target))
420 goto err;
422 if (!prop_dictionary_set_cstring(target_dict, DM_TABLE_PARAMS, params))
423 goto err;
425 if (!prop_array_add(pa, target_dict))
426 goto err;
428 prop_object_release(target_dict);
430 return 1;
431 /* NOT REACHED */
433 err:
434 prop_object_release(target_dict);
435 return 0;
439 dm_task_set_sector(struct dm_task *dmt, uint64_t sector)
441 return prop_dictionary_set_uint64(dmt->dict, DM_MESSAGE_SECTOR,
442 sector);
446 dm_task_set_message(struct dm_task *dmt, const char *msg)
448 return prop_dictionary_set_cstring(dmt->dict, DM_MESSAGE_STR, msg);
452 dm_task_set_ro(struct dm_task *dmt)
454 uint32_t flags = 0;
456 prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_FLAGS, &flags);
457 flags |= DM_READONLY_FLAG;
459 return prop_dictionary_set_uint32(dmt->dict, DM_IOCTL_FLAGS, flags);
463 dm_task_no_open_count(struct dm_task *dmt __unused)
466 * nothing else needed, since we don't have performance problems when
467 * getting the open count.
469 return 1;
473 dm_task_query_inactive_table(struct dm_task *dmt)
475 uint32_t flags = 0;
477 prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_FLAGS, &flags);
478 flags |= DM_QUERY_INACTIVE_TABLE_FLAG;
480 return prop_dictionary_set_uint32(dmt->dict, DM_IOCTL_FLAGS, flags);
484 dm_task_set_read_ahead(struct dm_task *dmt __unused,
485 uint32_t read_ahead __unused)
487 /* We don't support readahead */
488 return 1;
492 dm_task_get_read_ahead(struct dm_task *dmt __unused, uint32_t *read_ahead)
494 *read_ahead = 0;
496 return 1;
500 dm_task_secure_data(struct dm_task *dmt)
502 /* XXX: needs kernel support */
503 uint32_t flags = 0;
505 prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_FLAGS, &flags);
506 flags |= DM_SECURE_DATA_FLAG;
508 return prop_dictionary_set_uint32(dmt->dict, DM_IOCTL_FLAGS, flags);
512 dm_task_get_info(struct dm_task *dmt, struct dm_info *dmi)
514 uint32_t flags = 0;
516 memset(dmi, 0, sizeof(struct dm_info));
518 /* Hack due to the way Linux dm works */
519 if (dmt->was_enoent) {
520 dmi->exists = 0;
521 return 1;
522 /* NOT REACHED */
525 if (!prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_FLAGS,
526 &flags))
527 return 0;
529 prop_dictionary_get_int32(dmt->dict, DM_IOCTL_OPEN, &dmi->open_count);
531 prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_TARGET_COUNT,
532 &dmi->target_count);
534 prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_EVENT, &dmi->event_nr);
536 prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_MINOR, &dmi->minor);
538 dmi->major = dm_get_major();
540 dmi->read_only = (flags & DM_READONLY_FLAG);
541 dmi->exists = (flags & DM_EXISTS_FLAG);
542 dmi->suspended = (flags & DM_SUSPEND_FLAG);
543 dmi->live_table = (flags & DM_ACTIVE_PRESENT_FLAG);
544 dmi->inactive_table = (flags & DM_INACTIVE_PRESENT_FLAG);
546 return 1;
550 dm_task_get_driver_version(struct dm_task *dmt, char *ver, size_t ver_sz)
552 prop_array_t pa_ver;
553 uint32_t maj = 0, min = 0, patch = 0;
555 if ((pa_ver = prop_dictionary_get(dmt->dict, DM_IOCTL_VERSION)) == NULL)
556 return 0;
558 if (!prop_array_get_uint32(pa_ver, 0, &maj))
559 return 0;
561 if (!prop_array_get_uint32(pa_ver, 1, &min))
562 return 0;
564 if (!prop_array_get_uint32(pa_ver, 2, &patch))
565 return 0;
567 snprintf(ver, ver_sz, "%u.%u.%u", maj, min, patch);
569 return 1;
572 struct dm_deps *
573 dm_task_get_deps(struct dm_task *dmt)
575 prop_object_iterator_t iter;
576 prop_array_t pa;
577 prop_object_t po;
578 struct dm_deps *deps;
580 unsigned int count;
581 int i;
583 if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
584 return NULL;
586 count = prop_array_count(pa);
588 if (dmt->data_buffer != NULL)
589 free(dmt->data_buffer);
591 if ((dmt->data_buffer = malloc(sizeof(struct dm_deps) +
592 (count * sizeof(uint64_t)))) == NULL)
593 return NULL;
595 if ((iter = prop_array_iterator(pa)) == NULL)
596 return NULL;
598 deps = (struct dm_deps *)dmt->data_buffer;
599 memset(deps, 0, sizeof(struct dm_deps) + (count * sizeof(uint64_t)));
600 i = 0;
601 while ((po = prop_object_iterator_next(iter)) != NULL)
602 deps->deps[i++] = prop_number_unsigned_integer_value(po);
604 deps->count = (uint32_t)count;
606 prop_object_iterator_release(iter);
608 return deps;
611 struct dm_versions *
612 dm_task_get_versions(struct dm_task *dmt)
614 prop_object_iterator_t iter;
615 prop_dictionary_t target_dict;
616 prop_array_t pa, pa_ver;
617 struct dm_versions *vers;
619 unsigned int count;
620 int i, j;
622 if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
623 return NULL;
625 count = prop_array_count(pa);
627 if (dmt->data_buffer != NULL)
628 free(dmt->data_buffer);
630 if ((dmt->data_buffer = malloc(sizeof(struct dm_versions) * count))
631 == NULL)
632 return NULL;
634 if ((iter = prop_array_iterator(pa)) == NULL)
635 return NULL;
637 vers = (struct dm_versions *)dmt->data_buffer;
638 memset(vers, 0, sizeof(struct dm_versions) * count);
639 i = 0;
640 while ((target_dict = prop_object_iterator_next(iter)) != NULL) {
641 vers[i].next = sizeof(struct dm_versions);
642 prop_dictionary_get_cstring_nocopy(target_dict,
643 DM_TARGETS_NAME, &vers[i].name);
645 pa_ver = prop_dictionary_get(target_dict, DM_TARGETS_VERSION);
646 for (j = 0; j < 3; j++)
647 prop_array_get_uint32(pa_ver, j, &vers[i].version[j]);
649 ++i;
652 /* Finish the array */
653 vers[i-1].next = 0;
655 prop_object_iterator_release(iter);
657 return (struct dm_versions *)dmt->data_buffer;
660 struct dm_names *
661 dm_task_get_names(struct dm_task *dmt)
663 prop_object_iterator_t iter;
664 prop_dictionary_t devs_dict;
665 prop_array_t pa;
666 struct dm_names *names;
668 unsigned int count;
669 int i;
671 if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
672 return NULL;
674 count = prop_array_count(pa);
676 if (dmt->data_buffer != NULL)
677 free(dmt->data_buffer);
679 if ((dmt->data_buffer = malloc(sizeof(struct dm_names) * count))
680 == NULL)
681 return NULL;
683 if ((iter = prop_array_iterator(pa)) == NULL)
684 return NULL;
686 names = (struct dm_names *)dmt->data_buffer;
687 memset(names, 0, sizeof(struct dm_names) * count);
688 i = 0;
689 while ((devs_dict = prop_object_iterator_next(iter)) != NULL) {
690 names[i].next = sizeof(struct dm_names);
692 prop_dictionary_get_cstring_nocopy(devs_dict,
693 DM_DEV_NAME, &names[i].name);
695 prop_dictionary_get_uint64(devs_dict, DM_DEV_DEV,
696 &names[i].dev);
698 ++i;
701 /* Finish the array */
702 names[i-1].next = 0;
704 prop_object_iterator_release(iter);
706 return (struct dm_names *)dmt->data_buffer;
710 dm_task_update_nodes(void)
713 /* nothing else needed */
714 return 1;
717 void *
718 dm_get_next_target(struct dm_task *dmt, void *cur, uint64_t *startp,
719 uint64_t *lengthp, char **target_type, char **params)
721 prop_object_iterator_t iter;
722 prop_dictionary_t target_dict;
723 prop_array_t pa;
724 uint64_t ulength;
725 unsigned int count;
727 if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
728 return NULL;
730 count = prop_array_count(pa);
732 if (cur == NULL) {
733 if ((iter = prop_array_iterator(pa)) == NULL)
734 return NULL;
735 } else {
736 iter = (prop_object_iterator_t)cur;
739 /* Get the next target dict */
740 if ((target_dict = prop_object_iterator_next(iter)) == NULL) {
741 /* If there are no more target dicts, release the iterator */
742 goto err;
745 if (!prop_dictionary_get_cstring_nocopy(target_dict, DM_TABLE_TYPE,
746 (const char **)target_type))
747 goto err;
750 * Ugly __DECONST and (const char **) casts due to the linux prototype
751 * of this function.
753 *params = __DECONST(char *, "");
754 prop_dictionary_get_cstring_nocopy(target_dict, DM_TABLE_PARAMS,
755 (const char **)params);
757 if (!prop_dictionary_get_uint64(target_dict, DM_TABLE_START, startp))
758 goto err;
760 if (!prop_dictionary_get_uint64(target_dict, DM_TABLE_LENGTH, &ulength))
761 goto err;
763 *lengthp = (size_t)ulength;
765 /* If we are at the last element, make sure we return NULL */
766 if (target_dict == prop_array_get(pa, count-1))
767 goto err;
769 return (void *)iter;
770 /* NOT REACHED */
772 err:
773 if (iter != NULL)
774 prop_object_iterator_release(iter);
776 return NULL;
779 uint32_t
780 dm_get_major(void)
782 struct stat sb;
784 if (stat("/dev/mapper/control", &sb) < 0)
785 return 0;
787 return (uint32_t)major(sb.st_dev);
791 dm_is_dm_major(uint32_t major)
793 return (major == dm_get_major());
796 const char *
797 dm_dir(void)
799 return "/dev/mapper";
802 void
803 dm_udev_set_sync_support(int sync_udev __unused)
805 return;
809 dm_task_set_cookie(struct dm_task *dmt __unused, uint32_t *cookie __unused,
810 uint16_t udev_flags __unused)
812 return 1;
816 dm_udev_wait(uint32_t cookie __unused)
818 return 1;
821 void
822 dm_lib_release(void)
824 return;
828 dm_log_init(dm_error_func_t fn)
830 if (fn)
831 dm_log = fn;
832 return 1;
836 dm_log_init_verbose(int verbose __unused)
838 return 1;
841 /* XXX: unused in kernel */
843 dm_task_set_uid(struct dm_task *dmt, uid_t uid)
845 return prop_dictionary_set_uint32(dmt->dict, DM_DEV_UID,
846 (uint32_t)uid);
850 dm_task_set_gid(struct dm_task *dmt, gid_t gid)
852 return prop_dictionary_set_uint32(dmt->dict, DM_DEV_GID,
853 (uint32_t)gid);
857 dm_task_set_mode(struct dm_task *dmt, mode_t mode)
859 return prop_dictionary_set_uint32(dmt->dict, DM_DEV_MODE,
860 (uint32_t)mode);
864 dm_task_no_flush(struct dm_task *dmt __unused)
866 uint32_t flags = 0;
868 prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_FLAGS, &flags);
869 flags |= DM_NOFLUSH_FLAG;
871 return prop_dictionary_set_uint32(dmt->dict, DM_IOCTL_FLAGS, flags);
875 dm_task_skip_lockfs(struct dm_task *dmt __unused)
877 uint32_t flags = 0;
879 prop_dictionary_get_uint32(dmt->dict, DM_IOCTL_FLAGS, &flags);
880 flags |= DM_SKIP_LOCKFS_FLAG;
882 return prop_dictionary_set_uint32(dmt->dict, DM_IOCTL_FLAGS, flags);
885 int dm_task_set_geometry(struct dm_task *dmt __unused,
886 const char *cylinders __unused, const char *heads __unused,
887 const char *sectors __unused, const char *start __unused)
889 return 1;
892 /*****************************************************************************/
893 /********************** DragonFly-specific extensions ************************/
894 /*****************************************************************************/
895 void *
896 dm_get_next_version(struct dm_task *dmt, void *cur, const char **target_type,
897 uint32_t *target_ver)
899 prop_object_iterator_t iter;
900 prop_dictionary_t target_dict;
901 prop_array_t pa, pa_ver;
902 unsigned int count;
903 int j;
905 if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
906 return NULL;
908 count = prop_array_count(pa);
910 if (cur == NULL) {
911 if ((iter = prop_array_iterator(pa)) == NULL)
912 return NULL;
913 } else {
914 iter = (prop_object_iterator_t)cur;
917 /* Get the next target dict */
918 if ((target_dict = prop_object_iterator_next(iter)) == NULL) {
919 /* If there are no more target dicts, release the iterator */
920 goto err;
923 if (!prop_dictionary_get_cstring_nocopy(target_dict, DM_TARGETS_NAME,
924 target_type))
925 goto err;
927 if ((pa_ver = prop_dictionary_get(target_dict, DM_TARGETS_VERSION))
928 == NULL)
929 goto err;
931 for (j = 0; j < 3; j++) {
932 if (!prop_array_get_uint32(pa_ver, j, &target_ver[j]))
933 goto err;
936 /* If we are at the last element, make sure we return NULL */
937 if (target_dict == prop_array_get(pa, count-1))
938 goto err;
940 return (void *)iter;
941 /* NOT REACHED */
943 err:
944 if (iter != NULL)
945 prop_object_iterator_release(iter);
947 return NULL;
950 void *
951 dm_get_next_dep(struct dm_task *dmt, void *cur, uint64_t *dep)
953 prop_object_iterator_t iter;
954 prop_object_t po;
955 prop_array_t pa;
956 unsigned int count;
958 *dep = 0;
960 if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
961 return NULL;
963 count = prop_array_count(pa);
965 if (cur == NULL) {
966 if ((iter = prop_array_iterator(pa)) == NULL)
967 return NULL;
968 } else {
969 iter = (prop_object_iterator_t)cur;
972 /* Get the next target dict */
973 if ((po = prop_object_iterator_next(iter)) == NULL) {
974 /* If there are no more target dicts, release the iterator */
975 goto err;
978 *dep = prop_number_unsigned_integer_value(po);
980 /* If we are at the last element, make sure we return NULL */
981 if (po == prop_array_get(pa, count-1))
982 goto err;
984 return (void *)iter;
985 /* NOT REACHED */
987 err:
988 if (iter != NULL)
989 prop_object_iterator_release(iter);
991 return NULL;
994 void *
995 dm_get_next_name(struct dm_task *dmt, void *cur, const char **name,
996 uint64_t *dev)
998 prop_object_iterator_t iter;
999 prop_dictionary_t devs_dict;
1000 prop_array_t pa;
1001 unsigned int count;
1003 if ((pa = prop_dictionary_get(dmt->dict, DM_IOCTL_CMD_DATA)) == NULL)
1004 return NULL;
1006 count = prop_array_count(pa);
1009 if (cur == NULL) {
1010 if ((iter = prop_array_iterator(pa)) == NULL)
1011 return NULL;
1012 } else {
1013 iter = (prop_object_iterator_t)cur;
1016 /* Get the next dev dict */
1017 if ((devs_dict = prop_object_iterator_next(iter)) == NULL) {
1018 /* If there are no more dev dicts, release the iterator */
1019 goto err;
1022 if (!prop_dictionary_get_cstring_nocopy(devs_dict, DM_DEV_NAME, name))
1023 goto err;
1025 if (!prop_dictionary_get_uint64(devs_dict, DM_DEV_DEV, dev))
1026 goto err;
1028 /* If we are at the last element, make sure we return NULL */
1029 if (devs_dict == prop_array_get(pa, count-1))
1030 goto err;
1032 return (void *)iter;
1033 /* NOT REACHED */
1035 err:
1036 if (iter != NULL)
1037 prop_object_iterator_release(iter);
1039 return NULL;