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.
24 #include <libzfs_core.h>
26 #include <sys/nvpair.h>
27 #include <sys/zfs_ioctl.h>
30 * Test the nvpair inputs for the non-legacy zfs ioctl commands.
33 boolean_t unexpected_failures
;
35 const char *active_test
;
38 * Tracks which zfs_ioc_t commands were tested
40 boolean_t ioc_tested
[ZFS_IOC_LAST
- ZFS_IOC_FIRST
];
43 * Legacy ioctls that are skipped (for now)
45 static unsigned ioc_skip
[] = {
52 ZFS_IOC_POOL_TRYIMPORT
,
56 ZFS_IOC_POOL_GET_HISTORY
,
60 ZFS_IOC_VDEV_SET_STATE
,
67 ZFS_IOC_OBJSET_ZPLPROPS
,
68 ZFS_IOC_DATASET_LIST_NEXT
,
69 ZFS_IOC_SNAPSHOT_LIST_NEXT
,
77 ZFS_IOC_INJECT_LIST_NEXT
,
81 ZFS_IOC_DSOBJ_TO_DSNAME
,
83 ZFS_IOC_POOL_SET_PROPS
,
84 ZFS_IOC_POOL_GET_PROPS
,
90 ZFS_IOC_USERSPACE_ONE
,
91 ZFS_IOC_USERSPACE_MANY
,
92 ZFS_IOC_USERSPACE_UPGRADE
,
93 ZFS_IOC_OBJSET_RECVD_PROPS
,
99 ZFS_IOC_SPACE_WRITTEN
,
101 ZFS_IOC_SEND_PROGRESS
,
104 ZFS_IOC_EVENTS_CLEAR
,
109 #define IOC_INPUT_TEST(ioc, name, req, opt, err) \
110 IOC_INPUT_TEST_IMPL(ioc, name, req, opt, err, B_FALSE)
112 #define IOC_INPUT_TEST_WILD(ioc, name, req, opt, err) \
113 IOC_INPUT_TEST_IMPL(ioc, name, req, opt, err, B_TRUE)
115 #define IOC_INPUT_TEST_IMPL(ioc, name, req, opt, err, wild) \
117 active_test = __func__ + 5; \
118 ioc_tested[ioc - ZFS_IOC_FIRST] = B_TRUE; \
119 lzc_ioctl_test(ioc, name, req, opt, err, wild); \
123 * run a zfs ioctl command, verify expected results and log failures
126 lzc_ioctl_run(zfs_ioc_t ioc
, const char *name
, nvlist_t
*innvl
, int expected
)
128 zfs_cmd_t zc
= {"\0"};
135 case ZFS_ERR_IOC_ARG_UNAVAIL
:
136 variant
= "unsupported input";
138 case ZFS_ERR_IOC_ARG_REQUIRED
:
139 variant
= "missing input";
141 case ZFS_ERR_IOC_ARG_BADTYPE
:
142 variant
= "invalid input type";
145 variant
= "valid input";
149 packed
= fnvlist_pack(innvl
, &size
);
150 (void) strlcpy(zc
.zc_name
, name
, sizeof (zc
.zc_name
));
151 zc
.zc_name
[sizeof (zc
.zc_name
) - 1] = '\0';
152 zc
.zc_nvlist_src
= (uint64_t)(uintptr_t)packed
;
153 zc
.zc_nvlist_src_size
= size
;
154 zc
.zc_nvlist_dst_size
= MAX(size
* 2, 128 * 1024);
155 zc
.zc_nvlist_dst
= (uint64_t)(uintptr_t)malloc(zc
.zc_nvlist_dst_size
);
157 if (ioctl(zfs_fd
, ioc
, &zc
) != 0)
160 if (error
!= expected
) {
161 unexpected_failures
= B_TRUE
;
162 (void) fprintf(stderr
, "%s: Unexpected result with %s, "
163 "error %d (expecting %d)\n",
164 active_test
, variant
, error
, expected
);
167 fnvlist_pack_free(packed
, size
);
168 free((void *)(uintptr_t)zc
.zc_nvlist_dst
);
172 * Test each ioc for the following ioctl input errors:
173 * ZFS_ERR_IOC_ARG_UNAVAIL an input argument is not supported by kernel
174 * ZFS_ERR_IOC_ARG_REQUIRED a required input argument is missing
175 * ZFS_ERR_IOC_ARG_BADTYPE an input argument has an invalid type
178 lzc_ioctl_test(zfs_ioc_t ioc
, const char *name
, nvlist_t
*required
,
179 nvlist_t
*optional
, int expected_error
, boolean_t wildcard
)
181 nvlist_t
*input
= fnvlist_alloc();
182 nvlist_t
*future
= fnvlist_alloc();
185 if (required
!= NULL
) {
186 for (nvpair_t
*pair
= nvlist_next_nvpair(required
, NULL
);
187 pair
!= NULL
; pair
= nvlist_next_nvpair(required
, pair
)) {
188 fnvlist_add_nvpair(input
, pair
);
191 if (optional
!= NULL
) {
192 for (nvpair_t
*pair
= nvlist_next_nvpair(optional
, NULL
);
193 pair
!= NULL
; pair
= nvlist_next_nvpair(optional
, pair
)) {
194 fnvlist_add_nvpair(input
, pair
);
199 * Generic input run with 'optional' nvlist pair
202 fnvlist_add_nvlist(input
, "optional", future
);
203 lzc_ioctl_run(ioc
, name
, input
, expected_error
);
205 fnvlist_remove(input
, "optional");
211 fnvlist_add_string(input
, "bogus_input", "bogus");
212 lzc_ioctl_run(ioc
, name
, input
, ZFS_ERR_IOC_ARG_UNAVAIL
);
213 fnvlist_remove(input
, "bogus_input");
217 * Missing required inputs
219 if (required
!= NULL
) {
220 nvlist_t
*empty
= fnvlist_alloc();
221 lzc_ioctl_run(ioc
, name
, empty
, ZFS_ERR_IOC_ARG_REQUIRED
);
228 if (required
!= NULL
|| optional
!= NULL
) {
230 * switch the type of one of the input pairs
232 for (nvpair_t
*pair
= nvlist_next_nvpair(input
, NULL
);
233 pair
!= NULL
; pair
= nvlist_next_nvpair(input
, pair
)) {
234 char pname
[MAXNAMELEN
];
237 strlcpy(pname
, nvpair_name(pair
), sizeof (pname
));
238 pname
[sizeof (pname
) - 1] = '\0';
239 ptype
= nvpair_type(pair
);
240 fnvlist_remove_nvpair(input
, pair
);
243 case DATA_TYPE_STRING
:
244 fnvlist_add_uint64(input
, pname
, 42);
247 fnvlist_add_string(input
, pname
, "bogus");
251 lzc_ioctl_run(ioc
, name
, input
, ZFS_ERR_IOC_ARG_BADTYPE
);
261 test_pool_sync(const char *pool
)
263 nvlist_t
*required
= fnvlist_alloc();
265 fnvlist_add_boolean_value(required
, "force", B_TRUE
);
267 IOC_INPUT_TEST(ZFS_IOC_POOL_SYNC
, pool
, required
, NULL
, 0);
269 nvlist_free(required
);
273 test_pool_reopen(const char *pool
)
275 nvlist_t
*required
= fnvlist_alloc();
277 fnvlist_add_boolean_value(required
, "scrub_restart", B_FALSE
);
279 IOC_INPUT_TEST(ZFS_IOC_POOL_REOPEN
, pool
, required
, NULL
, 0);
281 nvlist_free(required
);
285 test_pool_checkpoint(const char *pool
)
287 IOC_INPUT_TEST(ZFS_IOC_POOL_CHECKPOINT
, pool
, NULL
, NULL
, 0);
291 test_pool_discard_checkpoint(const char *pool
)
293 int err
= lzc_pool_checkpoint(pool
);
294 if (err
== 0 || err
== ZFS_ERR_CHECKPOINT_EXISTS
)
295 IOC_INPUT_TEST(ZFS_IOC_POOL_DISCARD_CHECKPOINT
, pool
, NULL
,
300 test_log_history(const char *pool
)
302 nvlist_t
*required
= fnvlist_alloc();
304 fnvlist_add_string(required
, "message", "input check");
306 IOC_INPUT_TEST(ZFS_IOC_LOG_HISTORY
, pool
, required
, NULL
, 0);
308 nvlist_free(required
);
312 test_create(const char *pool
)
314 char dataset
[MAXNAMELEN
+ 32];
316 (void) snprintf(dataset
, sizeof (dataset
), "%s/create-fs", pool
);
318 nvlist_t
*required
= fnvlist_alloc();
319 nvlist_t
*optional
= fnvlist_alloc();
320 nvlist_t
*props
= fnvlist_alloc();
322 fnvlist_add_int32(required
, "type", DMU_OST_ZFS
);
323 fnvlist_add_uint64(props
, "recordsize", 8192);
324 fnvlist_add_nvlist(optional
, "props", props
);
326 IOC_INPUT_TEST(ZFS_IOC_CREATE
, dataset
, required
, optional
, 0);
328 nvlist_free(required
);
329 nvlist_free(optional
);
333 test_snapshot(const char *pool
, const char *snapshot
)
335 nvlist_t
*required
= fnvlist_alloc();
336 nvlist_t
*optional
= fnvlist_alloc();
337 nvlist_t
*snaps
= fnvlist_alloc();
338 nvlist_t
*props
= fnvlist_alloc();
340 fnvlist_add_boolean(snaps
, snapshot
);
341 fnvlist_add_nvlist(required
, "snaps", snaps
);
343 fnvlist_add_string(props
, "org.openzfs:launch", "September 17th, 2013");
344 fnvlist_add_nvlist(optional
, "props", props
);
346 IOC_INPUT_TEST(ZFS_IOC_SNAPSHOT
, pool
, required
, optional
, 0);
350 nvlist_free(optional
);
351 nvlist_free(required
);
355 test_space_snaps(const char *snapshot
)
357 nvlist_t
*required
= fnvlist_alloc();
358 fnvlist_add_string(required
, "firstsnap", snapshot
);
360 IOC_INPUT_TEST(ZFS_IOC_SPACE_SNAPS
, snapshot
, required
, NULL
, 0);
362 nvlist_free(required
);
366 test_destroy_snaps(const char *pool
, const char *snapshot
)
368 nvlist_t
*required
= fnvlist_alloc();
369 nvlist_t
*snaps
= fnvlist_alloc();
371 fnvlist_add_boolean(snaps
, snapshot
);
372 fnvlist_add_nvlist(required
, "snaps", snaps
);
374 IOC_INPUT_TEST(ZFS_IOC_DESTROY_SNAPS
, pool
, required
, NULL
, 0);
377 nvlist_free(required
);
382 test_bookmark(const char *pool
, const char *snapshot
, const char *bookmark
)
384 nvlist_t
*required
= fnvlist_alloc();
386 fnvlist_add_string(required
, bookmark
, snapshot
);
388 IOC_INPUT_TEST_WILD(ZFS_IOC_BOOKMARK
, pool
, required
, NULL
, 0);
390 nvlist_free(required
);
394 test_get_bookmarks(const char *dataset
)
396 nvlist_t
*optional
= fnvlist_alloc();
398 fnvlist_add_boolean(optional
, "guid");
399 fnvlist_add_boolean(optional
, "createtxg");
400 fnvlist_add_boolean(optional
, "creation");
402 IOC_INPUT_TEST_WILD(ZFS_IOC_GET_BOOKMARKS
, dataset
, NULL
, optional
, 0);
404 nvlist_free(optional
);
408 test_destroy_bookmarks(const char *pool
, const char *bookmark
)
410 nvlist_t
*required
= fnvlist_alloc();
412 fnvlist_add_boolean(required
, bookmark
);
414 IOC_INPUT_TEST_WILD(ZFS_IOC_DESTROY_BOOKMARKS
, pool
, required
, NULL
, 0);
416 nvlist_free(required
);
420 test_clone(const char *snapshot
, const char *clone
)
422 nvlist_t
*required
= fnvlist_alloc();
423 nvlist_t
*optional
= fnvlist_alloc();
424 nvlist_t
*props
= fnvlist_alloc();
426 fnvlist_add_string(required
, "origin", snapshot
);
428 IOC_INPUT_TEST(ZFS_IOC_CLONE
, clone
, required
, NULL
, 0);
431 nvlist_free(optional
);
432 nvlist_free(required
);
436 test_rollback(const char *dataset
, const char *snapshot
)
438 nvlist_t
*optional
= fnvlist_alloc();
440 fnvlist_add_string(optional
, "target", snapshot
);
442 IOC_INPUT_TEST(ZFS_IOC_ROLLBACK
, dataset
, NULL
, optional
, B_FALSE
);
444 nvlist_free(optional
);
448 test_hold(const char *pool
, const char *snapshot
)
450 nvlist_t
*required
= fnvlist_alloc();
451 nvlist_t
*optional
= fnvlist_alloc();
452 nvlist_t
*holds
= fnvlist_alloc();
454 fnvlist_add_string(holds
, snapshot
, "libzfs_check_hold");
455 fnvlist_add_nvlist(required
, "holds", holds
);
456 fnvlist_add_int32(optional
, "cleanup_fd", zfs_fd
);
458 IOC_INPUT_TEST(ZFS_IOC_HOLD
, pool
, required
, optional
, 0);
461 nvlist_free(optional
);
462 nvlist_free(required
);
466 test_get_holds(const char *snapshot
)
468 IOC_INPUT_TEST(ZFS_IOC_GET_HOLDS
, snapshot
, NULL
, NULL
, 0);
472 test_release(const char *pool
, const char *snapshot
)
474 nvlist_t
*required
= fnvlist_alloc();
475 nvlist_t
*release
= fnvlist_alloc();
477 fnvlist_add_boolean(release
, "libzfs_check_hold");
478 fnvlist_add_nvlist(required
, snapshot
, release
);
480 IOC_INPUT_TEST_WILD(ZFS_IOC_RELEASE
, pool
, required
, NULL
, 0);
482 nvlist_free(release
);
483 nvlist_free(required
);
488 test_send_new(const char *snapshot
, int fd
)
490 nvlist_t
*required
= fnvlist_alloc();
491 nvlist_t
*optional
= fnvlist_alloc();
493 fnvlist_add_int32(required
, "fd", fd
);
495 fnvlist_add_boolean(optional
, "largeblockok");
496 fnvlist_add_boolean(optional
, "embedok");
497 fnvlist_add_boolean(optional
, "compressok");
498 fnvlist_add_boolean(optional
, "rawok");
501 * TODO - Resumable send is harder to set up. So we currently
502 * ignore testing for that variant.
505 fnvlist_add_string(optional
, "fromsnap", from
);
506 fnvlist_add_uint64(optional
, "resume_object", resumeobj
);
507 fnvlist_add_uint64(optional
, "resume_offset", offset
);
509 IOC_INPUT_TEST(ZFS_IOC_SEND_NEW
, snapshot
, required
, optional
, 0);
511 nvlist_free(optional
);
512 nvlist_free(required
);
516 test_recv_new(const char *dataset
, int fd
)
518 dmu_replay_record_t drr
= { 0 };
519 nvlist_t
*required
= fnvlist_alloc();
520 nvlist_t
*optional
= fnvlist_alloc();
521 nvlist_t
*props
= fnvlist_alloc();
522 char snapshot
[MAXNAMELEN
+ 32];
525 int cleanup_fd
= open(ZFS_DEV
, O_RDWR
);
527 (void) snprintf(snapshot
, sizeof (snapshot
), "%s@replicant", dataset
);
529 count
= pread(fd
, &drr
, sizeof (drr
), 0);
530 if (count
!= sizeof (drr
)) {
531 (void) fprintf(stderr
, "could not read stream: %s\n",
535 fnvlist_add_string(required
, "snapname", snapshot
);
536 fnvlist_add_byte_array(required
, "begin_record", (uchar_t
*)&drr
,
538 fnvlist_add_int32(required
, "input_fd", fd
);
540 fnvlist_add_string(props
, "org.openzfs:launch", "September 17th, 2013");
541 fnvlist_add_nvlist(optional
, "localprops", props
);
542 fnvlist_add_boolean(optional
, "force");
543 fnvlist_add_int32(optional
, "cleanup_fd", cleanup_fd
);
546 * TODO - Resumable receive is harder to set up. So we currently
547 * ignore testing for one.
550 fnvlist_add_nvlist(optional
, "props", recvdprops
);
551 fnvlist_add_string(optional
, "origin", origin
);
552 fnvlist_add_boolean(optional
, "resumable");
553 fnvlist_add_uint64(optional
, "action_handle", *action_handle
);
555 IOC_INPUT_TEST(ZFS_IOC_RECV_NEW
, dataset
, required
, optional
, EBADE
);
558 nvlist_free(optional
);
559 nvlist_free(required
);
561 (void) close(cleanup_fd
);
565 test_send_space(const char *snapshot1
, const char *snapshot2
)
567 nvlist_t
*optional
= fnvlist_alloc();
569 fnvlist_add_string(optional
, "from", snapshot1
);
570 fnvlist_add_boolean(optional
, "largeblockok");
571 fnvlist_add_boolean(optional
, "embedok");
572 fnvlist_add_boolean(optional
, "compressok");
573 fnvlist_add_boolean(optional
, "rawok");
575 IOC_INPUT_TEST(ZFS_IOC_SEND_SPACE
, snapshot2
, NULL
, optional
, 0);
577 nvlist_free(optional
);
581 test_remap(const char *dataset
)
583 IOC_INPUT_TEST(ZFS_IOC_REMAP
, dataset
, NULL
, NULL
, 0);
587 test_channel_program(const char *pool
)
589 const char *program
=
591 "argv = arg[\"argv\"]\n"
593 char *const argv
[1] = { "Hello World!" };
594 nvlist_t
*required
= fnvlist_alloc();
595 nvlist_t
*optional
= fnvlist_alloc();
596 nvlist_t
*args
= fnvlist_alloc();
598 fnvlist_add_string(required
, "program", program
);
599 fnvlist_add_string_array(args
, "argv", argv
, 1);
600 fnvlist_add_nvlist(required
, "arg", args
);
602 fnvlist_add_boolean_value(optional
, "sync", B_TRUE
);
603 fnvlist_add_uint64(optional
, "instrlimit", 1000 * 1000);
604 fnvlist_add_uint64(optional
, "memlimit", 8192 * 1024);
606 IOC_INPUT_TEST(ZFS_IOC_CHANNEL_PROGRAM
, pool
, required
, optional
, 0);
609 nvlist_free(optional
);
610 nvlist_free(required
);
613 #define WRAPPING_KEY_LEN 32
616 test_load_key(const char *dataset
)
618 nvlist_t
*required
= fnvlist_alloc();
619 nvlist_t
*optional
= fnvlist_alloc();
620 nvlist_t
*hidden
= fnvlist_alloc();
621 uint8_t keydata
[WRAPPING_KEY_LEN
] = {0};
623 fnvlist_add_uint8_array(hidden
, "wkeydata", keydata
, sizeof (keydata
));
624 fnvlist_add_nvlist(required
, "hidden_args", hidden
);
625 fnvlist_add_boolean(optional
, "noop");
627 IOC_INPUT_TEST(ZFS_IOC_LOAD_KEY
, dataset
, required
, optional
, EINVAL
);
629 nvlist_free(optional
);
630 nvlist_free(required
);
634 test_change_key(const char *dataset
)
636 IOC_INPUT_TEST(ZFS_IOC_CHANGE_KEY
, dataset
, NULL
, NULL
, EINVAL
);
640 test_unload_key(const char *dataset
)
642 IOC_INPUT_TEST(ZFS_IOC_UNLOAD_KEY
, dataset
, NULL
, NULL
, EACCES
);
646 test_vdev_initialize(const char *pool
)
648 nvlist_t
*required
= fnvlist_alloc();
649 nvlist_t
*vdev_guids
= fnvlist_alloc();
651 fnvlist_add_uint64(vdev_guids
, "path", 0xdeadbeefdeadbeef);
652 fnvlist_add_uint64(required
, ZPOOL_INITIALIZE_COMMAND
,
653 POOL_INITIALIZE_START
);
654 fnvlist_add_nvlist(required
, ZPOOL_INITIALIZE_VDEVS
, vdev_guids
);
656 IOC_INPUT_TEST(ZFS_IOC_POOL_INITIALIZE
, pool
, required
, NULL
, EINVAL
);
657 nvlist_free(vdev_guids
);
658 nvlist_free(required
);
662 test_vdev_trim(const char *pool
)
664 nvlist_t
*required
= fnvlist_alloc();
665 nvlist_t
*optional
= fnvlist_alloc();
666 nvlist_t
*vdev_guids
= fnvlist_alloc();
668 fnvlist_add_uint64(vdev_guids
, "path", 0xdeadbeefdeadbeef);
669 fnvlist_add_uint64(required
, ZPOOL_TRIM_COMMAND
, POOL_TRIM_START
);
670 fnvlist_add_nvlist(required
, ZPOOL_TRIM_VDEVS
, vdev_guids
);
671 fnvlist_add_uint64(optional
, ZPOOL_TRIM_RATE
, 1ULL << 30);
672 fnvlist_add_boolean_value(optional
, ZPOOL_TRIM_SECURE
, B_TRUE
);
674 IOC_INPUT_TEST(ZFS_IOC_POOL_TRIM
, pool
, required
, optional
, EINVAL
);
675 nvlist_free(vdev_guids
);
676 nvlist_free(optional
);
677 nvlist_free(required
);
681 zfs_destroy(const char *dataset
)
683 zfs_cmd_t zc
= {"\0"};
686 (void) strlcpy(zc
.zc_name
, dataset
, sizeof (zc
.zc_name
));
687 zc
.zc_name
[sizeof (zc
.zc_name
) - 1] = '\0';
688 err
= ioctl(zfs_fd
, ZFS_IOC_DESTROY
, &zc
);
690 return (err
== 0 ? 0 : errno
);
694 test_redact(const char *snapshot1
, const char *snapshot2
)
696 nvlist_t
*required
= fnvlist_alloc();
697 nvlist_t
*snapnv
= fnvlist_alloc();
698 char bookmark
[MAXNAMELEN
+ 32];
700 fnvlist_add_string(required
, "bookname", "testbookmark");
701 fnvlist_add_boolean(snapnv
, snapshot2
);
702 fnvlist_add_nvlist(required
, "snapnv", snapnv
);
704 IOC_INPUT_TEST(ZFS_IOC_REDACT
, snapshot1
, required
, NULL
, 0);
707 nvlist_free(required
);
709 strlcpy(bookmark
, snapshot1
, sizeof (bookmark
));
710 *strchr(bookmark
, '@') = '\0';
711 strlcat(bookmark
, "#testbookmark", sizeof (bookmark
) -
713 zfs_destroy(bookmark
);
717 test_get_bookmark_props(const char *bookmark
)
719 IOC_INPUT_TEST(ZFS_IOC_GET_BOOKMARK_PROPS
, bookmark
, NULL
, NULL
, 0);
723 zfs_ioc_input_tests(const char *pool
)
725 char filepath
[] = "/tmp/ioc_test_file_XXXXXX";
726 char dataset
[ZFS_MAX_DATASET_NAME_LEN
];
727 char snapbase
[ZFS_MAX_DATASET_NAME_LEN
+ 32];
728 char snapshot
[ZFS_MAX_DATASET_NAME_LEN
+ 32];
729 char bookmark
[ZFS_MAX_DATASET_NAME_LEN
+ 32];
730 char backup
[ZFS_MAX_DATASET_NAME_LEN
];
731 char clone
[ZFS_MAX_DATASET_NAME_LEN
];
732 char clonesnap
[ZFS_MAX_DATASET_NAME_LEN
+ 32];
736 * Setup names and create a working dataset
738 (void) snprintf(dataset
, sizeof (dataset
), "%s/test-fs", pool
);
739 (void) snprintf(snapbase
, sizeof (snapbase
), "%s@snapbase", dataset
);
740 (void) snprintf(snapshot
, sizeof (snapshot
), "%s@snapshot", dataset
);
741 (void) snprintf(bookmark
, sizeof (bookmark
), "%s#bookmark", dataset
);
742 (void) snprintf(clone
, sizeof (clone
), "%s/test-fs-clone", pool
);
743 (void) snprintf(clonesnap
, sizeof (clonesnap
), "%s@snap", clone
);
744 (void) snprintf(backup
, sizeof (backup
), "%s/backup", pool
);
746 err
= lzc_create(dataset
, DMU_OST_ZFS
, NULL
, NULL
, 0);
748 (void) fprintf(stderr
, "could not create '%s': %s\n",
749 dataset
, strerror(errno
));
753 tmpfd
= mkstemp(filepath
);
755 (void) fprintf(stderr
, "could not create '%s': %s\n",
756 filepath
, strerror(errno
));
761 * run a test for each ioctl
762 * Note that some test build on previous test operations
764 test_pool_sync(pool
);
765 test_pool_reopen(pool
);
766 test_pool_checkpoint(pool
);
767 test_pool_discard_checkpoint(pool
);
768 test_log_history(pool
);
770 test_create(dataset
);
771 test_snapshot(pool
, snapbase
);
772 test_snapshot(pool
, snapshot
);
774 test_space_snaps(snapshot
);
775 test_send_space(snapbase
, snapshot
);
776 test_send_new(snapshot
, tmpfd
);
777 test_recv_new(backup
, tmpfd
);
779 test_bookmark(pool
, snapshot
, bookmark
);
780 test_get_bookmarks(dataset
);
781 test_get_bookmark_props(bookmark
);
782 test_destroy_bookmarks(pool
, bookmark
);
784 test_hold(pool
, snapshot
);
785 test_get_holds(snapshot
);
786 test_release(pool
, snapshot
);
788 test_clone(snapshot
, clone
);
789 test_snapshot(pool
, clonesnap
);
790 test_redact(snapshot
, clonesnap
);
791 zfs_destroy(clonesnap
);
794 test_rollback(dataset
, snapshot
);
795 test_destroy_snaps(pool
, snapshot
);
796 test_destroy_snaps(pool
, snapbase
);
799 test_channel_program(pool
);
801 test_load_key(dataset
);
802 test_change_key(dataset
);
803 test_unload_key(dataset
);
805 test_vdev_initialize(pool
);
806 test_vdev_trim(pool
);
811 zfs_cmd_t zc
= {"\0"};
813 nvlist_t
*snaps
= fnvlist_alloc();
814 fnvlist_add_boolean(snaps
, snapshot
);
815 (void) lzc_destroy_snaps(snaps
, B_FALSE
, NULL
);
818 (void) zfs_destroy(dataset
);
819 (void) zfs_destroy(backup
);
822 (void) unlink(filepath
);
825 * All the unused slots should yield ZFS_ERR_IOC_CMD_UNAVAIL
827 for (int i
= 0; i
< ARRAY_SIZE(ioc_skip
); i
++) {
828 if (ioc_tested
[ioc_skip
[i
] - ZFS_IOC_FIRST
])
829 (void) fprintf(stderr
, "cmd %d tested, not skipped!\n",
830 (int)(ioc_skip
[i
] - ZFS_IOC_FIRST
));
832 ioc_tested
[ioc_skip
[i
] - ZFS_IOC_FIRST
] = B_TRUE
;
835 (void) strlcpy(zc
.zc_name
, pool
, sizeof (zc
.zc_name
));
836 zc
.zc_name
[sizeof (zc
.zc_name
) - 1] = '\0';
838 for (unsigned ioc
= ZFS_IOC_FIRST
; ioc
< ZFS_IOC_LAST
; ioc
++) {
839 unsigned cmd
= ioc
- ZFS_IOC_FIRST
;
844 if (ioctl(zfs_fd
, ioc
, &zc
) != 0 &&
845 errno
!= ZFS_ERR_IOC_CMD_UNAVAIL
) {
846 (void) fprintf(stderr
, "cmd %d is missing a test case "
847 "(%d)\n", cmd
, errno
);
853 ZFS_IOC_BASE
= ('Z' << 8),
854 LINUX_IOC_BASE
= ('Z' << 8) + 0x80,
855 FREEBSD_IOC_BASE
= ('Z' << 8) + 0xC0,
859 * Canonical reference check of /dev/zfs ioctl numbers.
860 * These cannot change and new ioctl numbers must be appended.
863 validate_ioc_values(void)
865 boolean_t result
= TRUE
;
867 #define CHECK(expr) do { \
870 fprintf(stderr, "(%s) === FALSE\n", #expr); \
874 CHECK(ZFS_IOC_BASE
+ 0 == ZFS_IOC_POOL_CREATE
);
875 CHECK(ZFS_IOC_BASE
+ 1 == ZFS_IOC_POOL_DESTROY
);
876 CHECK(ZFS_IOC_BASE
+ 2 == ZFS_IOC_POOL_IMPORT
);
877 CHECK(ZFS_IOC_BASE
+ 3 == ZFS_IOC_POOL_EXPORT
);
878 CHECK(ZFS_IOC_BASE
+ 4 == ZFS_IOC_POOL_CONFIGS
);
879 CHECK(ZFS_IOC_BASE
+ 5 == ZFS_IOC_POOL_STATS
);
880 CHECK(ZFS_IOC_BASE
+ 6 == ZFS_IOC_POOL_TRYIMPORT
);
881 CHECK(ZFS_IOC_BASE
+ 7 == ZFS_IOC_POOL_SCAN
);
882 CHECK(ZFS_IOC_BASE
+ 8 == ZFS_IOC_POOL_FREEZE
);
883 CHECK(ZFS_IOC_BASE
+ 9 == ZFS_IOC_POOL_UPGRADE
);
884 CHECK(ZFS_IOC_BASE
+ 10 == ZFS_IOC_POOL_GET_HISTORY
);
885 CHECK(ZFS_IOC_BASE
+ 11 == ZFS_IOC_VDEV_ADD
);
886 CHECK(ZFS_IOC_BASE
+ 12 == ZFS_IOC_VDEV_REMOVE
);
887 CHECK(ZFS_IOC_BASE
+ 13 == ZFS_IOC_VDEV_SET_STATE
);
888 CHECK(ZFS_IOC_BASE
+ 14 == ZFS_IOC_VDEV_ATTACH
);
889 CHECK(ZFS_IOC_BASE
+ 15 == ZFS_IOC_VDEV_DETACH
);
890 CHECK(ZFS_IOC_BASE
+ 16 == ZFS_IOC_VDEV_SETPATH
);
891 CHECK(ZFS_IOC_BASE
+ 17 == ZFS_IOC_VDEV_SETFRU
);
892 CHECK(ZFS_IOC_BASE
+ 18 == ZFS_IOC_OBJSET_STATS
);
893 CHECK(ZFS_IOC_BASE
+ 19 == ZFS_IOC_OBJSET_ZPLPROPS
);
894 CHECK(ZFS_IOC_BASE
+ 20 == ZFS_IOC_DATASET_LIST_NEXT
);
895 CHECK(ZFS_IOC_BASE
+ 21 == ZFS_IOC_SNAPSHOT_LIST_NEXT
);
896 CHECK(ZFS_IOC_BASE
+ 22 == ZFS_IOC_SET_PROP
);
897 CHECK(ZFS_IOC_BASE
+ 23 == ZFS_IOC_CREATE
);
898 CHECK(ZFS_IOC_BASE
+ 24 == ZFS_IOC_DESTROY
);
899 CHECK(ZFS_IOC_BASE
+ 25 == ZFS_IOC_ROLLBACK
);
900 CHECK(ZFS_IOC_BASE
+ 26 == ZFS_IOC_RENAME
);
901 CHECK(ZFS_IOC_BASE
+ 27 == ZFS_IOC_RECV
);
902 CHECK(ZFS_IOC_BASE
+ 28 == ZFS_IOC_SEND
);
903 CHECK(ZFS_IOC_BASE
+ 29 == ZFS_IOC_INJECT_FAULT
);
904 CHECK(ZFS_IOC_BASE
+ 30 == ZFS_IOC_CLEAR_FAULT
);
905 CHECK(ZFS_IOC_BASE
+ 31 == ZFS_IOC_INJECT_LIST_NEXT
);
906 CHECK(ZFS_IOC_BASE
+ 32 == ZFS_IOC_ERROR_LOG
);
907 CHECK(ZFS_IOC_BASE
+ 33 == ZFS_IOC_CLEAR
);
908 CHECK(ZFS_IOC_BASE
+ 34 == ZFS_IOC_PROMOTE
);
909 CHECK(ZFS_IOC_BASE
+ 35 == ZFS_IOC_SNAPSHOT
);
910 CHECK(ZFS_IOC_BASE
+ 36 == ZFS_IOC_DSOBJ_TO_DSNAME
);
911 CHECK(ZFS_IOC_BASE
+ 37 == ZFS_IOC_OBJ_TO_PATH
);
912 CHECK(ZFS_IOC_BASE
+ 38 == ZFS_IOC_POOL_SET_PROPS
);
913 CHECK(ZFS_IOC_BASE
+ 39 == ZFS_IOC_POOL_GET_PROPS
);
914 CHECK(ZFS_IOC_BASE
+ 40 == ZFS_IOC_SET_FSACL
);
915 CHECK(ZFS_IOC_BASE
+ 41 == ZFS_IOC_GET_FSACL
);
916 CHECK(ZFS_IOC_BASE
+ 42 == ZFS_IOC_SHARE
);
917 CHECK(ZFS_IOC_BASE
+ 43 == ZFS_IOC_INHERIT_PROP
);
918 CHECK(ZFS_IOC_BASE
+ 44 == ZFS_IOC_SMB_ACL
);
919 CHECK(ZFS_IOC_BASE
+ 45 == ZFS_IOC_USERSPACE_ONE
);
920 CHECK(ZFS_IOC_BASE
+ 46 == ZFS_IOC_USERSPACE_MANY
);
921 CHECK(ZFS_IOC_BASE
+ 47 == ZFS_IOC_USERSPACE_UPGRADE
);
922 CHECK(ZFS_IOC_BASE
+ 48 == ZFS_IOC_HOLD
);
923 CHECK(ZFS_IOC_BASE
+ 49 == ZFS_IOC_RELEASE
);
924 CHECK(ZFS_IOC_BASE
+ 50 == ZFS_IOC_GET_HOLDS
);
925 CHECK(ZFS_IOC_BASE
+ 51 == ZFS_IOC_OBJSET_RECVD_PROPS
);
926 CHECK(ZFS_IOC_BASE
+ 52 == ZFS_IOC_VDEV_SPLIT
);
927 CHECK(ZFS_IOC_BASE
+ 53 == ZFS_IOC_NEXT_OBJ
);
928 CHECK(ZFS_IOC_BASE
+ 54 == ZFS_IOC_DIFF
);
929 CHECK(ZFS_IOC_BASE
+ 55 == ZFS_IOC_TMP_SNAPSHOT
);
930 CHECK(ZFS_IOC_BASE
+ 56 == ZFS_IOC_OBJ_TO_STATS
);
931 CHECK(ZFS_IOC_BASE
+ 57 == ZFS_IOC_SPACE_WRITTEN
);
932 CHECK(ZFS_IOC_BASE
+ 58 == ZFS_IOC_SPACE_SNAPS
);
933 CHECK(ZFS_IOC_BASE
+ 59 == ZFS_IOC_DESTROY_SNAPS
);
934 CHECK(ZFS_IOC_BASE
+ 60 == ZFS_IOC_POOL_REGUID
);
935 CHECK(ZFS_IOC_BASE
+ 61 == ZFS_IOC_POOL_REOPEN
);
936 CHECK(ZFS_IOC_BASE
+ 62 == ZFS_IOC_SEND_PROGRESS
);
937 CHECK(ZFS_IOC_BASE
+ 63 == ZFS_IOC_LOG_HISTORY
);
938 CHECK(ZFS_IOC_BASE
+ 64 == ZFS_IOC_SEND_NEW
);
939 CHECK(ZFS_IOC_BASE
+ 65 == ZFS_IOC_SEND_SPACE
);
940 CHECK(ZFS_IOC_BASE
+ 66 == ZFS_IOC_CLONE
);
941 CHECK(ZFS_IOC_BASE
+ 67 == ZFS_IOC_BOOKMARK
);
942 CHECK(ZFS_IOC_BASE
+ 68 == ZFS_IOC_GET_BOOKMARKS
);
943 CHECK(ZFS_IOC_BASE
+ 69 == ZFS_IOC_DESTROY_BOOKMARKS
);
944 CHECK(ZFS_IOC_BASE
+ 70 == ZFS_IOC_RECV_NEW
);
945 CHECK(ZFS_IOC_BASE
+ 71 == ZFS_IOC_POOL_SYNC
);
946 CHECK(ZFS_IOC_BASE
+ 72 == ZFS_IOC_CHANNEL_PROGRAM
);
947 CHECK(ZFS_IOC_BASE
+ 73 == ZFS_IOC_LOAD_KEY
);
948 CHECK(ZFS_IOC_BASE
+ 74 == ZFS_IOC_UNLOAD_KEY
);
949 CHECK(ZFS_IOC_BASE
+ 75 == ZFS_IOC_CHANGE_KEY
);
950 CHECK(ZFS_IOC_BASE
+ 76 == ZFS_IOC_REMAP
);
951 CHECK(ZFS_IOC_BASE
+ 77 == ZFS_IOC_POOL_CHECKPOINT
);
952 CHECK(ZFS_IOC_BASE
+ 78 == ZFS_IOC_POOL_DISCARD_CHECKPOINT
);
953 CHECK(ZFS_IOC_BASE
+ 79 == ZFS_IOC_POOL_INITIALIZE
);
954 CHECK(ZFS_IOC_BASE
+ 80 == ZFS_IOC_POOL_TRIM
);
955 CHECK(ZFS_IOC_BASE
+ 81 == ZFS_IOC_REDACT
);
956 CHECK(ZFS_IOC_BASE
+ 82 == ZFS_IOC_GET_BOOKMARK_PROPS
);
957 CHECK(LINUX_IOC_BASE
+ 1 == ZFS_IOC_EVENTS_NEXT
);
958 CHECK(LINUX_IOC_BASE
+ 2 == ZFS_IOC_EVENTS_CLEAR
);
959 CHECK(LINUX_IOC_BASE
+ 3 == ZFS_IOC_EVENTS_SEEK
);
967 main(int argc
, const char *argv
[])
970 (void) fprintf(stderr
, "usage: %s <pool>\n", argv
[0]);
974 if (!validate_ioc_values()) {
975 (void) fprintf(stderr
, "WARNING: zfs_ioc_t has binary "
976 "incompatible command values\n");
980 (void) libzfs_core_init();
981 zfs_fd
= open(ZFS_DEV
, O_RDWR
);
983 (void) fprintf(stderr
, "open: %s\n", strerror(errno
));
988 zfs_ioc_input_tests(argv
[1]);
990 (void) close(zfs_fd
);
993 return (unexpected_failures
);