]>
Commit | Line | Data |
---|---|---|
b83a0e2d DB |
1 | /* |
2 | * CDDL HEADER START | |
3 | * | |
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 | |
7 | * 1.0 of the CDDL. | |
8 | * | |
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. | |
12 | * | |
13 | * CDDL HEADER END | |
14 | */ | |
15 | ||
16 | /* | |
17 | * Copyright (c) 2018 by Delphix. All rights reserved. | |
18 | */ | |
19 | ||
20 | #include <stdio.h> | |
21 | #include <stdlib.h> | |
22 | #include <string.h> | |
b83a0e2d | 23 | #include <libzfs_core.h> |
054a0498 | 24 | #include <libzutil.h> |
b83a0e2d DB |
25 | |
26 | #include <sys/nvpair.h> | |
1db9e6e4 | 27 | #include <sys/vdev_impl.h> |
b83a0e2d | 28 | #include <sys/zfs_ioctl.h> |
1db9e6e4 | 29 | #include <sys/zfs_bootenv.h> |
b83a0e2d DB |
30 | |
31 | /* | |
32 | * Test the nvpair inputs for the non-legacy zfs ioctl commands. | |
33 | */ | |
34 | ||
d465fc58 AZ |
35 | static boolean_t unexpected_failures; |
36 | static int zfs_fd; | |
37 | static const char *active_test; | |
b83a0e2d DB |
38 | |
39 | /* | |
40 | * Tracks which zfs_ioc_t commands were tested | |
41 | */ | |
d465fc58 | 42 | static boolean_t ioc_tested[ZFS_IOC_LAST - ZFS_IOC_FIRST]; |
b83a0e2d DB |
43 | |
44 | /* | |
45 | * Legacy ioctls that are skipped (for now) | |
46 | */ | |
d465fc58 | 47 | static const zfs_ioc_t ioc_skip[] = { |
b83a0e2d DB |
48 | ZFS_IOC_POOL_CREATE, |
49 | ZFS_IOC_POOL_DESTROY, | |
50 | ZFS_IOC_POOL_IMPORT, | |
51 | ZFS_IOC_POOL_EXPORT, | |
52 | ZFS_IOC_POOL_CONFIGS, | |
53 | ZFS_IOC_POOL_STATS, | |
54 | ZFS_IOC_POOL_TRYIMPORT, | |
55 | ZFS_IOC_POOL_SCAN, | |
56 | ZFS_IOC_POOL_FREEZE, | |
57 | ZFS_IOC_POOL_UPGRADE, | |
58 | ZFS_IOC_POOL_GET_HISTORY, | |
59 | ||
60 | ZFS_IOC_VDEV_ADD, | |
61 | ZFS_IOC_VDEV_REMOVE, | |
62 | ZFS_IOC_VDEV_SET_STATE, | |
63 | ZFS_IOC_VDEV_ATTACH, | |
64 | ZFS_IOC_VDEV_DETACH, | |
65 | ZFS_IOC_VDEV_SETPATH, | |
66 | ZFS_IOC_VDEV_SETFRU, | |
67 | ||
68 | ZFS_IOC_OBJSET_STATS, | |
69 | ZFS_IOC_OBJSET_ZPLPROPS, | |
70 | ZFS_IOC_DATASET_LIST_NEXT, | |
71 | ZFS_IOC_SNAPSHOT_LIST_NEXT, | |
72 | ZFS_IOC_SET_PROP, | |
73 | ZFS_IOC_DESTROY, | |
74 | ZFS_IOC_RENAME, | |
75 | ZFS_IOC_RECV, | |
76 | ZFS_IOC_SEND, | |
77 | ZFS_IOC_INJECT_FAULT, | |
78 | ZFS_IOC_CLEAR_FAULT, | |
79 | ZFS_IOC_INJECT_LIST_NEXT, | |
80 | ZFS_IOC_ERROR_LOG, | |
81 | ZFS_IOC_CLEAR, | |
82 | ZFS_IOC_PROMOTE, | |
83 | ZFS_IOC_DSOBJ_TO_DSNAME, | |
84 | ZFS_IOC_OBJ_TO_PATH, | |
85 | ZFS_IOC_POOL_SET_PROPS, | |
86 | ZFS_IOC_POOL_GET_PROPS, | |
87 | ZFS_IOC_SET_FSACL, | |
88 | ZFS_IOC_GET_FSACL, | |
89 | ZFS_IOC_SHARE, | |
90 | ZFS_IOC_INHERIT_PROP, | |
91 | ZFS_IOC_SMB_ACL, | |
92 | ZFS_IOC_USERSPACE_ONE, | |
93 | ZFS_IOC_USERSPACE_MANY, | |
94 | ZFS_IOC_USERSPACE_UPGRADE, | |
95 | ZFS_IOC_OBJSET_RECVD_PROPS, | |
96 | ZFS_IOC_VDEV_SPLIT, | |
97 | ZFS_IOC_NEXT_OBJ, | |
98 | ZFS_IOC_DIFF, | |
99 | ZFS_IOC_TMP_SNAPSHOT, | |
100 | ZFS_IOC_OBJ_TO_STATS, | |
101 | ZFS_IOC_SPACE_WRITTEN, | |
102 | ZFS_IOC_POOL_REGUID, | |
103 | ZFS_IOC_SEND_PROGRESS, | |
b83a0e2d DB |
104 | ZFS_IOC_EVENTS_NEXT, |
105 | ZFS_IOC_EVENTS_CLEAR, | |
106 | ZFS_IOC_EVENTS_SEEK, | |
054a0498 MM |
107 | ZFS_IOC_NEXTBOOT, |
108 | ZFS_IOC_JAIL, | |
109 | ZFS_IOC_UNJAIL, | |
b83a0e2d DB |
110 | }; |
111 | ||
112 | ||
113 | #define IOC_INPUT_TEST(ioc, name, req, opt, err) \ | |
114 | IOC_INPUT_TEST_IMPL(ioc, name, req, opt, err, B_FALSE) | |
115 | ||
116 | #define IOC_INPUT_TEST_WILD(ioc, name, req, opt, err) \ | |
117 | IOC_INPUT_TEST_IMPL(ioc, name, req, opt, err, B_TRUE) | |
118 | ||
119 | #define IOC_INPUT_TEST_IMPL(ioc, name, req, opt, err, wild) \ | |
120 | do { \ | |
121 | active_test = __func__ + 5; \ | |
122 | ioc_tested[ioc - ZFS_IOC_FIRST] = B_TRUE; \ | |
123 | lzc_ioctl_test(ioc, name, req, opt, err, wild); \ | |
124 | } while (0) | |
125 | ||
126 | /* | |
127 | * run a zfs ioctl command, verify expected results and log failures | |
128 | */ | |
129 | static void | |
130 | lzc_ioctl_run(zfs_ioc_t ioc, const char *name, nvlist_t *innvl, int expected) | |
131 | { | |
132 | zfs_cmd_t zc = {"\0"}; | |
133 | char *packed = NULL; | |
134 | const char *variant; | |
135 | size_t size = 0; | |
136 | int error = 0; | |
137 | ||
138 | switch (expected) { | |
139 | case ZFS_ERR_IOC_ARG_UNAVAIL: | |
140 | variant = "unsupported input"; | |
141 | break; | |
142 | case ZFS_ERR_IOC_ARG_REQUIRED: | |
143 | variant = "missing input"; | |
144 | break; | |
145 | case ZFS_ERR_IOC_ARG_BADTYPE: | |
146 | variant = "invalid input type"; | |
147 | break; | |
148 | default: | |
149 | variant = "valid input"; | |
150 | break; | |
151 | } | |
152 | ||
153 | packed = fnvlist_pack(innvl, &size); | |
8005ca4f | 154 | (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); |
b83a0e2d DB |
155 | zc.zc_name[sizeof (zc.zc_name) - 1] = '\0'; |
156 | zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed; | |
157 | zc.zc_nvlist_src_size = size; | |
158 | zc.zc_nvlist_dst_size = MAX(size * 2, 128 * 1024); | |
159 | zc.zc_nvlist_dst = (uint64_t)(uintptr_t)malloc(zc.zc_nvlist_dst_size); | |
160 | ||
514498fe | 161 | if (lzc_ioctl_fd(zfs_fd, ioc, &zc) != 0) |
b83a0e2d DB |
162 | error = errno; |
163 | ||
164 | if (error != expected) { | |
165 | unexpected_failures = B_TRUE; | |
166 | (void) fprintf(stderr, "%s: Unexpected result with %s, " | |
167 | "error %d (expecting %d)\n", | |
168 | active_test, variant, error, expected); | |
169 | } | |
170 | ||
171 | fnvlist_pack_free(packed, size); | |
172 | free((void *)(uintptr_t)zc.zc_nvlist_dst); | |
173 | } | |
174 | ||
175 | /* | |
1b939560 | 176 | * Test each ioc for the following ioctl input errors: |
b83a0e2d DB |
177 | * ZFS_ERR_IOC_ARG_UNAVAIL an input argument is not supported by kernel |
178 | * ZFS_ERR_IOC_ARG_REQUIRED a required input argument is missing | |
179 | * ZFS_ERR_IOC_ARG_BADTYPE an input argument has an invalid type | |
180 | */ | |
181 | static int | |
182 | lzc_ioctl_test(zfs_ioc_t ioc, const char *name, nvlist_t *required, | |
183 | nvlist_t *optional, int expected_error, boolean_t wildcard) | |
184 | { | |
185 | nvlist_t *input = fnvlist_alloc(); | |
186 | nvlist_t *future = fnvlist_alloc(); | |
187 | int error = 0; | |
188 | ||
189 | if (required != NULL) { | |
190 | for (nvpair_t *pair = nvlist_next_nvpair(required, NULL); | |
191 | pair != NULL; pair = nvlist_next_nvpair(required, pair)) { | |
192 | fnvlist_add_nvpair(input, pair); | |
193 | } | |
194 | } | |
195 | if (optional != NULL) { | |
196 | for (nvpair_t *pair = nvlist_next_nvpair(optional, NULL); | |
197 | pair != NULL; pair = nvlist_next_nvpair(optional, pair)) { | |
198 | fnvlist_add_nvpair(input, pair); | |
199 | } | |
200 | } | |
201 | ||
202 | /* | |
203 | * Generic input run with 'optional' nvlist pair | |
204 | */ | |
205 | if (!wildcard) | |
206 | fnvlist_add_nvlist(input, "optional", future); | |
207 | lzc_ioctl_run(ioc, name, input, expected_error); | |
208 | if (!wildcard) | |
209 | fnvlist_remove(input, "optional"); | |
210 | ||
211 | /* | |
212 | * Bogus input value | |
213 | */ | |
214 | if (!wildcard) { | |
215 | fnvlist_add_string(input, "bogus_input", "bogus"); | |
216 | lzc_ioctl_run(ioc, name, input, ZFS_ERR_IOC_ARG_UNAVAIL); | |
217 | fnvlist_remove(input, "bogus_input"); | |
218 | } | |
219 | ||
220 | /* | |
221 | * Missing required inputs | |
222 | */ | |
223 | if (required != NULL) { | |
224 | nvlist_t *empty = fnvlist_alloc(); | |
225 | lzc_ioctl_run(ioc, name, empty, ZFS_ERR_IOC_ARG_REQUIRED); | |
226 | nvlist_free(empty); | |
227 | } | |
228 | ||
229 | /* | |
230 | * Wrong nvpair type | |
231 | */ | |
232 | if (required != NULL || optional != NULL) { | |
233 | /* | |
234 | * switch the type of one of the input pairs | |
235 | */ | |
236 | for (nvpair_t *pair = nvlist_next_nvpair(input, NULL); | |
237 | pair != NULL; pair = nvlist_next_nvpair(input, pair)) { | |
238 | char pname[MAXNAMELEN]; | |
239 | data_type_t ptype; | |
240 | ||
8005ca4f | 241 | strlcpy(pname, nvpair_name(pair), sizeof (pname)); |
b83a0e2d DB |
242 | pname[sizeof (pname) - 1] = '\0'; |
243 | ptype = nvpair_type(pair); | |
244 | fnvlist_remove_nvpair(input, pair); | |
245 | ||
246 | switch (ptype) { | |
247 | case DATA_TYPE_STRING: | |
248 | fnvlist_add_uint64(input, pname, 42); | |
249 | break; | |
250 | default: | |
251 | fnvlist_add_string(input, pname, "bogus"); | |
252 | break; | |
253 | } | |
254 | } | |
255 | lzc_ioctl_run(ioc, name, input, ZFS_ERR_IOC_ARG_BADTYPE); | |
256 | } | |
257 | ||
258 | nvlist_free(future); | |
259 | nvlist_free(input); | |
260 | ||
261 | return (error); | |
262 | } | |
263 | ||
264 | static void | |
265 | test_pool_sync(const char *pool) | |
266 | { | |
267 | nvlist_t *required = fnvlist_alloc(); | |
268 | ||
269 | fnvlist_add_boolean_value(required, "force", B_TRUE); | |
270 | ||
271 | IOC_INPUT_TEST(ZFS_IOC_POOL_SYNC, pool, required, NULL, 0); | |
272 | ||
273 | nvlist_free(required); | |
274 | } | |
275 | ||
276 | static void | |
277 | test_pool_reopen(const char *pool) | |
278 | { | |
7bb0c294 | 279 | nvlist_t *optional = fnvlist_alloc(); |
b83a0e2d | 280 | |
7bb0c294 | 281 | fnvlist_add_boolean_value(optional, "scrub_restart", B_FALSE); |
b83a0e2d | 282 | |
7bb0c294 | 283 | IOC_INPUT_TEST(ZFS_IOC_POOL_REOPEN, pool, NULL, optional, 0); |
b83a0e2d | 284 | |
7bb0c294 | 285 | nvlist_free(optional); |
b83a0e2d DB |
286 | } |
287 | ||
288 | static void | |
289 | test_pool_checkpoint(const char *pool) | |
290 | { | |
291 | IOC_INPUT_TEST(ZFS_IOC_POOL_CHECKPOINT, pool, NULL, NULL, 0); | |
292 | } | |
293 | ||
294 | static void | |
295 | test_pool_discard_checkpoint(const char *pool) | |
296 | { | |
297 | int err = lzc_pool_checkpoint(pool); | |
298 | if (err == 0 || err == ZFS_ERR_CHECKPOINT_EXISTS) | |
299 | IOC_INPUT_TEST(ZFS_IOC_POOL_DISCARD_CHECKPOINT, pool, NULL, | |
300 | NULL, 0); | |
301 | } | |
302 | ||
303 | static void | |
304 | test_log_history(const char *pool) | |
305 | { | |
306 | nvlist_t *required = fnvlist_alloc(); | |
307 | ||
308 | fnvlist_add_string(required, "message", "input check"); | |
309 | ||
310 | IOC_INPUT_TEST(ZFS_IOC_LOG_HISTORY, pool, required, NULL, 0); | |
311 | ||
312 | nvlist_free(required); | |
313 | } | |
314 | ||
315 | static void | |
316 | test_create(const char *pool) | |
317 | { | |
318 | char dataset[MAXNAMELEN + 32]; | |
319 | ||
320 | (void) snprintf(dataset, sizeof (dataset), "%s/create-fs", pool); | |
321 | ||
322 | nvlist_t *required = fnvlist_alloc(); | |
323 | nvlist_t *optional = fnvlist_alloc(); | |
324 | nvlist_t *props = fnvlist_alloc(); | |
325 | ||
326 | fnvlist_add_int32(required, "type", DMU_OST_ZFS); | |
327 | fnvlist_add_uint64(props, "recordsize", 8192); | |
328 | fnvlist_add_nvlist(optional, "props", props); | |
329 | ||
330 | IOC_INPUT_TEST(ZFS_IOC_CREATE, dataset, required, optional, 0); | |
331 | ||
332 | nvlist_free(required); | |
333 | nvlist_free(optional); | |
334 | } | |
335 | ||
336 | static void | |
337 | test_snapshot(const char *pool, const char *snapshot) | |
338 | { | |
339 | nvlist_t *required = fnvlist_alloc(); | |
340 | nvlist_t *optional = fnvlist_alloc(); | |
341 | nvlist_t *snaps = fnvlist_alloc(); | |
342 | nvlist_t *props = fnvlist_alloc(); | |
343 | ||
344 | fnvlist_add_boolean(snaps, snapshot); | |
345 | fnvlist_add_nvlist(required, "snaps", snaps); | |
346 | ||
347 | fnvlist_add_string(props, "org.openzfs:launch", "September 17th, 2013"); | |
348 | fnvlist_add_nvlist(optional, "props", props); | |
349 | ||
350 | IOC_INPUT_TEST(ZFS_IOC_SNAPSHOT, pool, required, optional, 0); | |
351 | ||
352 | nvlist_free(props); | |
353 | nvlist_free(snaps); | |
354 | nvlist_free(optional); | |
355 | nvlist_free(required); | |
356 | } | |
357 | ||
358 | static void | |
359 | test_space_snaps(const char *snapshot) | |
360 | { | |
361 | nvlist_t *required = fnvlist_alloc(); | |
362 | fnvlist_add_string(required, "firstsnap", snapshot); | |
363 | ||
364 | IOC_INPUT_TEST(ZFS_IOC_SPACE_SNAPS, snapshot, required, NULL, 0); | |
365 | ||
366 | nvlist_free(required); | |
367 | } | |
368 | ||
369 | static void | |
370 | test_destroy_snaps(const char *pool, const char *snapshot) | |
371 | { | |
372 | nvlist_t *required = fnvlist_alloc(); | |
373 | nvlist_t *snaps = fnvlist_alloc(); | |
374 | ||
375 | fnvlist_add_boolean(snaps, snapshot); | |
376 | fnvlist_add_nvlist(required, "snaps", snaps); | |
377 | ||
378 | IOC_INPUT_TEST(ZFS_IOC_DESTROY_SNAPS, pool, required, NULL, 0); | |
379 | ||
380 | nvlist_free(snaps); | |
381 | nvlist_free(required); | |
382 | } | |
383 | ||
384 | ||
385 | static void | |
386 | test_bookmark(const char *pool, const char *snapshot, const char *bookmark) | |
387 | { | |
388 | nvlist_t *required = fnvlist_alloc(); | |
389 | ||
390 | fnvlist_add_string(required, bookmark, snapshot); | |
391 | ||
392 | IOC_INPUT_TEST_WILD(ZFS_IOC_BOOKMARK, pool, required, NULL, 0); | |
393 | ||
394 | nvlist_free(required); | |
395 | } | |
396 | ||
397 | static void | |
398 | test_get_bookmarks(const char *dataset) | |
399 | { | |
400 | nvlist_t *optional = fnvlist_alloc(); | |
401 | ||
402 | fnvlist_add_boolean(optional, "guid"); | |
403 | fnvlist_add_boolean(optional, "createtxg"); | |
404 | fnvlist_add_boolean(optional, "creation"); | |
405 | ||
406 | IOC_INPUT_TEST_WILD(ZFS_IOC_GET_BOOKMARKS, dataset, NULL, optional, 0); | |
407 | ||
408 | nvlist_free(optional); | |
409 | } | |
410 | ||
411 | static void | |
412 | test_destroy_bookmarks(const char *pool, const char *bookmark) | |
413 | { | |
414 | nvlist_t *required = fnvlist_alloc(); | |
415 | ||
416 | fnvlist_add_boolean(required, bookmark); | |
417 | ||
418 | IOC_INPUT_TEST_WILD(ZFS_IOC_DESTROY_BOOKMARKS, pool, required, NULL, 0); | |
419 | ||
420 | nvlist_free(required); | |
421 | } | |
422 | ||
423 | static void | |
424 | test_clone(const char *snapshot, const char *clone) | |
425 | { | |
426 | nvlist_t *required = fnvlist_alloc(); | |
427 | nvlist_t *optional = fnvlist_alloc(); | |
428 | nvlist_t *props = fnvlist_alloc(); | |
429 | ||
430 | fnvlist_add_string(required, "origin", snapshot); | |
431 | ||
432 | IOC_INPUT_TEST(ZFS_IOC_CLONE, clone, required, NULL, 0); | |
433 | ||
434 | nvlist_free(props); | |
435 | nvlist_free(optional); | |
436 | nvlist_free(required); | |
437 | } | |
438 | ||
439 | static void | |
440 | test_rollback(const char *dataset, const char *snapshot) | |
441 | { | |
442 | nvlist_t *optional = fnvlist_alloc(); | |
443 | ||
444 | fnvlist_add_string(optional, "target", snapshot); | |
445 | ||
446 | IOC_INPUT_TEST(ZFS_IOC_ROLLBACK, dataset, NULL, optional, B_FALSE); | |
447 | ||
448 | nvlist_free(optional); | |
449 | } | |
450 | ||
451 | static void | |
452 | test_hold(const char *pool, const char *snapshot) | |
453 | { | |
454 | nvlist_t *required = fnvlist_alloc(); | |
455 | nvlist_t *optional = fnvlist_alloc(); | |
456 | nvlist_t *holds = fnvlist_alloc(); | |
457 | ||
458 | fnvlist_add_string(holds, snapshot, "libzfs_check_hold"); | |
459 | fnvlist_add_nvlist(required, "holds", holds); | |
460 | fnvlist_add_int32(optional, "cleanup_fd", zfs_fd); | |
461 | ||
462 | IOC_INPUT_TEST(ZFS_IOC_HOLD, pool, required, optional, 0); | |
463 | ||
464 | nvlist_free(holds); | |
465 | nvlist_free(optional); | |
466 | nvlist_free(required); | |
467 | } | |
468 | ||
469 | static void | |
470 | test_get_holds(const char *snapshot) | |
471 | { | |
472 | IOC_INPUT_TEST(ZFS_IOC_GET_HOLDS, snapshot, NULL, NULL, 0); | |
473 | } | |
474 | ||
475 | static void | |
476 | test_release(const char *pool, const char *snapshot) | |
477 | { | |
478 | nvlist_t *required = fnvlist_alloc(); | |
479 | nvlist_t *release = fnvlist_alloc(); | |
480 | ||
481 | fnvlist_add_boolean(release, "libzfs_check_hold"); | |
482 | fnvlist_add_nvlist(required, snapshot, release); | |
483 | ||
484 | IOC_INPUT_TEST_WILD(ZFS_IOC_RELEASE, pool, required, NULL, 0); | |
485 | ||
486 | nvlist_free(release); | |
487 | nvlist_free(required); | |
488 | } | |
489 | ||
490 | ||
491 | static void | |
492 | test_send_new(const char *snapshot, int fd) | |
493 | { | |
494 | nvlist_t *required = fnvlist_alloc(); | |
495 | nvlist_t *optional = fnvlist_alloc(); | |
496 | ||
497 | fnvlist_add_int32(required, "fd", fd); | |
498 | ||
499 | fnvlist_add_boolean(optional, "largeblockok"); | |
500 | fnvlist_add_boolean(optional, "embedok"); | |
501 | fnvlist_add_boolean(optional, "compressok"); | |
502 | fnvlist_add_boolean(optional, "rawok"); | |
503 | ||
504 | /* | |
505 | * TODO - Resumable send is harder to set up. So we currently | |
506 | * ignore testing for that variant. | |
507 | */ | |
508 | #if 0 | |
509 | fnvlist_add_string(optional, "fromsnap", from); | |
510 | fnvlist_add_uint64(optional, "resume_object", resumeobj); | |
511 | fnvlist_add_uint64(optional, "resume_offset", offset); | |
ba0ba69e | 512 | fnvlist_add_boolean(optional, "savedok"); |
b83a0e2d DB |
513 | #endif |
514 | IOC_INPUT_TEST(ZFS_IOC_SEND_NEW, snapshot, required, optional, 0); | |
515 | ||
516 | nvlist_free(optional); | |
517 | nvlist_free(required); | |
518 | } | |
519 | ||
520 | static void | |
521 | test_recv_new(const char *dataset, int fd) | |
522 | { | |
523 | dmu_replay_record_t drr = { 0 }; | |
524 | nvlist_t *required = fnvlist_alloc(); | |
525 | nvlist_t *optional = fnvlist_alloc(); | |
526 | nvlist_t *props = fnvlist_alloc(); | |
527 | char snapshot[MAXNAMELEN + 32]; | |
528 | ssize_t count; | |
529 | ||
530 | int cleanup_fd = open(ZFS_DEV, O_RDWR); | |
531 | ||
532 | (void) snprintf(snapshot, sizeof (snapshot), "%s@replicant", dataset); | |
533 | ||
534 | count = pread(fd, &drr, sizeof (drr), 0); | |
535 | if (count != sizeof (drr)) { | |
536 | (void) fprintf(stderr, "could not read stream: %s\n", | |
537 | strerror(errno)); | |
538 | } | |
539 | ||
540 | fnvlist_add_string(required, "snapname", snapshot); | |
541 | fnvlist_add_byte_array(required, "begin_record", (uchar_t *)&drr, | |
542 | sizeof (drr)); | |
543 | fnvlist_add_int32(required, "input_fd", fd); | |
544 | ||
545 | fnvlist_add_string(props, "org.openzfs:launch", "September 17th, 2013"); | |
546 | fnvlist_add_nvlist(optional, "localprops", props); | |
547 | fnvlist_add_boolean(optional, "force"); | |
e8cf3a4f | 548 | fnvlist_add_boolean(optional, "heal"); |
b83a0e2d DB |
549 | fnvlist_add_int32(optional, "cleanup_fd", cleanup_fd); |
550 | ||
551 | /* | |
552 | * TODO - Resumable receive is harder to set up. So we currently | |
553 | * ignore testing for one. | |
554 | */ | |
555 | #if 0 | |
556 | fnvlist_add_nvlist(optional, "props", recvdprops); | |
557 | fnvlist_add_string(optional, "origin", origin); | |
558 | fnvlist_add_boolean(optional, "resumable"); | |
559 | fnvlist_add_uint64(optional, "action_handle", *action_handle); | |
560 | #endif | |
6b7028ec BB |
561 | IOC_INPUT_TEST(ZFS_IOC_RECV_NEW, dataset, required, optional, |
562 | ZFS_ERR_STREAM_TRUNCATED); | |
b83a0e2d DB |
563 | |
564 | nvlist_free(props); | |
565 | nvlist_free(optional); | |
566 | nvlist_free(required); | |
567 | ||
568 | (void) close(cleanup_fd); | |
569 | } | |
570 | ||
571 | static void | |
572 | test_send_space(const char *snapshot1, const char *snapshot2) | |
573 | { | |
574 | nvlist_t *optional = fnvlist_alloc(); | |
575 | ||
576 | fnvlist_add_string(optional, "from", snapshot1); | |
577 | fnvlist_add_boolean(optional, "largeblockok"); | |
578 | fnvlist_add_boolean(optional, "embedok"); | |
579 | fnvlist_add_boolean(optional, "compressok"); | |
580 | fnvlist_add_boolean(optional, "rawok"); | |
581 | ||
582 | IOC_INPUT_TEST(ZFS_IOC_SEND_SPACE, snapshot2, NULL, optional, 0); | |
583 | ||
584 | nvlist_free(optional); | |
585 | } | |
586 | ||
587 | static void | |
588 | test_remap(const char *dataset) | |
589 | { | |
590 | IOC_INPUT_TEST(ZFS_IOC_REMAP, dataset, NULL, NULL, 0); | |
591 | } | |
592 | ||
593 | static void | |
594 | test_channel_program(const char *pool) | |
595 | { | |
596 | const char *program = | |
597 | "arg = ...\n" | |
598 | "argv = arg[\"argv\"]\n" | |
599 | "return argv[1]"; | |
a926aab9 | 600 | const char *const argv[1] = { "Hello World!" }; |
b83a0e2d DB |
601 | nvlist_t *required = fnvlist_alloc(); |
602 | nvlist_t *optional = fnvlist_alloc(); | |
603 | nvlist_t *args = fnvlist_alloc(); | |
604 | ||
605 | fnvlist_add_string(required, "program", program); | |
a926aab9 | 606 | fnvlist_add_string_array(args, "argv", argv, 1); |
b83a0e2d DB |
607 | fnvlist_add_nvlist(required, "arg", args); |
608 | ||
609 | fnvlist_add_boolean_value(optional, "sync", B_TRUE); | |
610 | fnvlist_add_uint64(optional, "instrlimit", 1000 * 1000); | |
611 | fnvlist_add_uint64(optional, "memlimit", 8192 * 1024); | |
612 | ||
613 | IOC_INPUT_TEST(ZFS_IOC_CHANNEL_PROGRAM, pool, required, optional, 0); | |
614 | ||
615 | nvlist_free(args); | |
616 | nvlist_free(optional); | |
617 | nvlist_free(required); | |
618 | } | |
619 | ||
620 | #define WRAPPING_KEY_LEN 32 | |
621 | ||
622 | static void | |
623 | test_load_key(const char *dataset) | |
624 | { | |
625 | nvlist_t *required = fnvlist_alloc(); | |
626 | nvlist_t *optional = fnvlist_alloc(); | |
627 | nvlist_t *hidden = fnvlist_alloc(); | |
628 | uint8_t keydata[WRAPPING_KEY_LEN] = {0}; | |
629 | ||
630 | fnvlist_add_uint8_array(hidden, "wkeydata", keydata, sizeof (keydata)); | |
631 | fnvlist_add_nvlist(required, "hidden_args", hidden); | |
632 | fnvlist_add_boolean(optional, "noop"); | |
633 | ||
634 | IOC_INPUT_TEST(ZFS_IOC_LOAD_KEY, dataset, required, optional, EINVAL); | |
635 | nvlist_free(hidden); | |
636 | nvlist_free(optional); | |
637 | nvlist_free(required); | |
638 | } | |
639 | ||
640 | static void | |
641 | test_change_key(const char *dataset) | |
642 | { | |
643 | IOC_INPUT_TEST(ZFS_IOC_CHANGE_KEY, dataset, NULL, NULL, EINVAL); | |
644 | } | |
645 | ||
646 | static void | |
647 | test_unload_key(const char *dataset) | |
648 | { | |
649 | IOC_INPUT_TEST(ZFS_IOC_UNLOAD_KEY, dataset, NULL, NULL, EACCES); | |
650 | } | |
651 | ||
619f0976 GW |
652 | static void |
653 | test_vdev_initialize(const char *pool) | |
654 | { | |
655 | nvlist_t *required = fnvlist_alloc(); | |
656 | nvlist_t *vdev_guids = fnvlist_alloc(); | |
657 | ||
658 | fnvlist_add_uint64(vdev_guids, "path", 0xdeadbeefdeadbeef); | |
659 | fnvlist_add_uint64(required, ZPOOL_INITIALIZE_COMMAND, | |
1b939560 | 660 | POOL_INITIALIZE_START); |
619f0976 GW |
661 | fnvlist_add_nvlist(required, ZPOOL_INITIALIZE_VDEVS, vdev_guids); |
662 | ||
663 | IOC_INPUT_TEST(ZFS_IOC_POOL_INITIALIZE, pool, required, NULL, EINVAL); | |
664 | nvlist_free(vdev_guids); | |
665 | nvlist_free(required); | |
666 | } | |
667 | ||
1b939560 BB |
668 | static void |
669 | test_vdev_trim(const char *pool) | |
670 | { | |
671 | nvlist_t *required = fnvlist_alloc(); | |
672 | nvlist_t *optional = fnvlist_alloc(); | |
673 | nvlist_t *vdev_guids = fnvlist_alloc(); | |
674 | ||
675 | fnvlist_add_uint64(vdev_guids, "path", 0xdeadbeefdeadbeef); | |
676 | fnvlist_add_uint64(required, ZPOOL_TRIM_COMMAND, POOL_TRIM_START); | |
677 | fnvlist_add_nvlist(required, ZPOOL_TRIM_VDEVS, vdev_guids); | |
678 | fnvlist_add_uint64(optional, ZPOOL_TRIM_RATE, 1ULL << 30); | |
679 | fnvlist_add_boolean_value(optional, ZPOOL_TRIM_SECURE, B_TRUE); | |
680 | ||
681 | IOC_INPUT_TEST(ZFS_IOC_POOL_TRIM, pool, required, optional, EINVAL); | |
682 | nvlist_free(vdev_guids); | |
683 | nvlist_free(optional); | |
684 | nvlist_free(required); | |
685 | } | |
686 | ||
b83a0e2d DB |
687 | static int |
688 | zfs_destroy(const char *dataset) | |
689 | { | |
690 | zfs_cmd_t zc = {"\0"}; | |
691 | int err; | |
692 | ||
8005ca4f | 693 | (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name)); |
b83a0e2d | 694 | zc.zc_name[sizeof (zc.zc_name) - 1] = '\0'; |
514498fe | 695 | err = lzc_ioctl_fd(zfs_fd, ZFS_IOC_DESTROY, &zc); |
b83a0e2d DB |
696 | |
697 | return (err == 0 ? 0 : errno); | |
698 | } | |
699 | ||
30af21b0 PD |
700 | static void |
701 | test_redact(const char *snapshot1, const char *snapshot2) | |
702 | { | |
703 | nvlist_t *required = fnvlist_alloc(); | |
704 | nvlist_t *snapnv = fnvlist_alloc(); | |
705 | char bookmark[MAXNAMELEN + 32]; | |
706 | ||
707 | fnvlist_add_string(required, "bookname", "testbookmark"); | |
708 | fnvlist_add_boolean(snapnv, snapshot2); | |
709 | fnvlist_add_nvlist(required, "snapnv", snapnv); | |
710 | ||
711 | IOC_INPUT_TEST(ZFS_IOC_REDACT, snapshot1, required, NULL, 0); | |
712 | ||
713 | nvlist_free(snapnv); | |
714 | nvlist_free(required); | |
715 | ||
d5bf1cf1 | 716 | strlcpy(bookmark, snapshot1, sizeof (bookmark)); |
30af21b0 | 717 | *strchr(bookmark, '@') = '\0'; |
d5bf1cf1 TK |
718 | strlcat(bookmark, "#testbookmark", sizeof (bookmark) - |
719 | strlen(bookmark)); | |
30af21b0 PD |
720 | zfs_destroy(bookmark); |
721 | } | |
722 | ||
723 | static void | |
724 | test_get_bookmark_props(const char *bookmark) | |
725 | { | |
726 | IOC_INPUT_TEST(ZFS_IOC_GET_BOOKMARK_PROPS, bookmark, NULL, NULL, 0); | |
727 | } | |
728 | ||
e60e158e JG |
729 | static void |
730 | test_wait(const char *pool) | |
731 | { | |
732 | nvlist_t *required = fnvlist_alloc(); | |
733 | nvlist_t *optional = fnvlist_alloc(); | |
734 | ||
735 | fnvlist_add_int32(required, "wait_activity", 2); | |
736 | fnvlist_add_uint64(optional, "wait_tag", 0xdeadbeefdeadbeef); | |
737 | ||
738 | IOC_INPUT_TEST(ZFS_IOC_WAIT, pool, required, optional, EINVAL); | |
739 | ||
740 | nvlist_free(required); | |
741 | nvlist_free(optional); | |
742 | } | |
743 | ||
5a42ef04 PD |
744 | static void |
745 | test_wait_fs(const char *dataset) | |
746 | { | |
747 | nvlist_t *required = fnvlist_alloc(); | |
748 | ||
749 | fnvlist_add_int32(required, "wait_activity", 2); | |
750 | ||
751 | IOC_INPUT_TEST(ZFS_IOC_WAIT_FS, dataset, required, NULL, EINVAL); | |
752 | ||
753 | nvlist_free(required); | |
754 | } | |
755 | ||
108a454a PD |
756 | static void |
757 | test_get_bootenv(const char *pool) | |
758 | { | |
759 | IOC_INPUT_TEST(ZFS_IOC_GET_BOOTENV, pool, NULL, NULL, 0); | |
760 | } | |
761 | ||
762 | static void | |
763 | test_set_bootenv(const char *pool) | |
764 | { | |
765 | nvlist_t *required = fnvlist_alloc(); | |
766 | ||
1db9e6e4 TS |
767 | fnvlist_add_uint64(required, "version", VB_RAW); |
768 | fnvlist_add_string(required, GRUB_ENVMAP, "test"); | |
108a454a | 769 | |
1db9e6e4 | 770 | IOC_INPUT_TEST_WILD(ZFS_IOC_SET_BOOTENV, pool, required, NULL, 0); |
108a454a PD |
771 | |
772 | nvlist_free(required); | |
773 | } | |
774 | ||
b83a0e2d DB |
775 | static void |
776 | zfs_ioc_input_tests(const char *pool) | |
777 | { | |
778 | char filepath[] = "/tmp/ioc_test_file_XXXXXX"; | |
779 | char dataset[ZFS_MAX_DATASET_NAME_LEN]; | |
780 | char snapbase[ZFS_MAX_DATASET_NAME_LEN + 32]; | |
781 | char snapshot[ZFS_MAX_DATASET_NAME_LEN + 32]; | |
782 | char bookmark[ZFS_MAX_DATASET_NAME_LEN + 32]; | |
783 | char backup[ZFS_MAX_DATASET_NAME_LEN]; | |
784 | char clone[ZFS_MAX_DATASET_NAME_LEN]; | |
30af21b0 | 785 | char clonesnap[ZFS_MAX_DATASET_NAME_LEN + 32]; |
b83a0e2d DB |
786 | int tmpfd, err; |
787 | ||
788 | /* | |
789 | * Setup names and create a working dataset | |
790 | */ | |
791 | (void) snprintf(dataset, sizeof (dataset), "%s/test-fs", pool); | |
792 | (void) snprintf(snapbase, sizeof (snapbase), "%s@snapbase", dataset); | |
793 | (void) snprintf(snapshot, sizeof (snapshot), "%s@snapshot", dataset); | |
794 | (void) snprintf(bookmark, sizeof (bookmark), "%s#bookmark", dataset); | |
795 | (void) snprintf(clone, sizeof (clone), "%s/test-fs-clone", pool); | |
30af21b0 | 796 | (void) snprintf(clonesnap, sizeof (clonesnap), "%s@snap", clone); |
b83a0e2d DB |
797 | (void) snprintf(backup, sizeof (backup), "%s/backup", pool); |
798 | ||
40ab927a | 799 | err = lzc_create(dataset, LZC_DATSET_TYPE_ZFS, NULL, NULL, -1); |
b83a0e2d DB |
800 | if (err) { |
801 | (void) fprintf(stderr, "could not create '%s': %s\n", | |
802 | dataset, strerror(errno)); | |
803 | exit(2); | |
804 | } | |
805 | ||
806 | tmpfd = mkstemp(filepath); | |
807 | if (tmpfd < 0) { | |
808 | (void) fprintf(stderr, "could not create '%s': %s\n", | |
809 | filepath, strerror(errno)); | |
810 | exit(2); | |
811 | } | |
812 | ||
813 | /* | |
814 | * run a test for each ioctl | |
815 | * Note that some test build on previous test operations | |
816 | */ | |
817 | test_pool_sync(pool); | |
818 | test_pool_reopen(pool); | |
819 | test_pool_checkpoint(pool); | |
820 | test_pool_discard_checkpoint(pool); | |
821 | test_log_history(pool); | |
822 | ||
823 | test_create(dataset); | |
824 | test_snapshot(pool, snapbase); | |
825 | test_snapshot(pool, snapshot); | |
826 | ||
827 | test_space_snaps(snapshot); | |
828 | test_send_space(snapbase, snapshot); | |
829 | test_send_new(snapshot, tmpfd); | |
830 | test_recv_new(backup, tmpfd); | |
831 | ||
832 | test_bookmark(pool, snapshot, bookmark); | |
833 | test_get_bookmarks(dataset); | |
30af21b0 | 834 | test_get_bookmark_props(bookmark); |
b83a0e2d DB |
835 | test_destroy_bookmarks(pool, bookmark); |
836 | ||
837 | test_hold(pool, snapshot); | |
838 | test_get_holds(snapshot); | |
839 | test_release(pool, snapshot); | |
840 | ||
841 | test_clone(snapshot, clone); | |
30af21b0 PD |
842 | test_snapshot(pool, clonesnap); |
843 | test_redact(snapshot, clonesnap); | |
844 | zfs_destroy(clonesnap); | |
b83a0e2d DB |
845 | zfs_destroy(clone); |
846 | ||
847 | test_rollback(dataset, snapshot); | |
848 | test_destroy_snaps(pool, snapshot); | |
849 | test_destroy_snaps(pool, snapbase); | |
850 | ||
851 | test_remap(dataset); | |
852 | test_channel_program(pool); | |
853 | ||
854 | test_load_key(dataset); | |
855 | test_change_key(dataset); | |
856 | test_unload_key(dataset); | |
857 | ||
619f0976 | 858 | test_vdev_initialize(pool); |
1b939560 | 859 | test_vdev_trim(pool); |
619f0976 | 860 | |
e60e158e | 861 | test_wait(pool); |
5a42ef04 | 862 | test_wait_fs(dataset); |
e60e158e | 863 | |
108a454a PD |
864 | test_set_bootenv(pool); |
865 | test_get_bootenv(pool); | |
866 | ||
b83a0e2d DB |
867 | /* |
868 | * cleanup | |
869 | */ | |
870 | zfs_cmd_t zc = {"\0"}; | |
871 | ||
872 | nvlist_t *snaps = fnvlist_alloc(); | |
873 | fnvlist_add_boolean(snaps, snapshot); | |
874 | (void) lzc_destroy_snaps(snaps, B_FALSE, NULL); | |
875 | nvlist_free(snaps); | |
876 | ||
877 | (void) zfs_destroy(dataset); | |
878 | (void) zfs_destroy(backup); | |
879 | ||
880 | (void) close(tmpfd); | |
881 | (void) unlink(filepath); | |
882 | ||
883 | /* | |
884 | * All the unused slots should yield ZFS_ERR_IOC_CMD_UNAVAIL | |
885 | */ | |
886 | for (int i = 0; i < ARRAY_SIZE(ioc_skip); i++) { | |
887 | if (ioc_tested[ioc_skip[i] - ZFS_IOC_FIRST]) | |
888 | (void) fprintf(stderr, "cmd %d tested, not skipped!\n", | |
889 | (int)(ioc_skip[i] - ZFS_IOC_FIRST)); | |
890 | ||
891 | ioc_tested[ioc_skip[i] - ZFS_IOC_FIRST] = B_TRUE; | |
892 | } | |
893 | ||
8005ca4f | 894 | (void) strlcpy(zc.zc_name, pool, sizeof (zc.zc_name)); |
b83a0e2d DB |
895 | zc.zc_name[sizeof (zc.zc_name) - 1] = '\0'; |
896 | ||
897 | for (unsigned ioc = ZFS_IOC_FIRST; ioc < ZFS_IOC_LAST; ioc++) { | |
898 | unsigned cmd = ioc - ZFS_IOC_FIRST; | |
899 | ||
900 | if (ioc_tested[cmd]) | |
901 | continue; | |
902 | ||
514498fe | 903 | if (lzc_ioctl_fd(zfs_fd, ioc, &zc) != 0 && |
b83a0e2d DB |
904 | errno != ZFS_ERR_IOC_CMD_UNAVAIL) { |
905 | (void) fprintf(stderr, "cmd %d is missing a test case " | |
906 | "(%d)\n", cmd, errno); | |
907 | } | |
908 | } | |
909 | } | |
910 | ||
911 | enum zfs_ioc_ref { | |
054a0498 MM |
912 | #ifdef __FreeBSD__ |
913 | ZFS_IOC_BASE = 0, | |
914 | #else | |
b83a0e2d | 915 | ZFS_IOC_BASE = ('Z' << 8), |
054a0498 MM |
916 | #endif |
917 | ZFS_IOC_PLATFORM_BASE = ZFS_IOC_BASE + 0x80, | |
b83a0e2d DB |
918 | }; |
919 | ||
920 | /* | |
921 | * Canonical reference check of /dev/zfs ioctl numbers. | |
922 | * These cannot change and new ioctl numbers must be appended. | |
923 | */ | |
65c7cc49 | 924 | static boolean_t |
b83a0e2d DB |
925 | validate_ioc_values(void) |
926 | { | |
a6a28777 | 927 | boolean_t result = B_TRUE; |
f591a581 RM |
928 | |
929 | #define CHECK(expr) do { \ | |
930 | if (!(expr)) { \ | |
a6a28777 | 931 | result = B_FALSE; \ |
f591a581 RM |
932 | fprintf(stderr, "(%s) === FALSE\n", #expr); \ |
933 | } \ | |
934 | } while (0) | |
935 | ||
936 | CHECK(ZFS_IOC_BASE + 0 == ZFS_IOC_POOL_CREATE); | |
937 | CHECK(ZFS_IOC_BASE + 1 == ZFS_IOC_POOL_DESTROY); | |
938 | CHECK(ZFS_IOC_BASE + 2 == ZFS_IOC_POOL_IMPORT); | |
939 | CHECK(ZFS_IOC_BASE + 3 == ZFS_IOC_POOL_EXPORT); | |
940 | CHECK(ZFS_IOC_BASE + 4 == ZFS_IOC_POOL_CONFIGS); | |
941 | CHECK(ZFS_IOC_BASE + 5 == ZFS_IOC_POOL_STATS); | |
942 | CHECK(ZFS_IOC_BASE + 6 == ZFS_IOC_POOL_TRYIMPORT); | |
943 | CHECK(ZFS_IOC_BASE + 7 == ZFS_IOC_POOL_SCAN); | |
944 | CHECK(ZFS_IOC_BASE + 8 == ZFS_IOC_POOL_FREEZE); | |
945 | CHECK(ZFS_IOC_BASE + 9 == ZFS_IOC_POOL_UPGRADE); | |
946 | CHECK(ZFS_IOC_BASE + 10 == ZFS_IOC_POOL_GET_HISTORY); | |
947 | CHECK(ZFS_IOC_BASE + 11 == ZFS_IOC_VDEV_ADD); | |
948 | CHECK(ZFS_IOC_BASE + 12 == ZFS_IOC_VDEV_REMOVE); | |
949 | CHECK(ZFS_IOC_BASE + 13 == ZFS_IOC_VDEV_SET_STATE); | |
950 | CHECK(ZFS_IOC_BASE + 14 == ZFS_IOC_VDEV_ATTACH); | |
951 | CHECK(ZFS_IOC_BASE + 15 == ZFS_IOC_VDEV_DETACH); | |
952 | CHECK(ZFS_IOC_BASE + 16 == ZFS_IOC_VDEV_SETPATH); | |
953 | CHECK(ZFS_IOC_BASE + 17 == ZFS_IOC_VDEV_SETFRU); | |
954 | CHECK(ZFS_IOC_BASE + 18 == ZFS_IOC_OBJSET_STATS); | |
955 | CHECK(ZFS_IOC_BASE + 19 == ZFS_IOC_OBJSET_ZPLPROPS); | |
956 | CHECK(ZFS_IOC_BASE + 20 == ZFS_IOC_DATASET_LIST_NEXT); | |
957 | CHECK(ZFS_IOC_BASE + 21 == ZFS_IOC_SNAPSHOT_LIST_NEXT); | |
958 | CHECK(ZFS_IOC_BASE + 22 == ZFS_IOC_SET_PROP); | |
959 | CHECK(ZFS_IOC_BASE + 23 == ZFS_IOC_CREATE); | |
960 | CHECK(ZFS_IOC_BASE + 24 == ZFS_IOC_DESTROY); | |
961 | CHECK(ZFS_IOC_BASE + 25 == ZFS_IOC_ROLLBACK); | |
962 | CHECK(ZFS_IOC_BASE + 26 == ZFS_IOC_RENAME); | |
963 | CHECK(ZFS_IOC_BASE + 27 == ZFS_IOC_RECV); | |
964 | CHECK(ZFS_IOC_BASE + 28 == ZFS_IOC_SEND); | |
965 | CHECK(ZFS_IOC_BASE + 29 == ZFS_IOC_INJECT_FAULT); | |
966 | CHECK(ZFS_IOC_BASE + 30 == ZFS_IOC_CLEAR_FAULT); | |
967 | CHECK(ZFS_IOC_BASE + 31 == ZFS_IOC_INJECT_LIST_NEXT); | |
968 | CHECK(ZFS_IOC_BASE + 32 == ZFS_IOC_ERROR_LOG); | |
969 | CHECK(ZFS_IOC_BASE + 33 == ZFS_IOC_CLEAR); | |
970 | CHECK(ZFS_IOC_BASE + 34 == ZFS_IOC_PROMOTE); | |
971 | CHECK(ZFS_IOC_BASE + 35 == ZFS_IOC_SNAPSHOT); | |
972 | CHECK(ZFS_IOC_BASE + 36 == ZFS_IOC_DSOBJ_TO_DSNAME); | |
973 | CHECK(ZFS_IOC_BASE + 37 == ZFS_IOC_OBJ_TO_PATH); | |
974 | CHECK(ZFS_IOC_BASE + 38 == ZFS_IOC_POOL_SET_PROPS); | |
975 | CHECK(ZFS_IOC_BASE + 39 == ZFS_IOC_POOL_GET_PROPS); | |
976 | CHECK(ZFS_IOC_BASE + 40 == ZFS_IOC_SET_FSACL); | |
977 | CHECK(ZFS_IOC_BASE + 41 == ZFS_IOC_GET_FSACL); | |
978 | CHECK(ZFS_IOC_BASE + 42 == ZFS_IOC_SHARE); | |
979 | CHECK(ZFS_IOC_BASE + 43 == ZFS_IOC_INHERIT_PROP); | |
980 | CHECK(ZFS_IOC_BASE + 44 == ZFS_IOC_SMB_ACL); | |
981 | CHECK(ZFS_IOC_BASE + 45 == ZFS_IOC_USERSPACE_ONE); | |
982 | CHECK(ZFS_IOC_BASE + 46 == ZFS_IOC_USERSPACE_MANY); | |
983 | CHECK(ZFS_IOC_BASE + 47 == ZFS_IOC_USERSPACE_UPGRADE); | |
984 | CHECK(ZFS_IOC_BASE + 48 == ZFS_IOC_HOLD); | |
985 | CHECK(ZFS_IOC_BASE + 49 == ZFS_IOC_RELEASE); | |
986 | CHECK(ZFS_IOC_BASE + 50 == ZFS_IOC_GET_HOLDS); | |
987 | CHECK(ZFS_IOC_BASE + 51 == ZFS_IOC_OBJSET_RECVD_PROPS); | |
988 | CHECK(ZFS_IOC_BASE + 52 == ZFS_IOC_VDEV_SPLIT); | |
989 | CHECK(ZFS_IOC_BASE + 53 == ZFS_IOC_NEXT_OBJ); | |
990 | CHECK(ZFS_IOC_BASE + 54 == ZFS_IOC_DIFF); | |
991 | CHECK(ZFS_IOC_BASE + 55 == ZFS_IOC_TMP_SNAPSHOT); | |
992 | CHECK(ZFS_IOC_BASE + 56 == ZFS_IOC_OBJ_TO_STATS); | |
993 | CHECK(ZFS_IOC_BASE + 57 == ZFS_IOC_SPACE_WRITTEN); | |
994 | CHECK(ZFS_IOC_BASE + 58 == ZFS_IOC_SPACE_SNAPS); | |
995 | CHECK(ZFS_IOC_BASE + 59 == ZFS_IOC_DESTROY_SNAPS); | |
996 | CHECK(ZFS_IOC_BASE + 60 == ZFS_IOC_POOL_REGUID); | |
997 | CHECK(ZFS_IOC_BASE + 61 == ZFS_IOC_POOL_REOPEN); | |
998 | CHECK(ZFS_IOC_BASE + 62 == ZFS_IOC_SEND_PROGRESS); | |
999 | CHECK(ZFS_IOC_BASE + 63 == ZFS_IOC_LOG_HISTORY); | |
1000 | CHECK(ZFS_IOC_BASE + 64 == ZFS_IOC_SEND_NEW); | |
1001 | CHECK(ZFS_IOC_BASE + 65 == ZFS_IOC_SEND_SPACE); | |
1002 | CHECK(ZFS_IOC_BASE + 66 == ZFS_IOC_CLONE); | |
1003 | CHECK(ZFS_IOC_BASE + 67 == ZFS_IOC_BOOKMARK); | |
1004 | CHECK(ZFS_IOC_BASE + 68 == ZFS_IOC_GET_BOOKMARKS); | |
1005 | CHECK(ZFS_IOC_BASE + 69 == ZFS_IOC_DESTROY_BOOKMARKS); | |
1006 | CHECK(ZFS_IOC_BASE + 70 == ZFS_IOC_RECV_NEW); | |
1007 | CHECK(ZFS_IOC_BASE + 71 == ZFS_IOC_POOL_SYNC); | |
1008 | CHECK(ZFS_IOC_BASE + 72 == ZFS_IOC_CHANNEL_PROGRAM); | |
1009 | CHECK(ZFS_IOC_BASE + 73 == ZFS_IOC_LOAD_KEY); | |
1010 | CHECK(ZFS_IOC_BASE + 74 == ZFS_IOC_UNLOAD_KEY); | |
1011 | CHECK(ZFS_IOC_BASE + 75 == ZFS_IOC_CHANGE_KEY); | |
1012 | CHECK(ZFS_IOC_BASE + 76 == ZFS_IOC_REMAP); | |
1013 | CHECK(ZFS_IOC_BASE + 77 == ZFS_IOC_POOL_CHECKPOINT); | |
1014 | CHECK(ZFS_IOC_BASE + 78 == ZFS_IOC_POOL_DISCARD_CHECKPOINT); | |
1015 | CHECK(ZFS_IOC_BASE + 79 == ZFS_IOC_POOL_INITIALIZE); | |
1016 | CHECK(ZFS_IOC_BASE + 80 == ZFS_IOC_POOL_TRIM); | |
1017 | CHECK(ZFS_IOC_BASE + 81 == ZFS_IOC_REDACT); | |
1018 | CHECK(ZFS_IOC_BASE + 82 == ZFS_IOC_GET_BOOKMARK_PROPS); | |
e60e158e | 1019 | CHECK(ZFS_IOC_BASE + 83 == ZFS_IOC_WAIT); |
5a42ef04 | 1020 | CHECK(ZFS_IOC_BASE + 84 == ZFS_IOC_WAIT_FS); |
054a0498 MM |
1021 | CHECK(ZFS_IOC_PLATFORM_BASE + 1 == ZFS_IOC_EVENTS_NEXT); |
1022 | CHECK(ZFS_IOC_PLATFORM_BASE + 2 == ZFS_IOC_EVENTS_CLEAR); | |
1023 | CHECK(ZFS_IOC_PLATFORM_BASE + 3 == ZFS_IOC_EVENTS_SEEK); | |
1024 | CHECK(ZFS_IOC_PLATFORM_BASE + 4 == ZFS_IOC_NEXTBOOT); | |
1025 | CHECK(ZFS_IOC_PLATFORM_BASE + 5 == ZFS_IOC_JAIL); | |
1026 | CHECK(ZFS_IOC_PLATFORM_BASE + 6 == ZFS_IOC_UNJAIL); | |
108a454a PD |
1027 | CHECK(ZFS_IOC_PLATFORM_BASE + 7 == ZFS_IOC_SET_BOOTENV); |
1028 | CHECK(ZFS_IOC_PLATFORM_BASE + 8 == ZFS_IOC_GET_BOOTENV); | |
f591a581 RM |
1029 | |
1030 | #undef CHECK | |
1031 | ||
1032 | return (result); | |
b83a0e2d DB |
1033 | } |
1034 | ||
1035 | int | |
1036 | main(int argc, const char *argv[]) | |
1037 | { | |
1038 | if (argc != 2) { | |
1039 | (void) fprintf(stderr, "usage: %s <pool>\n", argv[0]); | |
1040 | exit(2); | |
1041 | } | |
1042 | ||
1043 | if (!validate_ioc_values()) { | |
1044 | (void) fprintf(stderr, "WARNING: zfs_ioc_t has binary " | |
1045 | "incompatible command values\n"); | |
1046 | exit(3); | |
1047 | } | |
1048 | ||
1049 | (void) libzfs_core_init(); | |
1050 | zfs_fd = open(ZFS_DEV, O_RDWR); | |
1051 | if (zfs_fd < 0) { | |
1052 | (void) fprintf(stderr, "open: %s\n", strerror(errno)); | |
1053 | libzfs_core_fini(); | |
1054 | exit(2); | |
1055 | } | |
1056 | ||
1057 | zfs_ioc_input_tests(argv[1]); | |
1058 | ||
1059 | (void) close(zfs_fd); | |
1060 | libzfs_core_fini(); | |
1061 | ||
1062 | return (unexpected_failures); | |
1063 | } |