2 * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
5 * This code is derived from software contributed to The NetBSD Foundation
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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
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
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/ioctl.h>
36 #include <machine/inttypes.h>
37 #include <dev/disk/dm/netbsd-dm.h>
45 #include <libprop/proplib.h>
51 prop_dictionary_t dict
;
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} }
85 static void _stderr_log(int level
, const char *file
,
86 int line
, const char *fmt
, ...)
105 fprintf(stderr
, "libdm %s:%d: ", file
, line
);
106 fprintf(stderr
, "%s", prefix
);
109 vfprintf(stderr
, fmt
, ap
);
112 fprintf(stderr
, "\n");
117 static dm_error_func_t dm_log
= _stderr_log
;
120 dm_task_create(int task_type
)
123 struct dm_cmd
*cmd
= NULL
;
124 const char *task_cmd
= NULL
;
126 uint32_t flags
= DM_EXISTS_FLAG
;
129 for (i
= 0; dm_cmds
[i
].dm_cmd
!= NULL
; i
++) {
130 if (dm_cmds
[i
].task_type
== task_type
) {
132 task_cmd
= dm_cmds
[i
].dm_cmd
;
137 if (task_cmd
== 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
)
149 memset(dmt
, 0, sizeof(*dmt
));
151 dmt
->task_type
= task_type
;
154 if ((dmt
->dict
= prop_dictionary_create()) == NULL
)
157 if ((pa
= prop_array_create_with_capacity(3)) == NULL
)
160 if (!prop_array_add_uint32(pa
, cmd
->cmd_version
[0])) {
161 prop_object_release(pa
);
165 if (!prop_array_add_uint32(pa
, cmd
->cmd_version
[1])) {
166 prop_object_release(pa
);
170 if (!prop_array_add_uint32(pa
, cmd
->cmd_version
[2])) {
171 prop_object_release(pa
);
175 if (!prop_dictionary_set(dmt
->dict
, DM_IOCTL_VERSION
, pa
)) {
176 prop_object_release(pa
);
180 prop_object_release(pa
);
182 if (!prop_dictionary_set_cstring(dmt
->dict
, DM_IOCTL_COMMAND
,
186 if (!prop_dictionary_set_uint32(dmt
->dict
, DM_IOCTL_FLAGS
, flags
))
189 if ((pa
= prop_array_create_with_capacity(5)) == NULL
)
192 if (!prop_dictionary_set(dmt
->dict
, DM_IOCTL_CMD_DATA
, pa
)) {
193 prop_object_release(pa
);
197 prop_object_release(pa
);
203 if (dmt
->dict
!= NULL
)
204 prop_object_release(dmt
->dict
);
213 dm_task_destroy(struct dm_task
*dmt
)
216 if (dmt
->data_buffer
)
217 free(dmt
->data_buffer
);
220 prop_object_release(dmt
->dict
);
229 dm_task_run(struct dm_task
*dmt
)
231 struct dm_task
*dmt_internal
= NULL
;
232 prop_dictionary_t ret_pd
= NULL
;
238 if ((fd
= open("/dev/mapper/control", O_RDWR
)) < -1)
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
)
251 if (!dm_task_set_name(dmt_internal
, dm_task_get_name(dmt
)))
253 if (!dm_task_set_uuid(dmt_internal
, dm_task_get_uuid(dmt
)))
255 if (!dm_task_run(dmt_internal
))
257 dm_task_destroy(dmt_internal
);
260 if (!prop_dictionary_set_cstring_nocopy(dmt
->dict
,
261 DM_IOCTL_COMMAND
, "reload"))
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",
271 if (!prop_dictionary_set_cstring_nocopy(dmt
->dict
,
272 DM_IOCTL_COMMAND
, "resume"))
274 dmt
->task_type
= DM_DEVICE_RESUME
;
275 /* Remove superfluous stuff */
276 prop_dictionary_remove(dmt
->dict
, DM_IOCTL_CMD_DATA
);
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
)))) {
289 dm_log(_LOG_ERR
, __FILE__
, __LINE__
, "ioctl failed: %d",
299 prop_object_retain(ret_pd
);
301 prop_object_release(dmt
->dict
);
308 prop_dictionary_remove(dmt
->dict
, DM_IOCTL_CMD_DATA
);
310 if (!prop_dictionary_set_cstring_nocopy(dmt
->dict
, DM_IOCTL_COMMAND
,
312 dm_log(_LOG_ERR
, __FILE__
, __LINE__
, "couldn't unroll changes "
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",
323 dmt
->task_type
= DM_DEVICE_REMOVE
;
331 dm_task_destroy(dmt_internal
);
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
));
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
);
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
)
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
)
378 minor
= prop_dictionary_get_int32(dmt
->dict
, DM_IOCTL_MINOR
, &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
));
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
);
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
)
410 if ((target_dict
= prop_dictionary_create()) == NULL
)
413 if (!prop_dictionary_set_uint64(target_dict
, DM_TABLE_START
, start
))
416 if (!prop_dictionary_set_uint64(target_dict
, DM_TABLE_LENGTH
, size
))
419 if (!prop_dictionary_set_cstring(target_dict
, DM_TABLE_TYPE
, target
))
422 if (!prop_dictionary_set_cstring(target_dict
, DM_TABLE_PARAMS
, params
))
425 if (!prop_array_add(pa
, target_dict
))
428 prop_object_release(target_dict
);
434 prop_object_release(target_dict
);
439 dm_task_set_sector(struct dm_task
*dmt
, uint64_t sector
)
441 return prop_dictionary_set_uint64(dmt
->dict
, DM_MESSAGE_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
)
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.
473 dm_task_query_inactive_table(struct dm_task
*dmt
)
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 */
492 dm_task_get_read_ahead(struct dm_task
*dmt __unused
, uint32_t *read_ahead
)
500 dm_task_secure_data(struct dm_task
*dmt
)
502 /* XXX: needs kernel support */
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
)
516 memset(dmi
, 0, sizeof(struct dm_info
));
518 /* Hack due to the way Linux dm works */
519 if (dmt
->was_enoent
) {
525 if (!prop_dictionary_get_uint32(dmt
->dict
, DM_IOCTL_FLAGS
,
529 prop_dictionary_get_int32(dmt
->dict
, DM_IOCTL_OPEN
, &dmi
->open_count
);
531 prop_dictionary_get_uint32(dmt
->dict
, DM_IOCTL_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
);
550 dm_task_get_driver_version(struct dm_task
*dmt
, char *ver
, size_t ver_sz
)
553 uint32_t maj
= 0, min
= 0, patch
= 0;
555 if ((pa_ver
= prop_dictionary_get(dmt
->dict
, DM_IOCTL_VERSION
)) == NULL
)
558 if (!prop_array_get_uint32(pa_ver
, 0, &maj
))
561 if (!prop_array_get_uint32(pa_ver
, 1, &min
))
564 if (!prop_array_get_uint32(pa_ver
, 2, &patch
))
567 snprintf(ver
, ver_sz
, "%u.%u.%u", maj
, min
, patch
);
573 dm_task_get_deps(struct dm_task
*dmt
)
575 prop_object_iterator_t iter
;
578 struct dm_deps
*deps
;
583 if ((pa
= prop_dictionary_get(dmt
->dict
, DM_IOCTL_CMD_DATA
)) == 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
)
595 if ((iter
= prop_array_iterator(pa
)) == NULL
)
598 deps
= (struct dm_deps
*)dmt
->data_buffer
;
599 memset(deps
, 0, sizeof(struct dm_deps
) + (count
* sizeof(uint64_t)));
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
);
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
;
622 if ((pa
= prop_dictionary_get(dmt
->dict
, DM_IOCTL_CMD_DATA
)) == 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
))
634 if ((iter
= prop_array_iterator(pa
)) == NULL
)
637 vers
= (struct dm_versions
*)dmt
->data_buffer
;
638 memset(vers
, 0, sizeof(struct dm_versions
) * count
);
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
]);
652 /* Finish the array */
655 prop_object_iterator_release(iter
);
657 return (struct dm_versions
*)dmt
->data_buffer
;
661 dm_task_get_names(struct dm_task
*dmt
)
663 prop_object_iterator_t iter
;
664 prop_dictionary_t devs_dict
;
666 struct dm_names
*names
;
671 if ((pa
= prop_dictionary_get(dmt
->dict
, DM_IOCTL_CMD_DATA
)) == 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
))
683 if ((iter
= prop_array_iterator(pa
)) == NULL
)
686 names
= (struct dm_names
*)dmt
->data_buffer
;
687 memset(names
, 0, sizeof(struct dm_names
) * count
);
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
,
701 /* Finish the array */
704 prop_object_iterator_release(iter
);
706 return (struct dm_names
*)dmt
->data_buffer
;
710 dm_task_update_nodes(void)
713 /* nothing else needed */
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
;
727 if ((pa
= prop_dictionary_get(dmt
->dict
, DM_IOCTL_CMD_DATA
)) == NULL
)
730 count
= prop_array_count(pa
);
733 if ((iter
= prop_array_iterator(pa
)) == NULL
)
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 */
745 if (!prop_dictionary_get_cstring_nocopy(target_dict
, DM_TABLE_TYPE
,
746 (const char **)target_type
))
750 * Ugly __DECONST and (const char **) casts due to the linux prototype
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
))
760 if (!prop_dictionary_get_uint64(target_dict
, DM_TABLE_LENGTH
, &ulength
))
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))
774 prop_object_iterator_release(iter
);
784 if (stat("/dev/mapper/control", &sb
) < 0)
787 return (uint32_t)major(sb
.st_dev
);
791 dm_is_dm_major(uint32_t major
)
793 return (major
== dm_get_major());
799 return "/dev/mapper";
803 dm_udev_set_sync_support(int sync_udev __unused
)
809 dm_task_set_cookie(struct dm_task
*dmt __unused
, uint32_t *cookie __unused
,
810 uint16_t udev_flags __unused
)
816 dm_udev_wait(uint32_t cookie __unused
)
828 dm_log_init(dm_error_func_t fn
)
836 dm_log_init_verbose(int verbose __unused
)
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
,
850 dm_task_set_gid(struct dm_task
*dmt
, gid_t gid
)
852 return prop_dictionary_set_uint32(dmt
->dict
, DM_DEV_GID
,
857 dm_task_set_mode(struct dm_task
*dmt
, mode_t mode
)
859 return prop_dictionary_set_uint32(dmt
->dict
, DM_DEV_MODE
,
864 dm_task_no_flush(struct dm_task
*dmt __unused
)
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
)
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
)
892 /*****************************************************************************/
893 /********************** DragonFly-specific extensions ************************/
894 /*****************************************************************************/
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
;
905 if ((pa
= prop_dictionary_get(dmt
->dict
, DM_IOCTL_CMD_DATA
)) == NULL
)
908 count
= prop_array_count(pa
);
911 if ((iter
= prop_array_iterator(pa
)) == NULL
)
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 */
923 if (!prop_dictionary_get_cstring_nocopy(target_dict
, DM_TARGETS_NAME
,
927 if ((pa_ver
= prop_dictionary_get(target_dict
, DM_TARGETS_VERSION
))
931 for (j
= 0; j
< 3; j
++) {
932 if (!prop_array_get_uint32(pa_ver
, j
, &target_ver
[j
]))
936 /* If we are at the last element, make sure we return NULL */
937 if (target_dict
== prop_array_get(pa
, count
-1))
945 prop_object_iterator_release(iter
);
951 dm_get_next_dep(struct dm_task
*dmt
, void *cur
, uint64_t *dep
)
953 prop_object_iterator_t iter
;
960 if ((pa
= prop_dictionary_get(dmt
->dict
, DM_IOCTL_CMD_DATA
)) == NULL
)
963 count
= prop_array_count(pa
);
966 if ((iter
= prop_array_iterator(pa
)) == NULL
)
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 */
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))
989 prop_object_iterator_release(iter
);
995 dm_get_next_name(struct dm_task
*dmt
, void *cur
, const char **name
,
998 prop_object_iterator_t iter
;
999 prop_dictionary_t devs_dict
;
1003 if ((pa
= prop_dictionary_get(dmt
->dict
, DM_IOCTL_CMD_DATA
)) == NULL
)
1006 count
= prop_array_count(pa
);
1010 if ((iter
= prop_array_iterator(pa
)) == NULL
)
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 */
1022 if (!prop_dictionary_get_cstring_nocopy(devs_dict
, DM_DEV_NAME
, name
))
1025 if (!prop_dictionary_get_uint64(devs_dict
, DM_DEV_DEV
, dev
))
1028 /* If we are at the last element, make sure we return NULL */
1029 if (devs_dict
== prop_array_get(pa
, count
-1))
1032 return (void *)iter
;
1037 prop_object_iterator_release(iter
);