4 * This file and its contents are supplied under the terms of the
5 * Common Development and Distribution License ("CDDL"), version 1.0.
6 * You may only use this file in accordance with the terms of version
9 * A full copy of the text of the CDDL should have accompanied this
10 * source. A copy of the CDDL is also available via the Internet at
11 * http://www.illumos.org/license/CDDL.
17 * Copyright (c) 2018 by Delphix. All rights reserved.
23 #include <libzfs_core.h>
26 #include <sys/nvpair.h>
27 #include <sys/vdev_impl.h>
28 #include <sys/zfs_ioctl.h>
29 #include <sys/zfs_bootenv.h>
30 #include <sys/fs/zfs.h>
33 * Test the nvpair inputs for the non-legacy zfs ioctl commands.
36 static boolean_t unexpected_failures
;
38 static const char *active_test
;
41 * Tracks which zfs_ioc_t commands were tested
43 static boolean_t ioc_tested
[ZFS_IOC_LAST
- ZFS_IOC_FIRST
];
46 * Legacy ioctls that are skipped (for now)
48 static const zfs_ioc_t ioc_skip
[] = {
55 ZFS_IOC_POOL_TRYIMPORT
,
59 ZFS_IOC_POOL_GET_HISTORY
,
63 ZFS_IOC_VDEV_SET_STATE
,
70 ZFS_IOC_OBJSET_ZPLPROPS
,
71 ZFS_IOC_DATASET_LIST_NEXT
,
72 ZFS_IOC_SNAPSHOT_LIST_NEXT
,
80 ZFS_IOC_INJECT_LIST_NEXT
,
84 ZFS_IOC_DSOBJ_TO_DSNAME
,
86 ZFS_IOC_POOL_SET_PROPS
,
87 ZFS_IOC_POOL_GET_PROPS
,
93 ZFS_IOC_USERSPACE_ONE
,
94 ZFS_IOC_USERSPACE_MANY
,
95 ZFS_IOC_USERSPACE_UPGRADE
,
96 ZFS_IOC_OBJSET_RECVD_PROPS
,
100 ZFS_IOC_TMP_SNAPSHOT
,
101 ZFS_IOC_OBJ_TO_STATS
,
102 ZFS_IOC_SPACE_WRITTEN
,
104 ZFS_IOC_SEND_PROGRESS
,
106 ZFS_IOC_EVENTS_CLEAR
,
114 #define IOC_INPUT_TEST(ioc, name, req, opt, err) \
115 IOC_INPUT_TEST_IMPL(ioc, name, req, opt, err, B_FALSE)
117 #define IOC_INPUT_TEST_WILD(ioc, name, req, opt, err) \
118 IOC_INPUT_TEST_IMPL(ioc, name, req, opt, err, B_TRUE)
120 #define IOC_INPUT_TEST_IMPL(ioc, name, req, opt, err, wild) \
122 active_test = __func__ + 5; \
123 ioc_tested[ioc - ZFS_IOC_FIRST] = B_TRUE; \
124 lzc_ioctl_test(ioc, name, req, opt, err, wild); \
128 * run a zfs ioctl command, verify expected results and log failures
131 lzc_ioctl_run(zfs_ioc_t ioc
, const char *name
, nvlist_t
*innvl
, int expected
)
133 zfs_cmd_t zc
= {"\0"};
140 case ZFS_ERR_IOC_ARG_UNAVAIL
:
141 variant
= "unsupported input";
143 case ZFS_ERR_IOC_ARG_REQUIRED
:
144 variant
= "missing input";
146 case ZFS_ERR_IOC_ARG_BADTYPE
:
147 variant
= "invalid input type";
150 variant
= "valid input";
154 packed
= fnvlist_pack(innvl
, &size
);
155 (void) strlcpy(zc
.zc_name
, name
, sizeof (zc
.zc_name
));
156 zc
.zc_name
[sizeof (zc
.zc_name
) - 1] = '\0';
157 zc
.zc_nvlist_src
= (uint64_t)(uintptr_t)packed
;
158 zc
.zc_nvlist_src_size
= size
;
159 zc
.zc_nvlist_dst_size
= MAX(size
* 2, 128 * 1024);
160 zc
.zc_nvlist_dst
= (uint64_t)(uintptr_t)malloc(zc
.zc_nvlist_dst_size
);
162 if (lzc_ioctl_fd(zfs_fd
, ioc
, &zc
) != 0)
165 if (error
!= expected
) {
166 unexpected_failures
= B_TRUE
;
167 (void) fprintf(stderr
, "%s: Unexpected result with %s, "
168 "error %d (expecting %d)\n",
169 active_test
, variant
, error
, expected
);
172 fnvlist_pack_free(packed
, size
);
173 free((void *)(uintptr_t)zc
.zc_nvlist_dst
);
177 * Test each ioc for the following ioctl input errors:
178 * ZFS_ERR_IOC_ARG_UNAVAIL an input argument is not supported by kernel
179 * ZFS_ERR_IOC_ARG_REQUIRED a required input argument is missing
180 * ZFS_ERR_IOC_ARG_BADTYPE an input argument has an invalid type
183 lzc_ioctl_test(zfs_ioc_t ioc
, const char *name
, nvlist_t
*required
,
184 nvlist_t
*optional
, int expected_error
, boolean_t wildcard
)
186 nvlist_t
*input
= fnvlist_alloc();
187 nvlist_t
*future
= fnvlist_alloc();
190 if (required
!= NULL
) {
191 for (nvpair_t
*pair
= nvlist_next_nvpair(required
, NULL
);
192 pair
!= NULL
; pair
= nvlist_next_nvpair(required
, pair
)) {
193 fnvlist_add_nvpair(input
, pair
);
196 if (optional
!= NULL
) {
197 for (nvpair_t
*pair
= nvlist_next_nvpair(optional
, NULL
);
198 pair
!= NULL
; pair
= nvlist_next_nvpair(optional
, pair
)) {
199 fnvlist_add_nvpair(input
, pair
);
204 * Generic input run with 'optional' nvlist pair
207 fnvlist_add_nvlist(input
, "optional", future
);
208 lzc_ioctl_run(ioc
, name
, input
, expected_error
);
210 fnvlist_remove(input
, "optional");
216 fnvlist_add_string(input
, "bogus_input", "bogus");
217 lzc_ioctl_run(ioc
, name
, input
, ZFS_ERR_IOC_ARG_UNAVAIL
);
218 fnvlist_remove(input
, "bogus_input");
222 * Missing required inputs
224 if (required
!= NULL
) {
225 nvlist_t
*empty
= fnvlist_alloc();
226 lzc_ioctl_run(ioc
, name
, empty
, ZFS_ERR_IOC_ARG_REQUIRED
);
233 if (required
!= NULL
|| optional
!= NULL
) {
235 * switch the type of one of the input pairs
237 for (nvpair_t
*pair
= nvlist_next_nvpair(input
, NULL
);
238 pair
!= NULL
; pair
= nvlist_next_nvpair(input
, pair
)) {
239 char pname
[MAXNAMELEN
];
242 strlcpy(pname
, nvpair_name(pair
), sizeof (pname
));
243 pname
[sizeof (pname
) - 1] = '\0';
244 ptype
= nvpair_type(pair
);
245 fnvlist_remove_nvpair(input
, pair
);
248 case DATA_TYPE_STRING
:
249 fnvlist_add_uint64(input
, pname
, 42);
252 fnvlist_add_string(input
, pname
, "bogus");
256 lzc_ioctl_run(ioc
, name
, input
, ZFS_ERR_IOC_ARG_BADTYPE
);
266 test_pool_sync(const char *pool
)
268 nvlist_t
*required
= fnvlist_alloc();
270 fnvlist_add_boolean_value(required
, "force", B_TRUE
);
272 IOC_INPUT_TEST(ZFS_IOC_POOL_SYNC
, pool
, required
, NULL
, 0);
274 nvlist_free(required
);
278 test_pool_reopen(const char *pool
)
280 nvlist_t
*optional
= fnvlist_alloc();
282 fnvlist_add_boolean_value(optional
, "scrub_restart", B_FALSE
);
284 IOC_INPUT_TEST(ZFS_IOC_POOL_REOPEN
, pool
, NULL
, optional
, 0);
286 nvlist_free(optional
);
290 test_pool_checkpoint(const char *pool
)
292 IOC_INPUT_TEST(ZFS_IOC_POOL_CHECKPOINT
, pool
, NULL
, NULL
, 0);
296 test_pool_discard_checkpoint(const char *pool
)
298 int err
= lzc_pool_checkpoint(pool
);
299 if (err
== 0 || err
== ZFS_ERR_CHECKPOINT_EXISTS
)
300 IOC_INPUT_TEST(ZFS_IOC_POOL_DISCARD_CHECKPOINT
, pool
, NULL
,
305 test_log_history(const char *pool
)
307 nvlist_t
*required
= fnvlist_alloc();
309 fnvlist_add_string(required
, "message", "input check");
311 IOC_INPUT_TEST(ZFS_IOC_LOG_HISTORY
, pool
, required
, NULL
, 0);
313 nvlist_free(required
);
317 test_create(const char *pool
)
319 char dataset
[MAXNAMELEN
+ 32];
321 (void) snprintf(dataset
, sizeof (dataset
), "%s/create-fs", pool
);
323 nvlist_t
*required
= fnvlist_alloc();
324 nvlist_t
*optional
= fnvlist_alloc();
325 nvlist_t
*props
= fnvlist_alloc();
327 fnvlist_add_int32(required
, "type", DMU_OST_ZFS
);
328 fnvlist_add_uint64(props
, "recordsize", 8192);
329 fnvlist_add_nvlist(optional
, "props", props
);
331 IOC_INPUT_TEST(ZFS_IOC_CREATE
, dataset
, required
, optional
, 0);
333 nvlist_free(required
);
334 nvlist_free(optional
);
338 test_snapshot(const char *pool
, const char *snapshot
)
340 nvlist_t
*required
= fnvlist_alloc();
341 nvlist_t
*optional
= fnvlist_alloc();
342 nvlist_t
*snaps
= fnvlist_alloc();
343 nvlist_t
*props
= fnvlist_alloc();
345 fnvlist_add_boolean(snaps
, snapshot
);
346 fnvlist_add_nvlist(required
, "snaps", snaps
);
348 fnvlist_add_string(props
, "org.openzfs:launch", "September 17th, 2013");
349 fnvlist_add_nvlist(optional
, "props", props
);
351 IOC_INPUT_TEST(ZFS_IOC_SNAPSHOT
, pool
, required
, optional
, 0);
355 nvlist_free(optional
);
356 nvlist_free(required
);
360 test_space_snaps(const char *snapshot
)
362 nvlist_t
*required
= fnvlist_alloc();
363 fnvlist_add_string(required
, "firstsnap", snapshot
);
365 IOC_INPUT_TEST(ZFS_IOC_SPACE_SNAPS
, snapshot
, required
, NULL
, 0);
367 nvlist_free(required
);
371 test_destroy_snaps(const char *pool
, const char *snapshot
)
373 nvlist_t
*required
= fnvlist_alloc();
374 nvlist_t
*snaps
= fnvlist_alloc();
376 fnvlist_add_boolean(snaps
, snapshot
);
377 fnvlist_add_nvlist(required
, "snaps", snaps
);
379 IOC_INPUT_TEST(ZFS_IOC_DESTROY_SNAPS
, pool
, required
, NULL
, 0);
382 nvlist_free(required
);
387 test_bookmark(const char *pool
, const char *snapshot
, const char *bookmark
)
389 nvlist_t
*required
= fnvlist_alloc();
391 fnvlist_add_string(required
, bookmark
, snapshot
);
393 IOC_INPUT_TEST_WILD(ZFS_IOC_BOOKMARK
, pool
, required
, NULL
, 0);
395 nvlist_free(required
);
399 test_get_bookmarks(const char *dataset
)
401 nvlist_t
*optional
= fnvlist_alloc();
403 fnvlist_add_boolean(optional
, "guid");
404 fnvlist_add_boolean(optional
, "createtxg");
405 fnvlist_add_boolean(optional
, "creation");
407 IOC_INPUT_TEST_WILD(ZFS_IOC_GET_BOOKMARKS
, dataset
, NULL
, optional
, 0);
409 nvlist_free(optional
);
413 test_destroy_bookmarks(const char *pool
, const char *bookmark
)
415 nvlist_t
*required
= fnvlist_alloc();
417 fnvlist_add_boolean(required
, bookmark
);
419 IOC_INPUT_TEST_WILD(ZFS_IOC_DESTROY_BOOKMARKS
, pool
, required
, NULL
, 0);
421 nvlist_free(required
);
425 test_clone(const char *snapshot
, const char *clone
)
427 nvlist_t
*required
= fnvlist_alloc();
428 nvlist_t
*optional
= fnvlist_alloc();
429 nvlist_t
*props
= fnvlist_alloc();
431 fnvlist_add_string(required
, "origin", snapshot
);
433 IOC_INPUT_TEST(ZFS_IOC_CLONE
, clone
, required
, NULL
, 0);
436 nvlist_free(optional
);
437 nvlist_free(required
);
441 test_rollback(const char *dataset
, const char *snapshot
)
443 nvlist_t
*optional
= fnvlist_alloc();
445 fnvlist_add_string(optional
, "target", snapshot
);
447 IOC_INPUT_TEST(ZFS_IOC_ROLLBACK
, dataset
, NULL
, optional
, B_FALSE
);
449 nvlist_free(optional
);
453 test_hold(const char *pool
, const char *snapshot
)
455 nvlist_t
*required
= fnvlist_alloc();
456 nvlist_t
*optional
= fnvlist_alloc();
457 nvlist_t
*holds
= fnvlist_alloc();
459 fnvlist_add_string(holds
, snapshot
, "libzfs_check_hold");
460 fnvlist_add_nvlist(required
, "holds", holds
);
461 fnvlist_add_int32(optional
, "cleanup_fd", zfs_fd
);
463 IOC_INPUT_TEST(ZFS_IOC_HOLD
, pool
, required
, optional
, 0);
466 nvlist_free(optional
);
467 nvlist_free(required
);
471 test_get_holds(const char *snapshot
)
473 IOC_INPUT_TEST(ZFS_IOC_GET_HOLDS
, snapshot
, NULL
, NULL
, 0);
477 test_release(const char *pool
, const char *snapshot
)
479 nvlist_t
*required
= fnvlist_alloc();
480 nvlist_t
*release
= fnvlist_alloc();
482 fnvlist_add_boolean(release
, "libzfs_check_hold");
483 fnvlist_add_nvlist(required
, snapshot
, release
);
485 IOC_INPUT_TEST_WILD(ZFS_IOC_RELEASE
, pool
, required
, NULL
, 0);
487 nvlist_free(release
);
488 nvlist_free(required
);
493 test_send_new(const char *snapshot
, int fd
)
495 nvlist_t
*required
= fnvlist_alloc();
496 nvlist_t
*optional
= fnvlist_alloc();
498 fnvlist_add_int32(required
, "fd", fd
);
500 fnvlist_add_boolean(optional
, "largeblockok");
501 fnvlist_add_boolean(optional
, "embedok");
502 fnvlist_add_boolean(optional
, "compressok");
503 fnvlist_add_boolean(optional
, "rawok");
506 * TODO - Resumable send is harder to set up. So we currently
507 * ignore testing for that variant.
510 fnvlist_add_string(optional
, "fromsnap", from
);
511 fnvlist_add_uint64(optional
, "resume_object", resumeobj
);
512 fnvlist_add_uint64(optional
, "resume_offset", offset
);
513 fnvlist_add_boolean(optional
, "savedok");
515 IOC_INPUT_TEST(ZFS_IOC_SEND_NEW
, snapshot
, required
, optional
, 0);
517 nvlist_free(optional
);
518 nvlist_free(required
);
522 test_recv_new(const char *dataset
, int fd
)
524 dmu_replay_record_t drr
;
525 nvlist_t
*required
= fnvlist_alloc();
526 nvlist_t
*optional
= fnvlist_alloc();
527 nvlist_t
*props
= fnvlist_alloc();
528 char snapshot
[MAXNAMELEN
+ 32];
531 memset(&drr
, 0, sizeof (dmu_replay_record_t
));
533 int cleanup_fd
= open(ZFS_DEV
, O_RDWR
);
534 if (cleanup_fd
== -1) {
535 (void) fprintf(stderr
, "open(%s) failed: %s\n", ZFS_DEV
,
539 (void) snprintf(snapshot
, sizeof (snapshot
), "%s@replicant", dataset
);
541 count
= pread(fd
, &drr
, sizeof (drr
), 0);
542 if (count
!= sizeof (drr
)) {
543 (void) fprintf(stderr
, "could not read stream: %s\n",
547 fnvlist_add_string(required
, "snapname", snapshot
);
548 fnvlist_add_byte_array(required
, "begin_record", (uchar_t
*)&drr
,
550 fnvlist_add_int32(required
, "input_fd", fd
);
552 fnvlist_add_string(props
, "org.openzfs:launch", "September 17th, 2013");
553 fnvlist_add_nvlist(optional
, "localprops", props
);
554 fnvlist_add_boolean(optional
, "force");
555 fnvlist_add_boolean(optional
, "heal");
556 fnvlist_add_int32(optional
, "cleanup_fd", cleanup_fd
);
559 * TODO - Resumable receive is harder to set up. So we currently
560 * ignore testing for one.
563 fnvlist_add_nvlist(optional
, "props", recvdprops
);
564 fnvlist_add_string(optional
, "origin", origin
);
565 fnvlist_add_boolean(optional
, "resumable");
566 fnvlist_add_uint64(optional
, "action_handle", *action_handle
);
568 IOC_INPUT_TEST(ZFS_IOC_RECV_NEW
, dataset
, required
, optional
,
572 nvlist_free(optional
);
573 nvlist_free(required
);
575 (void) close(cleanup_fd
);
579 test_send_space(const char *snapshot1
, const char *snapshot2
)
581 nvlist_t
*optional
= fnvlist_alloc();
583 fnvlist_add_string(optional
, "from", snapshot1
);
584 fnvlist_add_boolean(optional
, "largeblockok");
585 fnvlist_add_boolean(optional
, "embedok");
586 fnvlist_add_boolean(optional
, "compressok");
587 fnvlist_add_boolean(optional
, "rawok");
589 IOC_INPUT_TEST(ZFS_IOC_SEND_SPACE
, snapshot2
, NULL
, optional
, 0);
591 nvlist_free(optional
);
595 test_remap(const char *dataset
)
597 IOC_INPUT_TEST(ZFS_IOC_REMAP
, dataset
, NULL
, NULL
, 0);
601 test_channel_program(const char *pool
)
603 const char *program
=
605 "argv = arg[\"argv\"]\n"
607 const char *const argv
[1] = { "Hello World!" };
608 nvlist_t
*required
= fnvlist_alloc();
609 nvlist_t
*optional
= fnvlist_alloc();
610 nvlist_t
*args
= fnvlist_alloc();
612 fnvlist_add_string(required
, "program", program
);
613 fnvlist_add_string_array(args
, "argv", argv
, 1);
614 fnvlist_add_nvlist(required
, "arg", args
);
616 fnvlist_add_boolean_value(optional
, "sync", B_TRUE
);
617 fnvlist_add_uint64(optional
, "instrlimit", 1000 * 1000);
618 fnvlist_add_uint64(optional
, "memlimit", 8192 * 1024);
620 IOC_INPUT_TEST(ZFS_IOC_CHANNEL_PROGRAM
, pool
, required
, optional
, 0);
623 nvlist_free(optional
);
624 nvlist_free(required
);
627 #define WRAPPING_KEY_LEN 32
630 test_load_key(const char *dataset
)
632 nvlist_t
*required
= fnvlist_alloc();
633 nvlist_t
*optional
= fnvlist_alloc();
634 nvlist_t
*hidden
= fnvlist_alloc();
635 uint8_t keydata
[WRAPPING_KEY_LEN
] = {0};
637 fnvlist_add_uint8_array(hidden
, "wkeydata", keydata
, sizeof (keydata
));
638 fnvlist_add_nvlist(required
, "hidden_args", hidden
);
639 fnvlist_add_boolean(optional
, "noop");
641 IOC_INPUT_TEST(ZFS_IOC_LOAD_KEY
, dataset
, required
, optional
, EINVAL
);
643 nvlist_free(optional
);
644 nvlist_free(required
);
648 test_change_key(const char *dataset
)
650 IOC_INPUT_TEST(ZFS_IOC_CHANGE_KEY
, dataset
, NULL
, NULL
, EINVAL
);
654 test_unload_key(const char *dataset
)
656 IOC_INPUT_TEST(ZFS_IOC_UNLOAD_KEY
, dataset
, NULL
, NULL
, EACCES
);
660 test_vdev_initialize(const char *pool
)
662 nvlist_t
*required
= fnvlist_alloc();
663 nvlist_t
*vdev_guids
= fnvlist_alloc();
665 fnvlist_add_uint64(vdev_guids
, "path", 0xdeadbeefdeadbeef);
666 fnvlist_add_uint64(required
, ZPOOL_INITIALIZE_COMMAND
,
667 POOL_INITIALIZE_START
);
668 fnvlist_add_nvlist(required
, ZPOOL_INITIALIZE_VDEVS
, vdev_guids
);
670 IOC_INPUT_TEST(ZFS_IOC_POOL_INITIALIZE
, pool
, required
, NULL
, EINVAL
);
671 nvlist_free(vdev_guids
);
672 nvlist_free(required
);
676 test_vdev_trim(const char *pool
)
678 nvlist_t
*required
= fnvlist_alloc();
679 nvlist_t
*optional
= fnvlist_alloc();
680 nvlist_t
*vdev_guids
= fnvlist_alloc();
682 fnvlist_add_uint64(vdev_guids
, "path", 0xdeadbeefdeadbeef);
683 fnvlist_add_uint64(required
, ZPOOL_TRIM_COMMAND
, POOL_TRIM_START
);
684 fnvlist_add_nvlist(required
, ZPOOL_TRIM_VDEVS
, vdev_guids
);
685 fnvlist_add_uint64(optional
, ZPOOL_TRIM_RATE
, 1ULL << 30);
686 fnvlist_add_boolean_value(optional
, ZPOOL_TRIM_SECURE
, B_TRUE
);
688 IOC_INPUT_TEST(ZFS_IOC_POOL_TRIM
, pool
, required
, optional
, EINVAL
);
689 nvlist_free(vdev_guids
);
690 nvlist_free(optional
);
691 nvlist_free(required
);
694 /* Test with invalid values */
696 test_scrub(const char *pool
)
698 nvlist_t
*required
= fnvlist_alloc();
699 fnvlist_add_uint64(required
, "scan_type", POOL_SCAN_FUNCS
+ 1);
700 fnvlist_add_uint64(required
, "scan_command", POOL_SCRUB_FLAGS_END
+ 1);
701 IOC_INPUT_TEST(ZFS_IOC_POOL_SCRUB
, pool
, required
, NULL
, EINVAL
);
702 nvlist_free(required
);
706 zfs_destroy(const char *dataset
)
708 zfs_cmd_t zc
= {"\0"};
711 (void) strlcpy(zc
.zc_name
, dataset
, sizeof (zc
.zc_name
));
712 zc
.zc_name
[sizeof (zc
.zc_name
) - 1] = '\0';
713 err
= lzc_ioctl_fd(zfs_fd
, ZFS_IOC_DESTROY
, &zc
);
715 return (err
== 0 ? 0 : errno
);
719 test_redact(const char *snapshot1
, const char *snapshot2
)
721 nvlist_t
*required
= fnvlist_alloc();
722 nvlist_t
*snapnv
= fnvlist_alloc();
723 char bookmark
[MAXNAMELEN
+ 32];
725 fnvlist_add_string(required
, "bookname", "testbookmark");
726 fnvlist_add_boolean(snapnv
, snapshot2
);
727 fnvlist_add_nvlist(required
, "snapnv", snapnv
);
729 IOC_INPUT_TEST(ZFS_IOC_REDACT
, snapshot1
, required
, NULL
, 0);
732 nvlist_free(required
);
734 strlcpy(bookmark
, snapshot1
, sizeof (bookmark
));
735 *strchr(bookmark
, '@') = '\0';
736 strlcat(bookmark
, "#testbookmark", sizeof (bookmark
) -
738 zfs_destroy(bookmark
);
742 test_get_bookmark_props(const char *bookmark
)
744 IOC_INPUT_TEST(ZFS_IOC_GET_BOOKMARK_PROPS
, bookmark
, NULL
, NULL
, 0);
748 test_wait(const char *pool
)
750 nvlist_t
*required
= fnvlist_alloc();
751 nvlist_t
*optional
= fnvlist_alloc();
753 fnvlist_add_int32(required
, "wait_activity", 2);
754 fnvlist_add_uint64(optional
, "wait_tag", 0xdeadbeefdeadbeef);
756 IOC_INPUT_TEST(ZFS_IOC_WAIT
, pool
, required
, optional
, EINVAL
);
758 nvlist_free(required
);
759 nvlist_free(optional
);
763 test_wait_fs(const char *dataset
)
765 nvlist_t
*required
= fnvlist_alloc();
767 fnvlist_add_int32(required
, "wait_activity", 2);
769 IOC_INPUT_TEST(ZFS_IOC_WAIT_FS
, dataset
, required
, NULL
, EINVAL
);
771 nvlist_free(required
);
775 test_get_bootenv(const char *pool
)
777 IOC_INPUT_TEST(ZFS_IOC_GET_BOOTENV
, pool
, NULL
, NULL
, 0);
781 test_set_bootenv(const char *pool
)
783 nvlist_t
*required
= fnvlist_alloc();
785 fnvlist_add_uint64(required
, "version", VB_RAW
);
786 fnvlist_add_string(required
, GRUB_ENVMAP
, "test");
788 IOC_INPUT_TEST_WILD(ZFS_IOC_SET_BOOTENV
, pool
, required
, NULL
, 0);
790 nvlist_free(required
);
794 zfs_ioc_input_tests(const char *pool
)
796 char filepath
[] = "/tmp/ioc_test_file_XXXXXX";
797 char dataset
[ZFS_MAX_DATASET_NAME_LEN
];
798 char snapbase
[ZFS_MAX_DATASET_NAME_LEN
+ 32];
799 char snapshot
[ZFS_MAX_DATASET_NAME_LEN
+ 32];
800 char bookmark
[ZFS_MAX_DATASET_NAME_LEN
+ 32];
801 char backup
[ZFS_MAX_DATASET_NAME_LEN
];
802 char clone
[ZFS_MAX_DATASET_NAME_LEN
];
803 char clonesnap
[ZFS_MAX_DATASET_NAME_LEN
+ 32];
807 * Setup names and create a working dataset
809 (void) snprintf(dataset
, sizeof (dataset
), "%s/test-fs", pool
);
810 (void) snprintf(snapbase
, sizeof (snapbase
), "%s@snapbase", dataset
);
811 (void) snprintf(snapshot
, sizeof (snapshot
), "%s@snapshot", dataset
);
812 (void) snprintf(bookmark
, sizeof (bookmark
), "%s#bookmark", dataset
);
813 (void) snprintf(clone
, sizeof (clone
), "%s/test-fs-clone", pool
);
814 (void) snprintf(clonesnap
, sizeof (clonesnap
), "%s@snap", clone
);
815 (void) snprintf(backup
, sizeof (backup
), "%s/backup", pool
);
817 err
= lzc_create(dataset
, LZC_DATSET_TYPE_ZFS
, NULL
, NULL
, -1);
819 (void) fprintf(stderr
, "could not create '%s': %s\n",
820 dataset
, strerror(errno
));
824 tmpfd
= mkstemp(filepath
);
826 (void) fprintf(stderr
, "could not create '%s': %s\n",
827 filepath
, strerror(errno
));
832 * run a test for each ioctl
833 * Note that some test build on previous test operations
835 test_pool_sync(pool
);
836 test_pool_reopen(pool
);
837 test_pool_checkpoint(pool
);
838 test_pool_discard_checkpoint(pool
);
839 test_log_history(pool
);
841 test_create(dataset
);
842 test_snapshot(pool
, snapbase
);
843 test_snapshot(pool
, snapshot
);
845 test_space_snaps(snapshot
);
846 test_send_space(snapbase
, snapshot
);
847 test_send_new(snapshot
, tmpfd
);
848 test_recv_new(backup
, tmpfd
);
850 test_bookmark(pool
, snapshot
, bookmark
);
851 test_get_bookmarks(dataset
);
852 test_get_bookmark_props(bookmark
);
853 test_destroy_bookmarks(pool
, bookmark
);
855 test_hold(pool
, snapshot
);
856 test_get_holds(snapshot
);
857 test_release(pool
, snapshot
);
859 test_clone(snapshot
, clone
);
860 test_snapshot(pool
, clonesnap
);
861 test_redact(snapshot
, clonesnap
);
862 zfs_destroy(clonesnap
);
865 test_rollback(dataset
, snapshot
);
866 test_destroy_snaps(pool
, snapshot
);
867 test_destroy_snaps(pool
, snapbase
);
870 test_channel_program(pool
);
872 test_load_key(dataset
);
873 test_change_key(dataset
);
874 test_unload_key(dataset
);
876 test_vdev_initialize(pool
);
877 test_vdev_trim(pool
);
880 test_wait_fs(dataset
);
882 test_set_bootenv(pool
);
883 test_get_bootenv(pool
);
890 zfs_cmd_t zc
= {"\0"};
892 nvlist_t
*snaps
= fnvlist_alloc();
893 fnvlist_add_boolean(snaps
, snapshot
);
894 (void) lzc_destroy_snaps(snaps
, B_FALSE
, NULL
);
897 (void) zfs_destroy(dataset
);
898 (void) zfs_destroy(backup
);
901 (void) unlink(filepath
);
904 * All the unused slots should yield ZFS_ERR_IOC_CMD_UNAVAIL
906 for (int i
= 0; i
< ARRAY_SIZE(ioc_skip
); i
++) {
907 if (ioc_tested
[ioc_skip
[i
] - ZFS_IOC_FIRST
])
908 (void) fprintf(stderr
, "cmd %d tested, not skipped!\n",
909 (int)(ioc_skip
[i
] - ZFS_IOC_FIRST
));
911 ioc_tested
[ioc_skip
[i
] - ZFS_IOC_FIRST
] = B_TRUE
;
914 (void) strlcpy(zc
.zc_name
, pool
, sizeof (zc
.zc_name
));
915 zc
.zc_name
[sizeof (zc
.zc_name
) - 1] = '\0';
917 for (unsigned ioc
= ZFS_IOC_FIRST
; ioc
< ZFS_IOC_LAST
; ioc
++) {
918 unsigned cmd
= ioc
- ZFS_IOC_FIRST
;
923 if (lzc_ioctl_fd(zfs_fd
, ioc
, &zc
) != 0 &&
924 errno
!= ZFS_ERR_IOC_CMD_UNAVAIL
) {
925 (void) fprintf(stderr
, "cmd %d is missing a test case "
926 "(%d)\n", cmd
, errno
);
935 ZFS_IOC_BASE
= ('Z' << 8),
937 ZFS_IOC_PLATFORM_BASE
= ZFS_IOC_BASE
+ 0x80,
941 * Canonical reference check of /dev/zfs ioctl numbers.
942 * These cannot change and new ioctl numbers must be appended.
945 validate_ioc_values(void)
947 boolean_t result
= B_TRUE
;
949 #define CHECK(expr) do { \
952 fprintf(stderr, "(%s) === FALSE\n", #expr); \
956 CHECK(ZFS_IOC_BASE
+ 0 == ZFS_IOC_POOL_CREATE
);
957 CHECK(ZFS_IOC_BASE
+ 1 == ZFS_IOC_POOL_DESTROY
);
958 CHECK(ZFS_IOC_BASE
+ 2 == ZFS_IOC_POOL_IMPORT
);
959 CHECK(ZFS_IOC_BASE
+ 3 == ZFS_IOC_POOL_EXPORT
);
960 CHECK(ZFS_IOC_BASE
+ 4 == ZFS_IOC_POOL_CONFIGS
);
961 CHECK(ZFS_IOC_BASE
+ 5 == ZFS_IOC_POOL_STATS
);
962 CHECK(ZFS_IOC_BASE
+ 6 == ZFS_IOC_POOL_TRYIMPORT
);
963 CHECK(ZFS_IOC_BASE
+ 7 == ZFS_IOC_POOL_SCAN
);
964 CHECK(ZFS_IOC_BASE
+ 8 == ZFS_IOC_POOL_FREEZE
);
965 CHECK(ZFS_IOC_BASE
+ 9 == ZFS_IOC_POOL_UPGRADE
);
966 CHECK(ZFS_IOC_BASE
+ 10 == ZFS_IOC_POOL_GET_HISTORY
);
967 CHECK(ZFS_IOC_BASE
+ 11 == ZFS_IOC_VDEV_ADD
);
968 CHECK(ZFS_IOC_BASE
+ 12 == ZFS_IOC_VDEV_REMOVE
);
969 CHECK(ZFS_IOC_BASE
+ 13 == ZFS_IOC_VDEV_SET_STATE
);
970 CHECK(ZFS_IOC_BASE
+ 14 == ZFS_IOC_VDEV_ATTACH
);
971 CHECK(ZFS_IOC_BASE
+ 15 == ZFS_IOC_VDEV_DETACH
);
972 CHECK(ZFS_IOC_BASE
+ 16 == ZFS_IOC_VDEV_SETPATH
);
973 CHECK(ZFS_IOC_BASE
+ 17 == ZFS_IOC_VDEV_SETFRU
);
974 CHECK(ZFS_IOC_BASE
+ 18 == ZFS_IOC_OBJSET_STATS
);
975 CHECK(ZFS_IOC_BASE
+ 19 == ZFS_IOC_OBJSET_ZPLPROPS
);
976 CHECK(ZFS_IOC_BASE
+ 20 == ZFS_IOC_DATASET_LIST_NEXT
);
977 CHECK(ZFS_IOC_BASE
+ 21 == ZFS_IOC_SNAPSHOT_LIST_NEXT
);
978 CHECK(ZFS_IOC_BASE
+ 22 == ZFS_IOC_SET_PROP
);
979 CHECK(ZFS_IOC_BASE
+ 23 == ZFS_IOC_CREATE
);
980 CHECK(ZFS_IOC_BASE
+ 24 == ZFS_IOC_DESTROY
);
981 CHECK(ZFS_IOC_BASE
+ 25 == ZFS_IOC_ROLLBACK
);
982 CHECK(ZFS_IOC_BASE
+ 26 == ZFS_IOC_RENAME
);
983 CHECK(ZFS_IOC_BASE
+ 27 == ZFS_IOC_RECV
);
984 CHECK(ZFS_IOC_BASE
+ 28 == ZFS_IOC_SEND
);
985 CHECK(ZFS_IOC_BASE
+ 29 == ZFS_IOC_INJECT_FAULT
);
986 CHECK(ZFS_IOC_BASE
+ 30 == ZFS_IOC_CLEAR_FAULT
);
987 CHECK(ZFS_IOC_BASE
+ 31 == ZFS_IOC_INJECT_LIST_NEXT
);
988 CHECK(ZFS_IOC_BASE
+ 32 == ZFS_IOC_ERROR_LOG
);
989 CHECK(ZFS_IOC_BASE
+ 33 == ZFS_IOC_CLEAR
);
990 CHECK(ZFS_IOC_BASE
+ 34 == ZFS_IOC_PROMOTE
);
991 CHECK(ZFS_IOC_BASE
+ 35 == ZFS_IOC_SNAPSHOT
);
992 CHECK(ZFS_IOC_BASE
+ 36 == ZFS_IOC_DSOBJ_TO_DSNAME
);
993 CHECK(ZFS_IOC_BASE
+ 37 == ZFS_IOC_OBJ_TO_PATH
);
994 CHECK(ZFS_IOC_BASE
+ 38 == ZFS_IOC_POOL_SET_PROPS
);
995 CHECK(ZFS_IOC_BASE
+ 39 == ZFS_IOC_POOL_GET_PROPS
);
996 CHECK(ZFS_IOC_BASE
+ 40 == ZFS_IOC_SET_FSACL
);
997 CHECK(ZFS_IOC_BASE
+ 41 == ZFS_IOC_GET_FSACL
);
998 CHECK(ZFS_IOC_BASE
+ 42 == ZFS_IOC_SHARE
);
999 CHECK(ZFS_IOC_BASE
+ 43 == ZFS_IOC_INHERIT_PROP
);
1000 CHECK(ZFS_IOC_BASE
+ 44 == ZFS_IOC_SMB_ACL
);
1001 CHECK(ZFS_IOC_BASE
+ 45 == ZFS_IOC_USERSPACE_ONE
);
1002 CHECK(ZFS_IOC_BASE
+ 46 == ZFS_IOC_USERSPACE_MANY
);
1003 CHECK(ZFS_IOC_BASE
+ 47 == ZFS_IOC_USERSPACE_UPGRADE
);
1004 CHECK(ZFS_IOC_BASE
+ 48 == ZFS_IOC_HOLD
);
1005 CHECK(ZFS_IOC_BASE
+ 49 == ZFS_IOC_RELEASE
);
1006 CHECK(ZFS_IOC_BASE
+ 50 == ZFS_IOC_GET_HOLDS
);
1007 CHECK(ZFS_IOC_BASE
+ 51 == ZFS_IOC_OBJSET_RECVD_PROPS
);
1008 CHECK(ZFS_IOC_BASE
+ 52 == ZFS_IOC_VDEV_SPLIT
);
1009 CHECK(ZFS_IOC_BASE
+ 53 == ZFS_IOC_NEXT_OBJ
);
1010 CHECK(ZFS_IOC_BASE
+ 54 == ZFS_IOC_DIFF
);
1011 CHECK(ZFS_IOC_BASE
+ 55 == ZFS_IOC_TMP_SNAPSHOT
);
1012 CHECK(ZFS_IOC_BASE
+ 56 == ZFS_IOC_OBJ_TO_STATS
);
1013 CHECK(ZFS_IOC_BASE
+ 57 == ZFS_IOC_SPACE_WRITTEN
);
1014 CHECK(ZFS_IOC_BASE
+ 58 == ZFS_IOC_SPACE_SNAPS
);
1015 CHECK(ZFS_IOC_BASE
+ 59 == ZFS_IOC_DESTROY_SNAPS
);
1016 CHECK(ZFS_IOC_BASE
+ 60 == ZFS_IOC_POOL_REGUID
);
1017 CHECK(ZFS_IOC_BASE
+ 61 == ZFS_IOC_POOL_REOPEN
);
1018 CHECK(ZFS_IOC_BASE
+ 62 == ZFS_IOC_SEND_PROGRESS
);
1019 CHECK(ZFS_IOC_BASE
+ 63 == ZFS_IOC_LOG_HISTORY
);
1020 CHECK(ZFS_IOC_BASE
+ 64 == ZFS_IOC_SEND_NEW
);
1021 CHECK(ZFS_IOC_BASE
+ 65 == ZFS_IOC_SEND_SPACE
);
1022 CHECK(ZFS_IOC_BASE
+ 66 == ZFS_IOC_CLONE
);
1023 CHECK(ZFS_IOC_BASE
+ 67 == ZFS_IOC_BOOKMARK
);
1024 CHECK(ZFS_IOC_BASE
+ 68 == ZFS_IOC_GET_BOOKMARKS
);
1025 CHECK(ZFS_IOC_BASE
+ 69 == ZFS_IOC_DESTROY_BOOKMARKS
);
1026 CHECK(ZFS_IOC_BASE
+ 70 == ZFS_IOC_RECV_NEW
);
1027 CHECK(ZFS_IOC_BASE
+ 71 == ZFS_IOC_POOL_SYNC
);
1028 CHECK(ZFS_IOC_BASE
+ 72 == ZFS_IOC_CHANNEL_PROGRAM
);
1029 CHECK(ZFS_IOC_BASE
+ 73 == ZFS_IOC_LOAD_KEY
);
1030 CHECK(ZFS_IOC_BASE
+ 74 == ZFS_IOC_UNLOAD_KEY
);
1031 CHECK(ZFS_IOC_BASE
+ 75 == ZFS_IOC_CHANGE_KEY
);
1032 CHECK(ZFS_IOC_BASE
+ 76 == ZFS_IOC_REMAP
);
1033 CHECK(ZFS_IOC_BASE
+ 77 == ZFS_IOC_POOL_CHECKPOINT
);
1034 CHECK(ZFS_IOC_BASE
+ 78 == ZFS_IOC_POOL_DISCARD_CHECKPOINT
);
1035 CHECK(ZFS_IOC_BASE
+ 79 == ZFS_IOC_POOL_INITIALIZE
);
1036 CHECK(ZFS_IOC_BASE
+ 80 == ZFS_IOC_POOL_TRIM
);
1037 CHECK(ZFS_IOC_BASE
+ 81 == ZFS_IOC_REDACT
);
1038 CHECK(ZFS_IOC_BASE
+ 82 == ZFS_IOC_GET_BOOKMARK_PROPS
);
1039 CHECK(ZFS_IOC_BASE
+ 83 == ZFS_IOC_WAIT
);
1040 CHECK(ZFS_IOC_BASE
+ 84 == ZFS_IOC_WAIT_FS
);
1041 CHECK(ZFS_IOC_BASE
+ 87 == ZFS_IOC_POOL_SCRUB
);
1042 CHECK(ZFS_IOC_PLATFORM_BASE
+ 1 == ZFS_IOC_EVENTS_NEXT
);
1043 CHECK(ZFS_IOC_PLATFORM_BASE
+ 2 == ZFS_IOC_EVENTS_CLEAR
);
1044 CHECK(ZFS_IOC_PLATFORM_BASE
+ 3 == ZFS_IOC_EVENTS_SEEK
);
1045 CHECK(ZFS_IOC_PLATFORM_BASE
+ 4 == ZFS_IOC_NEXTBOOT
);
1046 CHECK(ZFS_IOC_PLATFORM_BASE
+ 5 == ZFS_IOC_JAIL
);
1047 CHECK(ZFS_IOC_PLATFORM_BASE
+ 6 == ZFS_IOC_UNJAIL
);
1048 CHECK(ZFS_IOC_PLATFORM_BASE
+ 7 == ZFS_IOC_SET_BOOTENV
);
1049 CHECK(ZFS_IOC_PLATFORM_BASE
+ 8 == ZFS_IOC_GET_BOOTENV
);
1057 main(int argc
, const char *argv
[])
1060 (void) fprintf(stderr
, "usage: %s <pool>\n", argv
[0]);
1064 if (!validate_ioc_values()) {
1065 (void) fprintf(stderr
, "WARNING: zfs_ioc_t has binary "
1066 "incompatible command values\n");
1070 (void) libzfs_core_init();
1071 zfs_fd
= open(ZFS_DEV
, O_RDWR
);
1073 (void) fprintf(stderr
, "open: %s\n", strerror(errno
));
1078 zfs_ioc_input_tests(argv
[1]);
1080 (void) close(zfs_fd
);
1083 return (unexpected_failures
);