• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "tests.h"
2 
3 #ifdef HAVE_LINUX_BTRFS_H
4 
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <inttypes.h>
8 #include <limits.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <sys/ioctl.h>
15 #include <sys/stat.h>
16 #include <sys/sysmacros.h>
17 #include <sys/vfs.h>
18 #include <linux/fs.h>
19 #include <linux/btrfs.h>
20 #include <linux/magic.h>
21 #include "xlat.h"
22 
23 #include "xlat/btrfs_balance_args.h"
24 #include "xlat/btrfs_balance_flags.h"
25 #include "xlat/btrfs_balance_state.h"
26 #include "xlat/btrfs_compress_types.h"
27 #include "xlat/btrfs_cont_reading_from_srcdev_mode.h"
28 #include "xlat/btrfs_defrag_flags.h"
29 #include "xlat/btrfs_dev_stats_values.h"
30 #include "xlat/btrfs_dev_stats_flags.h"
31 #include "xlat/btrfs_qgroup_inherit_flags.h"
32 #include "xlat/btrfs_qgroup_limit_flags.h"
33 #include "xlat/btrfs_scrub_flags.h"
34 #include "xlat/btrfs_send_flags.h"
35 #include "xlat/btrfs_space_info_flags.h"
36 #include "xlat/btrfs_snap_flags_v2.h"
37 #include "xlat/btrfs_tree_objectids.h"
38 #include "xlat/btrfs_features_compat.h"
39 #include "xlat/btrfs_features_compat_ro.h"
40 #include "xlat/btrfs_features_incompat.h"
41 #include "xlat/btrfs_key_types.h"
42 
43 #ifdef HAVE_LINUX_FIEMAP_H
44 # include <linux/fiemap.h>
45 # include "xlat/fiemap_flags.h"
46 # include "xlat/fiemap_extent_flags.h"
47 #endif
48 
49 #ifndef BTRFS_LABEL_SIZE
50 # define BTRFS_LABEL_SIZE 256
51 #endif
52 
53 #ifndef BTRFS_NAME_LEN
54 # define BTRFS_NAME_LEN 255
55 #endif
56 
57 #ifndef FS_IOC_GETFSLABEL
58 # define FS_IOC_GETFSLABEL BTRFS_IOC_GET_FSLABEL
59 #endif
60 
61 #ifndef FS_IOC_SETFSLABEL
62 # define FS_IOC_SETFSLABEL BTRFS_IOC_SET_FSLABEL
63 #endif
64 
65 /*
66  * Prior to Linux 3.12, the BTRFS_IOC_DEFAULT_SUBVOL used u64 in
67  * its definition, which isn't exported by the kernel.
68  */
69 typedef __u64 u64;
70 
71 static const char *btrfs_test_root;
72 static int btrfs_test_dir_fd;
73 static bool verbose;
74 static bool write_ok;
75 static bool verbose_xlat;
76 
77 static const char *path;
78 static const char dir_name_fmt[] = "strace-test-%d";
79 static char dir_name[sizeof(dir_name_fmt) + sizeof(int) * 3];
80 
81 const unsigned char uuid_reference[BTRFS_UUID_SIZE] = {
82 	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
83 	0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
84 };
85 
86 const char uuid_reference_string[] = "01234567-89ab-cdef-fedc-ba9876543210";
87 
88 #ifndef BTRFS_IOC_QUOTA_RESCAN
89 struct btrfs_ioctl_quota_rescan_args {
90 	uint64_t flags, progress, reserved[6];
91 };
92 # define BTRFS_IOC_QUOTA_RESCAN			\
93 	_IOW(BTRFS_IOCTL_MAGIC, 44, struct btrfs_ioctl_quota_rescan_args)
94 # define BTRFS_IOC_QUOTA_RESCAN_STATUS		\
95 	_IOR(BTRFS_IOCTL_MAGIC, 45, struct btrfs_ioctl_quota_rescan_args)
96 #endif
97 
98 #ifndef BTRFS_IOC_QUOTA_RESCAN_WAIT
99 # define BTRFS_IOC_QUOTA_RESCAN_WAIT _IO(BTRFS_IOCTL_MAGIC, 46)
100 #endif
101 
102 #ifndef BTRFS_IOC_GET_FEATURES
103 # define BTRFS_IOC_GET_FEATURES			\
104 	_IOR(BTRFS_IOCTL_MAGIC, 57, struct btrfs_ioctl_feature_flags)
105 # define BTRFS_IOC_SET_FEATURES			\
106 	_IOW(BTRFS_IOCTL_MAGIC, 57, struct btrfs_ioctl_feature_flags[2])
107 # define BTRFS_IOC_GET_SUPPORTED_FEATURES	\
108 	_IOR(BTRFS_IOCTL_MAGIC, 57, struct btrfs_ioctl_feature_flags[3])
109 #endif
110 
111 #ifndef HAVE_STRUCT_BTRFS_IOCTL_FEATURE_FLAGS_COMPAT_FLAGS
112 struct btrfs_ioctl_feature_flags {
113 	uint64_t compat_flags;
114 	uint64_t compat_ro_flags;
115 	uint64_t incompat_flags;
116 };
117 #endif
118 
119 #ifndef HAVE_STRUCT_BTRFS_IOCTL_DEFRAG_RANGE_ARGS_START
120 struct btrfs_ioctl_defrag_range_args {
121 	uint64_t start;
122 	uint64_t len;
123 	uint64_t flags;
124 	uint32_t extent_thresh;
125 	uint32_t compress_type;
126 	uint32_t unused[4];
127 };
128 #endif
129 
130 #ifndef FIDEDUPERANGE
131 # define FIDEDUPERANGE   _IOWR(0x94, 54, struct file_dedupe_range)
132 struct file_dedupe_range_info {
133 	int64_t dest_fd;	/* in - destination file */
134 	uint64_t dest_offset;	/* in - start of extent in destination */
135 	uint64_t bytes_deduped;	/* out - total # of bytes we were able
136 				 * to dedupe from this file. */
137 	/* status of this dedupe operation:
138 	 * < 0 for error
139 	 * == FILE_DEDUPE_RANGE_SAME if dedupe succeeds
140 	 * == FILE_DEDUPE_RANGE_DIFFERS if data differs
141 	 */
142 	int32_t status;		/* out - see above description */
143 	uint32_t reserved;	/* must be zero */
144 };
145 
146 struct file_dedupe_range {
147 	uint64_t src_offset;	/* in - start of extent in source */
148 	uint64_t src_length;	/* in - length of extent */
149 	uint16_t dest_count;	/* in - total elements in info array */
150 	uint16_t reserved1;	/* must be zero */
151 	uint32_t reserved2;	/* must be zero */
152 	struct file_dedupe_range_info info[0];
153 };
154 #endif
155 
156 #ifndef BTRFS_IOC_TREE_SEARCH_V2
157 # define BTRFS_IOC_TREE_SEARCH_V2	\
158 	_IOWR(BTRFS_IOCTL_MAGIC, 17, struct btrfs_ioctl_search_args_v2)
159 struct btrfs_ioctl_search_args_v2 {
160 	struct btrfs_ioctl_search_key key; /* in/out - search parameters */
161 	uint64_t buf_size;		   /* in - size of buffer
162 					    * out - on EOVERFLOW: needed size
163 					    *       to store item */
164 	uint64_t buf[0];		   /* out - found items */
165 };
166 #endif
167 
168 
169 static const char *
sprint_xlat_(uint32_t val,const char * xlat)170 sprint_xlat_(uint32_t val, const char *xlat)
171 {
172 	static char str[256];
173 	int ret;
174 
175 	if (verbose_xlat) {
176 		ret = snprintf(str, sizeof(str), "%#x /* %s */", val, xlat);
177 
178 		if (ret < 0)
179 			perror_msg_and_fail("sprint_ioc(%#x, %s)", val, xlat);
180 		if ((unsigned) ret >= sizeof(str))
181 			error_msg_and_fail("sprint_ioc(%#x, %s): buffer "
182 					   "overflow", val, xlat);
183 
184 		return str;
185 	}
186 
187 	return xlat;
188 }
189 
190 #define ioc(x_) sprint_xlat_(x_, #x_)
191 
192 void
prfl_btrfs(const struct xlat * xlat,const unsigned long long val,const char * str)193 prfl_btrfs(const struct xlat *xlat, const unsigned long long val,
194 	   const char *str)
195 {
196 	if (verbose_xlat && val)
197 		printf("%#llx /* ", val);
198 	printflags(xlat, val, str);
199 	if (verbose_xlat && val)
200 		printf(" */");
201 }
202 
203 void
prxval_btrfs(const struct xlat * xlat,const unsigned long long val,const char * str,bool known)204 prxval_btrfs(const struct xlat *xlat, const unsigned long long val,
205 	     const char *str, bool known)
206 {
207 	if (verbose_xlat && known)
208 		printf("%#llx /* ", val);
209 	printxval(xlat, val, str);
210 	if (verbose_xlat && known)
211 		printf(" */");
212 }
213 
214 static void
print_uint64(const char * prefix,uint64_t val)215 print_uint64(const char *prefix, uint64_t val)
216 {
217 	if (val == UINT64_MAX) {
218 		if (verbose_xlat)
219 			printf("%s%" PRIu64 " /* UINT64_MAX */", prefix, val);
220 		else
221 			printf("%sUINT64_MAX", prefix);
222 	} else {
223 		printf("%s%" PRIu64, prefix, val);
224 	}
225 }
226 
227 /* takes highest valid flag bit */
228 static uint64_t
max_flags_plus_one(int bit)229 max_flags_plus_one(int bit)
230 {
231 	int i;
232 	uint64_t val = 0;
233 	if (bit == -1)
234 		return 1;
235 	for (i = 0; i <= bit + 1 && i < 64; i++)
236 		val |= (1ULL << i);
237 	return val;
238 }
239 
240 /*
241  * Consumes no arguments, returns nothing:
242  *
243  * - BTRFS_IOC_TRANS_START
244  * - BTRFS_IOC_TRANS_END
245  */
246 static void
btrfs_test_trans_ioctls(void)247 btrfs_test_trans_ioctls(void)
248 {
249 	ioctl(-1, BTRFS_IOC_TRANS_START, NULL);
250 	printf("ioctl(-1, %s) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_TRANS_START));
251 
252 	ioctl(-1, BTRFS_IOC_TRANS_END, NULL);
253 	printf("ioctl(-1, %s) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_TRANS_END));
254 }
255 
256 /*
257  * Consumes no arguments, returns nothing:
258  * - BTRFS_IOC_SYNC
259  *
260  * Consumes argument, returns nothing
261  * - BTRFS_IOC_WAIT_SYNC
262  */
263 static void
btrfs_test_sync_ioctls(void)264 btrfs_test_sync_ioctls(void)
265 {
266 	uint64_t u64val = 0xdeadbeefbadc0dedULL;
267 
268 	ioctl(-1, BTRFS_IOC_SYNC, NULL);
269 	printf("ioctl(-1, %s) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_SYNC));
270 
271 	ioctl(-1, BTRFS_IOC_WAIT_SYNC, NULL);
272 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
273 	       ioc(BTRFS_IOC_WAIT_SYNC));
274 
275 	ioctl(-1, BTRFS_IOC_WAIT_SYNC, &u64val);
276 	printf("ioctl(-1, %s, [%" PRIu64 "]) = -1 EBADF (%m)\n",
277 	       ioc(BTRFS_IOC_WAIT_SYNC), u64val);
278 
279 	/*
280 	 * The live test of BTRFS_IOC_SYNC happens as a part of the test
281 	 * for BTRFS_IOC_LOGICAL_INO
282 	 */
283 }
284 
285 static void
btrfs_print_qgroup_inherit(struct btrfs_qgroup_inherit * inherit)286 btrfs_print_qgroup_inherit(struct btrfs_qgroup_inherit *inherit)
287 {
288 	printf("{flags=");
289 	prfl_btrfs(btrfs_qgroup_inherit_flags, inherit->flags,
290 		   "BTRFS_QGROUP_INHERIT_???");
291 	printf(", num_qgroups=%" PRI__u64
292 	       ", num_ref_copies=%" PRI__u64
293 	       ", num_excl_copies=%" PRI__u64 ", lim={flags=",
294 	       inherit->num_qgroups, inherit->num_ref_copies,
295 	       inherit->num_excl_copies);
296 	prfl_btrfs(btrfs_qgroup_limit_flags,
297 		   inherit->lim.flags,
298 		   "BTRFS_QGROUP_LIMIT_???");
299 	printf(", max_rfer=%" PRI__u64 ", max_excl=%" PRI__u64
300 	       ", rsv_rfer=%" PRI__u64 ", rsv_excl=%" PRI__u64
301 	       "}, ",
302 	       inherit->lim.max_rfer, inherit->lim.max_excl,
303 	       inherit->lim.rsv_rfer, inherit->lim.rsv_excl);
304 	if (verbose) {
305 		unsigned int i;
306 		printf("qgroups=[");
307 		for (i = 0; i < inherit->num_qgroups; i++) {
308 			if (i > 0)
309 				printf(", ");
310 			printf("%" PRI__u64, inherit->qgroups[i]);
311 		}
312 		printf("]");
313 	} else
314 		printf("...");
315 	printf("}");
316 }
317 
318 
319 static void
btrfs_print_vol_args_v2(struct btrfs_ioctl_vol_args_v2 * args,int print_qgroups)320 btrfs_print_vol_args_v2(struct btrfs_ioctl_vol_args_v2 *args, int print_qgroups)
321 {
322 	printf("{fd=%d, flags=", (int) args->fd);
323 	prfl_btrfs(btrfs_snap_flags_v2, args->flags, "BTRFS_SUBVOL_???");
324 
325 	if (args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
326 		printf(", size=%" PRI__u64 ", qgroup_inherit=", args->size);
327 		if (args->qgroup_inherit && print_qgroups)
328 			btrfs_print_qgroup_inherit(args->qgroup_inherit);
329 		else if (args->qgroup_inherit)
330 			printf("%p", args->qgroup_inherit);
331 		else
332 			printf("NULL");
333 	}
334 	printf(", name=\"%s\"}", args->name);
335 }
336 
337 /*
338  * Consumes argument, returns nothing:
339  * - BTRFS_IOC_SNAP_CREATE
340  * - BTRFS_IOC_SUBVOL_CREATE
341  * - BTRFS_IOC_SNAP_DESTROY
342  * - BTRFS_IOC_DEFAULT_SUBVOL
343  *
344  * Consumes argument, returns u64:
345  * - BTRFS_IOC_SNAP_CREATE_V2
346  * - BTRFS_IOC_SUBVOL_CREATE_V2
347  */
348 
349 static void
btrfs_test_subvol_ioctls(void)350 btrfs_test_subvol_ioctls(void)
351 {
352 	const char *subvol_name = "subvol-name";
353 	char *long_subvol_name;
354 	void *bad_pointer = (void *) (unsigned long) 0xdeadbeeffffffeedULL;
355 	uint64_t u64val = 0xdeadbeefbadc0dedULL;
356 	struct btrfs_ioctl_vol_args vol_args = {};
357 	struct btrfs_ioctl_vol_args_v2 vol_args_v2 = {
358 		.fd = 2,
359 		.flags = max_flags_plus_one(2),
360 	};
361 
362 	long_subvol_name = malloc(BTRFS_PATH_NAME_MAX);
363 	if (!long_subvol_name)
364 		perror_msg_and_fail("malloc failed");
365 	memset(long_subvol_name, 'f', BTRFS_PATH_NAME_MAX);
366 	long_subvol_name[BTRFS_PATH_NAME_MAX - 1] = '\0';
367 
368 	strcpy(vol_args.name, subvol_name);
369 
370 	ioctl(-1, BTRFS_IOC_SNAP_CREATE, NULL);
371 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
372 	       ioc(BTRFS_IOC_SNAP_CREATE));
373 
374 	ioctl(-1, BTRFS_IOC_SNAP_CREATE, &vol_args);
375 	printf("ioctl(-1, %s, {fd=0, name=\"%s\"}) = -1 EBADF (%m)\n",
376 	       ioc(BTRFS_IOC_SNAP_CREATE), vol_args.name);
377 
378 	ioctl(-1, BTRFS_IOC_SUBVOL_CREATE, &vol_args);
379 	printf("ioctl(-1, %s, {fd=0, name=\"%s\"}) = -1 EBADF (%m)\n",
380 	       ioc(BTRFS_IOC_SUBVOL_CREATE), vol_args.name);
381 
382 	ioctl(-1, BTRFS_IOC_SNAP_DESTROY, &vol_args);
383 	printf("ioctl(-1, %s, {fd=0, name=\"%s\"}) = -1 EBADF (%m)\n",
384 	       ioc(BTRFS_IOC_SNAP_DESTROY), vol_args.name);
385 
386 	strncpy(vol_args.name, long_subvol_name, BTRFS_PATH_NAME_MAX);
387 	ioctl(-1, BTRFS_IOC_SNAP_CREATE, &vol_args);
388 	printf("ioctl(-1, %s, {fd=0, name=\"%s\"}) = -1 EBADF (%m)\n",
389 	       ioc(BTRFS_IOC_SNAP_CREATE), vol_args.name);
390 
391 	ioctl(-1, BTRFS_IOC_SUBVOL_CREATE, &vol_args);
392 	printf("ioctl(-1, %s, {fd=0, name=\"%s\"}) = -1 EBADF (%m)\n",
393 	       ioc(BTRFS_IOC_SUBVOL_CREATE), vol_args.name);
394 
395 	ioctl(-1, BTRFS_IOC_SNAP_DESTROY, &vol_args);
396 	printf("ioctl(-1, %s, {fd=0, name=\"%s\"}) = -1 EBADF (%m)\n",
397 	       ioc(BTRFS_IOC_SNAP_DESTROY), vol_args.name);
398 
399 	long_subvol_name = realloc(long_subvol_name, BTRFS_SUBVOL_NAME_MAX);
400 	if (!long_subvol_name)
401 		perror_msg_and_fail("realloc failed");
402 
403 	ioctl(-1, BTRFS_IOC_SNAP_CREATE_V2, NULL);
404 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
405 	       ioc(BTRFS_IOC_SNAP_CREATE_V2));
406 
407 	ioctl(-1, BTRFS_IOC_SUBVOL_CREATE_V2, NULL);
408 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
409 	       ioc(BTRFS_IOC_SUBVOL_CREATE_V2));
410 
411 	strcpy(vol_args_v2.name, subvol_name);
412 	printf("ioctl(-1, %s, ", ioc(BTRFS_IOC_SNAP_CREATE_V2));
413 	btrfs_print_vol_args_v2(&vol_args_v2, 1);
414 	ioctl(-1, BTRFS_IOC_SNAP_CREATE_V2, &vol_args_v2);
415 	printf(") = -1 EBADF (%m)\n");
416 
417 	printf("ioctl(-1, %s, ", ioc(BTRFS_IOC_SUBVOL_CREATE_V2));
418 	btrfs_print_vol_args_v2(&vol_args_v2, 1);
419 	ioctl(-1, BTRFS_IOC_SUBVOL_CREATE_V2, &vol_args_v2);
420 	printf(") = -1 EBADF (%m)\n");
421 
422 	strncpy(vol_args_v2.name, long_subvol_name, BTRFS_SUBVOL_NAME_MAX);
423 	printf("ioctl(-1, %s, ", ioc(BTRFS_IOC_SNAP_CREATE_V2));
424 	btrfs_print_vol_args_v2(&vol_args_v2, 1);
425 	ioctl(-1, BTRFS_IOC_SNAP_CREATE_V2, &vol_args_v2);
426 	printf(") = -1 EBADF (%m)\n");
427 
428 	printf("ioctl(-1, %s, ", ioc(BTRFS_IOC_SUBVOL_CREATE_V2));
429 	btrfs_print_vol_args_v2(&vol_args_v2, 1);
430 	ioctl(-1, BTRFS_IOC_SUBVOL_CREATE_V2, &vol_args_v2);
431 	printf(") = -1 EBADF (%m)\n");
432 
433 	strcpy(vol_args_v2.name, subvol_name);
434 	vol_args_v2.qgroup_inherit = bad_pointer;
435 
436 	printf("ioctl(-1, %s, ", ioc(BTRFS_IOC_SNAP_CREATE_V2));
437 	btrfs_print_vol_args_v2(&vol_args_v2, 0);
438 	ioctl(-1, BTRFS_IOC_SNAP_CREATE_V2, &vol_args_v2);
439 	printf(") = -1 EBADF (%m)\n");
440 
441 	printf("ioctl(-1, %s, ", ioc(BTRFS_IOC_SUBVOL_CREATE_V2));
442 	btrfs_print_vol_args_v2(&vol_args_v2, 0);
443 	ioctl(-1, BTRFS_IOC_SUBVOL_CREATE_V2, &vol_args_v2);
444 	printf(") = -1 EBADF (%m)\n");
445 
446 	const unsigned int n_qgroups = 8;
447 	unsigned int i;
448 	struct btrfs_qgroup_inherit *inherit;
449 	vol_args_v2.size =
450 		sizeof(*inherit) + n_qgroups * sizeof(inherit->qgroups[0]);
451 	inherit = tail_alloc(vol_args_v2.size);
452 
453 	inherit->flags = 0x3;
454 	inherit->num_ref_copies = 0;
455 	inherit->num_excl_copies = 0;
456 	inherit->num_qgroups = n_qgroups;
457 	for (i = 0; i < n_qgroups; i++)
458 		inherit->qgroups[i] = 1ULL << i;
459 	inherit->lim.flags = 0x7f;
460 	inherit->lim.max_rfer = u64val;
461 	inherit->lim.max_excl = u64val;
462 	inherit->lim.rsv_rfer = u64val;
463 	inherit->lim.rsv_excl = u64val;
464 	vol_args_v2.qgroup_inherit = inherit;
465 
466 	printf("ioctl(-1, %s, ", ioc(BTRFS_IOC_SNAP_CREATE_V2));
467 	btrfs_print_vol_args_v2(&vol_args_v2, 1);
468 	ioctl(-1, BTRFS_IOC_SNAP_CREATE_V2, &vol_args_v2);
469 	printf(") = -1 EBADF (%m)\n");
470 
471 	printf("ioctl(-1, %s, ", ioc(BTRFS_IOC_SUBVOL_CREATE_V2));
472 	btrfs_print_vol_args_v2(&vol_args_v2, 1);
473 	ioctl(-1, BTRFS_IOC_SUBVOL_CREATE_V2, &vol_args_v2);
474 	printf(") = -1 EBADF (%m)\n");
475 
476 	ioctl(-1, BTRFS_IOC_DEFAULT_SUBVOL, NULL);
477 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
478 	       ioc(BTRFS_IOC_DEFAULT_SUBVOL));
479 
480 	ioctl(-1, BTRFS_IOC_DEFAULT_SUBVOL, &u64val);
481 	printf("ioctl(-1, %s, [%" PRIu64 "]) = -1 EBADF (%m)\n",
482 	       ioc(BTRFS_IOC_DEFAULT_SUBVOL), u64val);
483 
484 	printf("ioctl(-1, %s, ", ioc(BTRFS_IOC_SUBVOL_SETFLAGS));
485 	prfl_btrfs(btrfs_snap_flags_v2, vol_args_v2.flags,
486 		   "BTRFS_SUBVOL_???");
487 	ioctl(-1, BTRFS_IOC_SUBVOL_SETFLAGS, &vol_args_v2.flags);
488 	printf(") = -1 EBADF (%m)\n");
489 
490 	if (write_ok) {
491 		struct btrfs_ioctl_vol_args_v2 args_passed;
492 		long ret;
493 		/*
494 		 * Returns transid if flags & BTRFS_SUBVOL_CREATE_ASYNC
495 		 * - BTRFS_IOC_SNAP_CREATE_V2
496 		 * - BTRFS_IOC_SUBVOL_CREATE_V2
497 		 */
498 		int subvolfd;
499 
500 		strncpy(vol_args_v2.name, subvol_name,
501 			sizeof(vol_args_v2.name));
502 		vol_args_v2.flags = BTRFS_SUBVOL_CREATE_ASYNC;
503 		vol_args_v2.size = 0;
504 		vol_args_v2.qgroup_inherit = NULL;
505 		args_passed = vol_args_v2;
506 		printf("ioctl(%d, %s, ",
507 		       btrfs_test_dir_fd, ioc(BTRFS_IOC_SUBVOL_CREATE_V2));
508 		btrfs_print_vol_args_v2(&vol_args_v2, 1);
509 		ret = ioctl(btrfs_test_dir_fd, BTRFS_IOC_SUBVOL_CREATE_V2,
510 		      &args_passed);
511 		if (ret < 0)
512 			perror_msg_and_fail("ioctl(BTRFS_IOC_SUBVOL_CREATE_V2) "
513 					    "failed");
514 		printf(" => {transid=%" PRI__u64 "}) = 0\n",
515 			args_passed.transid);
516 
517 		subvolfd = openat(btrfs_test_dir_fd, subvol_name,
518 				  O_RDONLY|O_DIRECTORY);
519 		if (subvolfd < 0)
520 			perror_msg_and_fail("openat(%s) failed", subvol_name);
521 
522 		strncpy(vol_args_v2.name, long_subvol_name, BTRFS_NAME_LEN);
523 		vol_args_v2.fd = subvolfd;
524 		args_passed = vol_args_v2;
525 		printf("ioctl(%d, %s, ",
526 		       btrfs_test_dir_fd, ioc(BTRFS_IOC_SNAP_CREATE_V2));
527 		btrfs_print_vol_args_v2(&args_passed, 1);
528 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_SNAP_CREATE_V2,
529 		      &args_passed);
530 		printf(" => {transid=%" PRI__u64 "}) = 0\n",
531 			args_passed.transid);
532 
533 		/* This only works when mounted w/ -ouser_subvol_rm_allowed */
534 		strncpy(vol_args.name, long_subvol_name, 255);
535 		vol_args.name[255] = 0;
536 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_SNAP_DESTROY, &vol_args);
537 		printf("ioctl(%d, %s, {fd=%d, name=\"%.*s\"}) = 0\n",
538 		       btrfs_test_dir_fd, ioc(BTRFS_IOC_SNAP_DESTROY),
539 		       (int) vol_args.fd, 255, long_subvol_name);
540 
541 		strcpy(vol_args.name, subvol_name);
542 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_SNAP_DESTROY, &vol_args);
543 		printf("ioctl(%d, %s, {fd=%d, name=\"%s\"}) = 0\n",
544 		       btrfs_test_dir_fd, ioc(BTRFS_IOC_SNAP_DESTROY),
545 		       (int) vol_args.fd, subvol_name);
546 
547 		close(subvolfd);
548 	}
549 	free(long_subvol_name);
550 }
551 
552 static void
btrfs_print_balance_args(struct btrfs_balance_args * args)553 btrfs_print_balance_args(struct btrfs_balance_args *args)
554 {
555 	printf("{profiles=");
556 	prfl_btrfs(btrfs_space_info_flags, args->profiles,
557 		   "BTRFS_BLOCK_GROUP_???");
558 	print_uint64(", usage=", args->usage);
559 	printf(", devid=makedev(%u, %u)",
560 	       major(args->devid), minor(args->devid));
561 	print_uint64(", pstart=", args->pstart);
562 	print_uint64(", pend=", args->pend);
563 	print_uint64(", vstart=", args->vstart);
564 	print_uint64(", vend=", args->vend);
565 	print_uint64(", target=", args->target);
566 	printf(", flags=");
567 	prfl_btrfs(btrfs_balance_args, args->flags, "BTRFS_BALANCE_ARGS_???");
568 	printf("}");
569 }
570 
571 /*
572  * Accepts argument, returns nothing
573  * - BTRFS_IOC_BALANCE
574  * - BTRFS_IOC_BALANCE_CTL
575  *
576  * Accepts argument, returns argument
577  * - BTRFS_IOC_BALANCE_V2
578  */
579 static void
btrfs_test_balance_ioctls(void)580 btrfs_test_balance_ioctls(void)
581 {
582 	struct btrfs_ioctl_balance_args args = {
583 		.flags = 0x3f,
584 		.data = {
585 			.profiles = 0x7,
586 			.flags = 0x7,
587 			.devid = 1,
588 			.pend = -1ULL,
589 			.vend = -1ULL,
590 		},
591 
592 		.meta = {
593 			.profiles = 0x38,
594 			.flags = 0x38,
595 			.devid = 1,
596 		},
597 
598 		.sys = {
599 			.profiles = 0x1c0 | (1ULL << 48),
600 			.flags = 0x4c0,
601 			.devid = 1,
602 		},
603 	};
604 	struct btrfs_ioctl_vol_args vol_args = {};
605 
606 	ioctl(-1, BTRFS_IOC_BALANCE_CTL, 1);
607 	printf("ioctl(-1, %s, %sBTRFS_BALANCE_CTL_PAUSE%s) = -1 EBADF (%m)\n",
608 	       ioc(BTRFS_IOC_BALANCE_CTL),
609 	       verbose_xlat ? "0x1 /* " : "",
610 	       verbose_xlat ? " */" : "");
611 
612 	ioctl(-1, BTRFS_IOC_BALANCE_CTL, 2);
613 	printf("ioctl(-1, %s, "
614 	       "%sBTRFS_BALANCE_CTL_CANCEL%s) = -1 EBADF (%m)\n",
615 	       ioc(BTRFS_IOC_BALANCE_CTL),
616 	       verbose_xlat ? "0x2 /* " : "",
617 	       verbose_xlat ? " */" : "");
618 
619 	ioctl(-1, BTRFS_IOC_BALANCE, NULL);
620 	printf("ioctl(-1, %s) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_BALANCE));
621 
622 	ioctl(-1, BTRFS_IOC_BALANCE, &vol_args);
623 	printf("ioctl(-1, %s) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_BALANCE));
624 
625 	/* struct btrfs_ioctl_balance_args */
626 	ioctl(-1, BTRFS_IOC_BALANCE_V2, NULL);
627 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
628 	       ioc(BTRFS_IOC_BALANCE_V2));
629 
630 	printf("ioctl(-1, %s, {flags=", ioc(BTRFS_IOC_BALANCE_V2));
631 	prfl_btrfs(btrfs_balance_flags, args.flags, "BTRFS_BALANCE_???");
632 	printf(", data=");
633 	btrfs_print_balance_args(&args.data);
634 	printf(", meta=");
635 	btrfs_print_balance_args(&args.meta);
636 	printf(", sys=");
637 	btrfs_print_balance_args(&args.sys);
638 	ioctl(-1, BTRFS_IOC_BALANCE_V2, &args);
639 	printf("}) = -1 EBADF (%m)\n");
640 
641 	if (write_ok) {
642 		long ret;
643 
644 		args.flags = BTRFS_BALANCE_DATA | BTRFS_BALANCE_METADATA |
645 			     BTRFS_BALANCE_SYSTEM;
646 		args.data.flags = 0;
647 		args.data.profiles = 0;
648 		args.meta.flags = 0;
649 		args.meta.profiles = 0;
650 		args.sys.flags = 0;
651 		args.sys.profiles = 0;
652 
653 		/*
654 		 * We should keep args the same for data in meta in case
655 		 * volume-under-tests uses mixed groups data and metadata.
656 		 */
657 		args.meta.pend = -1ULL;
658 		args.meta.vend = -1ULL;
659 
660 		printf("ioctl(%d, %s, {flags=",
661 			btrfs_test_dir_fd, ioc(BTRFS_IOC_BALANCE_V2));
662 
663 		prfl_btrfs(btrfs_balance_flags, args.flags,
664 			   "BTRFS_BALANCE_???");
665 		printf(", data=");
666 		btrfs_print_balance_args(&args.data);
667 		printf(", meta=");
668 		btrfs_print_balance_args(&args.meta);
669 		printf(", sys=");
670 		btrfs_print_balance_args(&args.sys);
671 		ret = ioctl(btrfs_test_dir_fd, BTRFS_IOC_BALANCE_V2,  &args);
672 		if (ret < 0) {
673 			printf("}) = %s\n", sprintrc(ret));
674 		} else {
675 			printf("} => {flags=");
676 			prfl_btrfs(btrfs_balance_flags, args.flags,
677 				   "BTRFS_BALANCE_???");
678 			printf(", state=");
679 			prfl_btrfs(btrfs_balance_state, args.state,
680 				   "BTRFS_BALANCE_STATE_???");
681 			printf(", data=");
682 			btrfs_print_balance_args(&args.data);
683 			printf(", meta=");
684 			btrfs_print_balance_args(&args.meta);
685 			printf(", sys=");
686 			btrfs_print_balance_args(&args.sys);
687 			printf("}) = %ld\n", ret);
688 		}
689 	}
690 }
691 
692 /*
693  * Consumes argument, returns nothing:
694  * - BTRFS_IOC_RESIZE
695  *
696  * Requires /dev/btrfs-control, consumes argument, returns nothing:
697  * - BTRFS_IOC_SCAN_DEV
698  * - BTRFS_IOC_DEVICES_READY
699  *
700  */
701 static void
btrfs_test_device_ioctls(void)702 btrfs_test_device_ioctls(void)
703 {
704 	const char *devid = "1";
705 	const char *devname = "/dev/sda1";
706 	struct btrfs_ioctl_vol_args args = {
707 		.fd = 2,
708 	};
709 
710 	ioctl(-1, BTRFS_IOC_RESIZE, NULL);
711 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_RESIZE));
712 
713 	strcpy(args.name, devid);
714 	ioctl(-1, BTRFS_IOC_RESIZE, &args);
715 	printf("ioctl(-1, %s, {fd=%d, name=\"%s\"}) = -1 EBADF (%m)\n",
716 	       ioc(BTRFS_IOC_RESIZE), (int) args.fd, args.name);
717 
718 	ioctl(-1, BTRFS_IOC_SCAN_DEV, NULL);
719 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
720 	       ioc(BTRFS_IOC_SCAN_DEV));
721 
722 	strcpy(args.name, devname);
723 	ioctl(-1, BTRFS_IOC_SCAN_DEV, &args);
724 	printf("ioctl(-1, %s, {fd=%d, name=\"%s\"}) = -1 EBADF (%m)\n",
725 	       ioc(BTRFS_IOC_SCAN_DEV), (int) args.fd, args.name);
726 
727 	ioctl(-1, BTRFS_IOC_ADD_DEV, NULL);
728 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_ADD_DEV));
729 
730 	ioctl(-1, BTRFS_IOC_ADD_DEV, &args);
731 	printf("ioctl(-1, %s, {fd=%d, name=\"%s\"}) = -1 EBADF (%m)\n",
732 	       ioc(BTRFS_IOC_ADD_DEV), (int) args.fd, args.name);
733 
734 	ioctl(-1, BTRFS_IOC_RM_DEV, NULL);
735 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_RM_DEV));
736 
737 	ioctl(-1, BTRFS_IOC_RM_DEV, &args);
738 	printf("ioctl(-1, %s, {fd=%d, name=\"%s\"}) = -1 EBADF (%m)\n",
739 	       ioc(BTRFS_IOC_RM_DEV), (int) args.fd, args.name);
740 
741 }
742 
743 /*
744  * Consumes argument, returns nothing:
745  * - BTRFS_IOC_CLONE
746  * - BTRFS_IOC_CLONE_RANGE
747  */
748 static void
btrfs_test_clone_ioctls(void)749 btrfs_test_clone_ioctls(void)
750 {
751 	int clone_fd = 4;
752 	struct btrfs_ioctl_clone_range_args args = {
753 		.src_fd = clone_fd,
754 		.src_offset = 4096,
755 		.src_length = 16384,
756 		.dest_offset = 128 * 1024,
757 	};
758 
759 	ioctl(-1, BTRFS_IOC_CLONE, clone_fd);
760 	printf("ioctl(-1, %s, %x) = -1 EBADF (%m)\n",
761 	       sprint_xlat_(BTRFS_IOC_CLONE, "BTRFS_IOC_CLONE or FICLONE"),
762 	       clone_fd);
763 
764 	ioctl(-1, BTRFS_IOC_CLONE_RANGE, NULL);
765 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
766 	       sprint_xlat_(BTRFS_IOC_CLONE_RANGE,
767 			    "BTRFS_IOC_CLONE_RANGE or FICLONERANGE"));
768 
769 	ioctl(-1, BTRFS_IOC_CLONE_RANGE, &args);
770 	printf("ioctl(-1, %s, "
771 	       "{src_fd=%d, src_offset=%" PRI__u64 ", src_length=%" PRI__u64
772 	       ", dest_offset=%" PRI__u64 "}) = -1 EBADF (%m)\n",
773 	       sprint_xlat_(BTRFS_IOC_CLONE_RANGE,
774 			    "BTRFS_IOC_CLONE_RANGE or FICLONERANGE"),
775 		(int) args.src_fd, args.src_offset, args.src_length,
776 		args.dest_offset);
777 }
778 
779 #define BTRFS_COMPRESS_TYPES 2
780 #define BTRFS_INVALID_COMPRESS (BTRFS_COMPRESS_TYPES + 1)
781 
782 static void
btrfs_print_defrag_range_args(struct btrfs_ioctl_defrag_range_args * args,bool compress_type_known)783 btrfs_print_defrag_range_args(struct btrfs_ioctl_defrag_range_args *args,
784 			      bool compress_type_known)
785 {
786 	printf("{start=%" PRIu64, (uint64_t) args->start);
787 	print_uint64(", len=", args->len);
788 
789 	printf(", flags=");
790 	prfl_btrfs(btrfs_defrag_flags, args->flags, "BTRFS_DEFRAG_RANGE_???");
791 	printf(", extent_thresh=%u, compress_type=", args->extent_thresh);
792 	prxval_btrfs(btrfs_compress_types, args->compress_type,
793 		     "BTRFS_COMPRESS_???", compress_type_known);
794 	printf("}");
795 }
796 
797 /*
798  * Consumes argument, returns nothing:
799  * - BTRFS_IOC_DEFRAG
800  * - BTRFS_DEFRAG_RANGE
801  */
802 static void
btrfs_test_defrag_ioctls(void)803 btrfs_test_defrag_ioctls(void)
804 {
805 	struct btrfs_ioctl_vol_args vol_args = {};
806 	struct btrfs_ioctl_defrag_range_args args = {
807 		.start = 0,
808 		.len = -1ULL,
809 		.flags = max_flags_plus_one(1),
810 		.extent_thresh = 128 * 1024,
811 		.compress_type = 2, /* BTRFS_COMPRESS_LZO */
812 	};
813 
814 	/*
815 	 * These are documented as using vol_args but don't
816 	 * actually consume it.
817 	 */
818 	ioctl(-1, BTRFS_IOC_DEFRAG, NULL);
819 	printf("ioctl(-1, %s) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_DEFRAG));
820 
821 	ioctl(-1, BTRFS_IOC_DEFRAG, &vol_args);
822 	printf("ioctl(-1, %s) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_DEFRAG));
823 
824 	/* struct btrfs_ioctl_defrag_range_args */
825 	ioctl(-1, BTRFS_IOC_DEFRAG_RANGE, NULL);
826 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
827 	       ioc(BTRFS_IOC_DEFRAG_RANGE));
828 
829 	printf("ioctl(-1, %s, ", ioc(BTRFS_IOC_DEFRAG_RANGE));
830 	btrfs_print_defrag_range_args(&args, true);
831 	ioctl(-1, BTRFS_IOC_DEFRAG_RANGE, &args);
832 	printf(") = -1 EBADF (%m)\n");
833 
834 	args.compress_type = BTRFS_INVALID_COMPRESS;
835 	printf("ioctl(-1, %s, ", ioc(BTRFS_IOC_DEFRAG_RANGE));
836 	btrfs_print_defrag_range_args(&args, false);
837 	ioctl(-1, BTRFS_IOC_DEFRAG_RANGE, &args);
838 	printf(") = -1 EBADF (%m)\n");
839 
840 	args.len--;
841 	printf("ioctl(-1, %s, ", ioc(BTRFS_IOC_DEFRAG_RANGE));
842 	btrfs_print_defrag_range_args(&args, false);
843 	ioctl(-1, BTRFS_IOC_DEFRAG_RANGE, &args);
844 	printf(") = -1 EBADF (%m)\n");
845 }
846 
847 static const char *
xlookup(const struct xlat * xlat,const uint64_t val)848 xlookup(const struct xlat *xlat, const uint64_t val)
849 {
850 	for (; xlat->str != NULL; xlat++)
851 		if (xlat->val == val)
852 			return xlat->str;
853 	return NULL;
854 }
855 
856 static void
btrfs_print_objectid(uint64_t objectid)857 btrfs_print_objectid(uint64_t objectid)
858 {
859 	const char *str = xlookup(btrfs_tree_objectids, objectid);
860 	if (str) {
861 		if (verbose_xlat)
862 			printf("%" PRIu64 " /* %s */", objectid, str);
863 		else
864 			printf("%s", str);
865 	} else {
866 		printf("%" PRIu64, objectid);
867 	}
868 }
869 
870 static void
btrfs_print_key_type(uint32_t type)871 btrfs_print_key_type(uint32_t type)
872 {
873 	const char *str = xlookup(btrfs_key_types, type);
874 	if (str) {
875 		if (verbose_xlat)
876 			printf("%u /* %s */", type, str);
877 		else
878 			printf("%s", str);
879 	} else {
880 		printf("%u", type);
881 	}
882 }
883 
884 static void
btrfs_print_search_key(struct btrfs_ioctl_search_key * key)885 btrfs_print_search_key(struct btrfs_ioctl_search_key *key)
886 {
887 	printf("key={tree_id=");
888 	btrfs_print_objectid(key->tree_id);
889 	if (verbose || key->min_objectid != 256) {
890 		printf(", min_objectid=");
891 		btrfs_print_objectid(key->min_objectid);
892 	}
893 	if (verbose || key->max_objectid != -256ULL) {
894 		printf(", max_objectid=");
895 		btrfs_print_objectid(key->max_objectid);
896 	}
897 	print_uint64(", min_offset=", key->min_offset);
898 	print_uint64(", max_offset=", key->max_offset);
899 	print_uint64(", min_transid=", key->min_transid);
900 	print_uint64(", max_transid=", key->max_transid);
901 	printf(", min_type=");
902 	btrfs_print_key_type(key->min_type);
903 	printf(", max_type=");
904 	btrfs_print_key_type(key->max_type);
905 	printf(", nr_items=%u}", key->nr_items);
906 }
907 
908 static void
btrfs_print_tree_search_buf(struct btrfs_ioctl_search_key * key,void * buf,uint64_t buf_size)909 btrfs_print_tree_search_buf(struct btrfs_ioctl_search_key *key,
910 			    void *buf, uint64_t buf_size)
911 {
912 	if (verbose) {
913 		uint64_t i;
914 		uint64_t off = 0;
915 		printf("buf=[");
916 		for (i = 0; i < key->nr_items; i++) {
917 			struct btrfs_ioctl_search_header *sh;
918 			sh = (typeof(sh))(buf + off);
919 			if (i)
920 				printf(", ");
921 			printf("{transid=%" PRI__u64 ", objectid=",
922 				sh->transid);
923 			btrfs_print_objectid(sh->objectid);
924 			printf(", offset=%" PRI__u64 ", type=", sh->offset);
925 			btrfs_print_key_type(sh->type);
926 			printf(", len=%u}", sh->len);
927 			off += sizeof(*sh) + sh->len;
928 		}
929 		printf("]");
930 	} else
931 		printf("...");
932 }
933 
934 /*
935  * Consumes argument, returns argument:
936  * - BTRFS_IOC_TREE_SEARCH
937  * - BTRFS_IOC_TREE_SEARCH_V2
938  */
939 static void
btrfs_test_search_ioctls(void)940 btrfs_test_search_ioctls(void)
941 {
942 	struct btrfs_ioctl_search_key key_reference = {
943 		.tree_id = 5,
944 		.min_objectid = 256,
945 		.max_objectid = -1ULL,
946 		.min_offset = 0,
947 		.max_offset = -1ULL,
948 		.min_transid = 0,
949 		.max_transid = -1ULL,
950 		.min_type = 0,
951 		.max_type = -1U,
952 		.nr_items = 10,
953 	};
954 	struct btrfs_ioctl_search_args search_args;
955 	struct btrfs_ioctl_search_args_v2 search_args_v2 = {
956 		.buf_size = 4096,
957 	};
958 
959 	ioctl(-1, BTRFS_IOC_TREE_SEARCH, NULL);
960 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
961 	       ioc(BTRFS_IOC_TREE_SEARCH));
962 
963 	ioctl(-1, BTRFS_IOC_TREE_SEARCH_V2, NULL);
964 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
965 	       ioc(BTRFS_IOC_TREE_SEARCH_V2));
966 
967 	search_args.key = key_reference;
968 	printf("ioctl(-1, %s, {", ioc(BTRFS_IOC_TREE_SEARCH));
969 	btrfs_print_search_key(&search_args.key);
970 	ioctl(-1, BTRFS_IOC_TREE_SEARCH, &search_args);
971 	printf("}) = -1 EBADF (%m)\n");
972 
973 	search_args_v2.key = key_reference;
974 	printf("ioctl(-1, %s, {", ioc(BTRFS_IOC_TREE_SEARCH_V2));
975 	btrfs_print_search_key(&search_args_v2.key);
976 	ioctl(-1, BTRFS_IOC_TREE_SEARCH_V2, &search_args_v2);
977 	printf(", buf_size=%" PRIu64 "}) = -1 EBADF (%m)\n",
978 	       (uint64_t)search_args_v2.buf_size);
979 
980 	key_reference.min_objectid = 6;
981 	key_reference.max_objectid = 7;
982 	search_args.key = key_reference;
983 	printf("ioctl(-1, %s, {", ioc(BTRFS_IOC_TREE_SEARCH));
984 	btrfs_print_search_key(&search_args.key);
985 	ioctl(-1, BTRFS_IOC_TREE_SEARCH, &search_args);
986 	printf("}) = -1 EBADF (%m)\n");
987 
988 	search_args_v2.key = key_reference;
989 	printf("ioctl(-1, %s, {", ioc(BTRFS_IOC_TREE_SEARCH_V2));
990 	btrfs_print_search_key(&search_args_v2.key);
991 	ioctl(-1, BTRFS_IOC_TREE_SEARCH_V2, &search_args_v2);
992 	printf(", buf_size=%" PRIu64 "}) = -1 EBADF (%m)\n",
993 	       (uint64_t)search_args_v2.buf_size);
994 
995 	key_reference.min_offset++;
996 	key_reference.max_offset--;
997 	search_args.key = key_reference;
998 	printf("ioctl(-1, %s, {", ioc(BTRFS_IOC_TREE_SEARCH));
999 	btrfs_print_search_key(&search_args.key);
1000 	ioctl(-1, BTRFS_IOC_TREE_SEARCH, &search_args);
1001 	printf("}) = -1 EBADF (%m)\n");
1002 
1003 	search_args_v2.key = key_reference;
1004 	printf("ioctl(-1, %s, {", ioc(BTRFS_IOC_TREE_SEARCH_V2));
1005 	btrfs_print_search_key(&search_args_v2.key);
1006 	ioctl(-1, BTRFS_IOC_TREE_SEARCH_V2, &search_args_v2);
1007 	printf(", buf_size=%" PRIu64 "}) = -1 EBADF (%m)\n",
1008 	       (uint64_t)search_args_v2.buf_size);
1009 
1010 	key_reference.min_transid++;
1011 	key_reference.max_transid--;
1012 	search_args.key = key_reference;
1013 	printf("ioctl(-1, %s, {", ioc(BTRFS_IOC_TREE_SEARCH));
1014 	btrfs_print_search_key(&search_args.key);
1015 	ioctl(-1, BTRFS_IOC_TREE_SEARCH, &search_args);
1016 	printf("}) = -1 EBADF (%m)\n");
1017 
1018 	search_args_v2.key = key_reference;
1019 	printf("ioctl(-1, %s, {", ioc(BTRFS_IOC_TREE_SEARCH_V2));
1020 	btrfs_print_search_key(&search_args_v2.key);
1021 	ioctl(-1, BTRFS_IOC_TREE_SEARCH_V2, &search_args_v2);
1022 	printf(", buf_size=%" PRIu64 "}) = -1 EBADF (%m)\n",
1023 	       (uint64_t)search_args_v2.buf_size);
1024 
1025 	key_reference.min_type = 1;
1026 	key_reference.max_type = 12;
1027 	search_args.key = key_reference;
1028 	printf("ioctl(-1, %s, {", ioc(BTRFS_IOC_TREE_SEARCH));
1029 	btrfs_print_search_key(&search_args.key);
1030 	ioctl(-1, BTRFS_IOC_TREE_SEARCH, &search_args);
1031 	printf("}) = -1 EBADF (%m)\n");
1032 
1033 	search_args_v2.key = key_reference;
1034 	printf("ioctl(-1, %s, {", ioc(BTRFS_IOC_TREE_SEARCH_V2));
1035 	btrfs_print_search_key(&search_args_v2.key);
1036 	ioctl(-1, BTRFS_IOC_TREE_SEARCH_V2, &search_args_v2);
1037 	printf(", buf_size=%" PRIu64 "}) = -1 EBADF (%m)\n",
1038 	       (uint64_t)search_args_v2.buf_size);
1039 
1040 	if (btrfs_test_root) {
1041 		struct btrfs_ioctl_search_args_v2 *args;
1042 		int bufsize = 4096;
1043 
1044 		key_reference.tree_id = 5;
1045 		key_reference.min_type = 1;
1046 		key_reference.max_type = 1;
1047 		key_reference.min_objectid = 256;
1048 		key_reference.max_objectid = 357;
1049 		key_reference.min_offset = 0;
1050 		key_reference.max_offset = -1ULL;
1051 
1052 		search_args.key = key_reference;
1053 		printf("ioctl(%d, %s, {",
1054 			btrfs_test_dir_fd, ioc(BTRFS_IOC_TREE_SEARCH));
1055 		btrfs_print_search_key(&search_args.key);
1056 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_TREE_SEARCH, &search_args);
1057 		printf("} => {key={nr_items=%u}, ",
1058 			search_args.key.nr_items);
1059 		btrfs_print_tree_search_buf(&search_args.key, search_args.buf,
1060 					    sizeof(search_args.buf));
1061 		printf("}) = 0\n");
1062 
1063 		args = malloc(sizeof(*args) + bufsize);
1064 		if (!args)
1065 			perror_msg_and_fail("malloc failed");
1066 
1067 		args->key = key_reference;
1068 		args->buf_size = bufsize;
1069 		printf("ioctl(%d, %s, {",
1070 			btrfs_test_dir_fd, ioc(BTRFS_IOC_TREE_SEARCH_V2));
1071 		btrfs_print_search_key(&key_reference);
1072 		printf(", buf_size=%" PRIu64 "}", (uint64_t) args->buf_size);
1073 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_TREE_SEARCH_V2, args);
1074 		printf(" => {key={nr_items=%u}, buf_size=%" PRIu64 ", ",
1075 			args->key.nr_items, (uint64_t)args->buf_size);
1076 		btrfs_print_tree_search_buf(&args->key, args->buf,
1077 					    args->buf_size);
1078 		printf("}) = 0\n");
1079 
1080 		args->key = key_reference;
1081 		args->buf_size = sizeof(struct btrfs_ioctl_search_header);
1082 		printf("ioctl(%d, %s, {",
1083 			btrfs_test_dir_fd, ioc(BTRFS_IOC_TREE_SEARCH_V2));
1084 		btrfs_print_search_key(&args->key);
1085 		printf(", buf_size=%" PRIu64 "}", (uint64_t)args->buf_size);
1086 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_TREE_SEARCH_V2, args);
1087 		printf(" => {buf_size=%" PRIu64 "}) = -1 EOVERFLOW (%m)\n",
1088 			(uint64_t)args->buf_size);
1089 		free(args);
1090 	}
1091 }
1092 
1093 /*
1094  * Consumes argument, returns argument:
1095  * - BTRFS_IOC_INO_LOOKUP
1096  */
1097 static void
btrfs_test_ino_lookup_ioctl(void)1098 btrfs_test_ino_lookup_ioctl(void)
1099 {
1100 	struct btrfs_ioctl_ino_lookup_args args = {
1101 		.treeid = 5,
1102 		.objectid = 256,
1103 	};
1104 
1105 	ioctl(-1, BTRFS_IOC_INO_LOOKUP, NULL);
1106 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1107 	       ioc(BTRFS_IOC_INO_LOOKUP));
1108 
1109 	printf("ioctl(-1, %s, {treeid=", ioc(BTRFS_IOC_INO_LOOKUP));
1110 	btrfs_print_objectid(args.treeid);
1111 	printf(", objectid=");
1112 	btrfs_print_objectid(args.objectid);
1113 	ioctl(-1, BTRFS_IOC_INO_LOOKUP, &args);
1114 	printf("}) = -1 EBADF (%m)\n");
1115 
1116 	if (btrfs_test_root) {
1117 		printf("ioctl(%d, %s, {treeid=",
1118 		       btrfs_test_dir_fd, ioc(BTRFS_IOC_INO_LOOKUP));
1119 		btrfs_print_objectid(args.treeid);
1120 		printf(", objectid=");
1121 		btrfs_print_objectid(args.objectid);
1122 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_INO_LOOKUP, &args);
1123 		printf("} => {name=\"%s\"}) = 0\n", args.name);
1124 	}
1125 }
1126 
1127 /*
1128  * Consumes argument, returns argument:
1129  * - BTRFS_IOC_SPACE_INFO
1130  */
1131 static void
btrfs_test_space_info_ioctl(void)1132 btrfs_test_space_info_ioctl(void)
1133 {
1134 	struct btrfs_ioctl_space_args args = {};
1135 
1136 	ioctl(-1, BTRFS_IOC_SPACE_INFO, NULL);
1137 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1138 	       ioc(BTRFS_IOC_SPACE_INFO));
1139 
1140 	ioctl(-1, BTRFS_IOC_SPACE_INFO, &args);
1141 	printf("ioctl(-1, %s, {space_slots=%" PRI__u64 "}) = -1 EBADF (%m)\n",
1142 	       ioc(BTRFS_IOC_SPACE_INFO), args.space_slots);
1143 
1144 	if (btrfs_test_root) {
1145 		struct btrfs_ioctl_space_args args_passed;
1146 		struct btrfs_ioctl_space_args *argsp;
1147 		args_passed = args;
1148 		printf("ioctl(%d, %s, {space_slots=%" PRI__u64 "}",
1149 		       btrfs_test_dir_fd, ioc(BTRFS_IOC_SPACE_INFO),
1150 		       args_passed.space_slots);
1151 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_SPACE_INFO, &args_passed);
1152 		printf(" => {total_spaces=%" PRI__u64 "}) = 0\n",
1153 			args_passed.total_spaces);
1154 
1155 		argsp = malloc(sizeof(args) +
1156 			args_passed.total_spaces * sizeof(args.spaces[0]));
1157 		if (!argsp)
1158 			perror_msg_and_fail("malloc failed");
1159 
1160 		*argsp = args;
1161 		argsp->space_slots = args_passed.total_spaces;
1162 		printf("ioctl(%d, %s, {space_slots=%" PRI__u64 "}",
1163 		       btrfs_test_dir_fd, ioc(BTRFS_IOC_SPACE_INFO),
1164 		       argsp->space_slots);
1165 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_SPACE_INFO, argsp);
1166 		printf(" => {total_spaces=%" PRI__u64 ", ",
1167 			argsp->total_spaces);
1168 		if (verbose) {
1169 			unsigned int i;
1170 			printf("spaces=[");
1171 			for (i = 0; i < argsp->total_spaces; i++) {
1172 				struct btrfs_ioctl_space_info *info;
1173 				info = &argsp->spaces[i];
1174 				if (i)
1175 					printf(", ");
1176 				printf("{flags=");
1177 				prfl_btrfs(btrfs_space_info_flags, info->flags,
1178 					   "BTRFS_SPACE_INFO_???");
1179 				printf(", total_bytes=%" PRI__u64
1180 				       ", used_bytes=%" PRI__u64 "}",
1181 				       info->total_bytes, info->used_bytes);
1182 			}
1183 
1184 			printf("]");
1185 		} else
1186 			printf("...");
1187 		printf("}) = 0\n");
1188 		free(argsp);
1189 	}
1190 }
1191 
1192 /*
1193  * Consumes no arguments, returns nothing:
1194  * - BTRFS_IOC_SCRUB_CANCEL
1195  * Consumes argument, returns argument:
1196  - * BTRFS_IOC_SCRUB
1197  - * BTRFS_IOC_SCRUB_PROGRESS
1198  */
1199 static void
btrfs_test_scrub_ioctls(void)1200 btrfs_test_scrub_ioctls(void)
1201 {
1202 	struct btrfs_ioctl_scrub_args args = {
1203 		.devid = 1,
1204 		.start = 0,
1205 		.end = -1ULL,
1206 		.flags = max_flags_plus_one(0),
1207 	};
1208 
1209 	ioctl(-1, BTRFS_IOC_SCRUB, NULL);
1210 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_SCRUB));
1211 
1212 	ioctl(-1, BTRFS_IOC_SCRUB_CANCEL, NULL);
1213 	printf("ioctl(-1, %s) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_SCRUB_CANCEL));
1214 
1215 	printf("ioctl(-1, %s, {devid=makedev(%u, %u)",
1216 	       ioc(BTRFS_IOC_SCRUB), major(args.devid), minor(args.devid));
1217 	print_uint64(", start=", args.start);
1218 	print_uint64(", end=", args.end);
1219 	printf(", flags=");
1220 	prfl_btrfs(btrfs_scrub_flags, args.flags, "BTRFS_SCRUB_???");
1221 	ioctl(-1, BTRFS_IOC_SCRUB, &args);
1222 	printf("}) = -1 EBADF (%m)\n");
1223 
1224 	ioctl(-1, BTRFS_IOC_SCRUB_PROGRESS, NULL);
1225 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1226 	       ioc(BTRFS_IOC_SCRUB_PROGRESS));
1227 
1228 	ioctl(-1, BTRFS_IOC_SCRUB_PROGRESS, &args);
1229 	printf("ioctl(-1, %s, {devid=makedev(%u, %u)}) = -1 EBADF (%m)\n",
1230 	       ioc(BTRFS_IOC_SCRUB_PROGRESS),
1231 	       major(args.devid), minor(args.devid));
1232 }
1233 
1234 /*
1235  * Consumes argument, returns argument:
1236  * - BTRFS_IOC_DEV_INFO
1237  */
1238 static void
btrfs_test_dev_info_ioctl(void)1239 btrfs_test_dev_info_ioctl(void)
1240 {
1241 	struct btrfs_ioctl_dev_info_args args = {
1242 		.devid = 1,
1243 	};
1244 	memcpy(&args.uuid, uuid_reference, BTRFS_UUID_SIZE);
1245 
1246 	ioctl(-1, BTRFS_IOC_DEV_INFO, NULL);
1247 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1248 	       ioc(BTRFS_IOC_DEV_INFO));
1249 
1250 	ioctl(-1, BTRFS_IOC_DEV_INFO, &args);
1251 	printf("ioctl(-1, %s, "
1252 	       "{devid=makedev(%u, %u), uuid=%s}) = -1 EBADF (%m)\n",
1253 	       ioc(BTRFS_IOC_DEV_INFO), major(args.devid), minor(args.devid),
1254 	       uuid_reference_string);
1255 }
1256 
1257 /*
1258  * Consumes argument, returns argument:
1259  * - BTRFS_IOC_INO_PATHS
1260  * - BTRFS_IOC_LOGICAL_INO
1261  */
1262 static void
btrfs_test_ino_path_ioctls(void)1263 btrfs_test_ino_path_ioctls(void)
1264 {
1265 	char buf[16384];
1266 	struct btrfs_ioctl_ino_path_args args = {
1267 		.inum = 256,
1268 		.size = sizeof(buf),
1269 		.reserved = {
1270 			0xdeadc0defacefeebULL,
1271 			0xdeadc0defacefeecULL,
1272 			0xdeadc0defacefeedULL,
1273 		},
1274 		.fspath = 0,
1275 	};
1276 
1277 #ifdef HAVE_BTRFS_IOCTL_LOGICAL_INO_ARGS
1278 	args.flags =
1279 #else
1280 	args.reserved[3] =
1281 #endif
1282 			0xdeadc0defacefeeeULL;
1283 
1284 
1285 	ioctl(-1, BTRFS_IOC_INO_PATHS, NULL);
1286 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1287 	       ioc(BTRFS_IOC_INO_PATHS));
1288 
1289 	ioctl(-1, BTRFS_IOC_LOGICAL_INO, NULL);
1290 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1291 	       ioc(BTRFS_IOC_LOGICAL_INO));
1292 
1293 	ioctl(-1, BTRFS_IOC_INO_PATHS, &args);
1294 	printf("ioctl(-1, %s, {inum=%" PRI__u64 ", size=%" PRI__u64
1295 	       ", fspath=NULL}) = -1 EBADF (%m)\n",
1296 	       ioc(BTRFS_IOC_INO_PATHS), args.inum, args.size);
1297 
1298 	args.fspath = (uintptr_t) buf;
1299 	ioctl(-1, BTRFS_IOC_INO_PATHS, &args);
1300 	printf("ioctl(-1, %s, {inum=%" PRI__u64 ", size=%" PRI__u64
1301 	       ", fspath=0x%" PRI__x64 "}) = -1 EBADF (%m)\n",
1302 	       ioc(BTRFS_IOC_INO_PATHS), args.inum, args.size, args.fspath);
1303 
1304 	args.fspath = 0;
1305 	ioctl(-1, BTRFS_IOC_LOGICAL_INO, &args);
1306 	printf("ioctl(-1, %s, {logical=%" PRI__u64
1307 	       ", size=%" PRI__u64 ", reserved=[0xdeadc0defacefeeb"
1308 	       ", 0xdeadc0defacefeec, 0xdeadc0defacefeed]"
1309 	       ", flags=0xdeadc0defacefeee /* BTRFS_LOGICAL_INO_ARGS_??? */"
1310 	       ", inodes=NULL}) = -1 EBADF (%m)\n",
1311 	       ioc(BTRFS_IOC_LOGICAL_INO), args.inum, args.size);
1312 
1313 	args.fspath = (uintptr_t) buf;
1314 	args.reserved[0] = 0;
1315 	args.reserved[2] = 0;
1316 #ifdef HAVE_BTRFS_IOCTL_LOGICAL_INO_ARGS
1317 	args.flags =
1318 #else
1319 	args.reserved[3] =
1320 #endif
1321 			1;
1322 
1323 	ioctl(-1, BTRFS_IOC_LOGICAL_INO, &args);
1324 	printf("ioctl(-1, %s, {logical=%" PRI__u64
1325 	       ", size=%" PRI__u64 ", reserved=[0, 0xdeadc0defacefeec, 0]"
1326 	       ", flags=%sBTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET%s"
1327 	       ", inodes=0x%" PRI__x64 "}) = -1 EBADF (%m)\n",
1328 	       ioc(BTRFS_IOC_LOGICAL_INO), args.inum, args.size,
1329 	       verbose_xlat ? "0x1 /* " : "", verbose_xlat ? " */" : "",
1330 	       args.fspath);
1331 
1332 	args.reserved[1] = 0;
1333 #ifdef HAVE_BTRFS_IOCTL_LOGICAL_INO_ARGS
1334 	args.flags =
1335 #else
1336 	args.reserved[3] =
1337 #endif
1338 			0;
1339 
1340 	ioctl(-1, BTRFS_IOC_LOGICAL_INO, &args);
1341 	printf("ioctl(-1, %s, {logical=%" PRI__u64
1342 	       ", size=%" PRI__u64 ", flags=0, inodes=0x%" PRI__x64
1343 	       "}) = -1 EBADF (%m)\n",
1344 	       ioc(BTRFS_IOC_LOGICAL_INO), args.inum, args.size, args.fspath);
1345 
1346 #ifdef HAVE_LINUX_FIEMAP_H
1347 	if (btrfs_test_root) {
1348 		int size;
1349 		struct stat si;
1350 		int ret;
1351 		struct btrfs_data_container *data = (void *)buf;
1352 		struct fiemap *fiemap;
1353 		int fd;
1354 
1355 		ret = fstat(btrfs_test_dir_fd, &si);
1356 		if (ret)
1357 			perror_msg_and_fail("fstat failed");
1358 
1359 		args.inum = si.st_ino;
1360 		printf("ioctl(%d, %s, {inum=%" PRI__u64 ", size=%" PRI__u64
1361 		       ", fspath=0x%" PRI__x64 "}",
1362 		       btrfs_test_dir_fd, ioc(BTRFS_IOC_INO_PATHS),
1363 		       args.inum, args.size, args.fspath);
1364 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_INO_PATHS, &args);
1365 		printf(" => {fspath={bytes_left=%u, bytes_missing=%u, elem_cnt=%u, elem_missed=%u, ",
1366 			data->bytes_left, data->bytes_missing, data->elem_cnt,
1367 			data->elem_missed);
1368 		if (verbose) {
1369 			printf("val=[\"%s\"]", dir_name);
1370 		} else
1371 			printf("...");
1372 		printf("}}) = 0\n");
1373 
1374 		fd = openat(btrfs_test_dir_fd, "file1", O_RDWR|O_CREAT, 0600);
1375 		if (fd < 0)
1376 			perror_msg_and_fail("openat(file1) failed");
1377 
1378 		ret = fstat(fd, &si);
1379 		if (ret)
1380 			perror_msg_and_fail("fstat failed");
1381 
1382 		if (write(fd, buf, sizeof(buf)) < 0)
1383 			perror_msg_and_fail("write: fd");
1384 
1385 		/*
1386 		 * Force delalloc so we can actually
1387 		 * search for the extent.
1388 		 */
1389 		fsync(fd);
1390 		ioctl(fd, BTRFS_IOC_SYNC, NULL);
1391 		printf("ioctl(%d, %s) = 0\n", fd, ioc(BTRFS_IOC_SYNC));
1392 
1393 		size = sizeof(*fiemap) + 2 * sizeof(fiemap->fm_extents[0]);
1394 		fiemap = malloc(size);
1395 		if (!fiemap)
1396 			perror_msg_and_fail("malloc failed");
1397 		memset(fiemap, 0, size);
1398 
1399 		fiemap->fm_length = sizeof(buf);
1400 		fiemap->fm_extent_count = 2;
1401 
1402 		/* This is also a live test for FIEMAP */
1403 		printf("ioctl(%d, %s, {fm_start=%" PRI__u64
1404 		       ", fm_length=%" PRI__u64 ", fm_flags=",
1405 		       fd, ioc(FS_IOC_FIEMAP),
1406 		       fiemap->fm_start, fiemap->fm_length);
1407 		prfl_btrfs(fiemap_flags, fiemap->fm_flags, "FIEMAP_FLAG_???");
1408 		printf(", fm_extent_count=%u}", fiemap->fm_extent_count);
1409 		ioctl(fd, FS_IOC_FIEMAP, fiemap);
1410 		printf(" => {fm_flags=");
1411 		prfl_btrfs(fiemap_flags, fiemap->fm_flags, "FIEMAP_FLAG_???");
1412 		printf(", fm_mapped_extents=%u, ",
1413 			fiemap->fm_mapped_extents);
1414 		if (verbose) {
1415 			printf("fm_extents=[");
1416 			unsigned int i;
1417 			for (i = 0; i < fiemap->fm_mapped_extents; i++) {
1418 				struct fiemap_extent *fe;
1419 				fe = &fiemap->fm_extents[i];
1420 				if (i)
1421 					printf(", ");
1422 				printf("{fe_logical=%" PRI__u64
1423 				       ", fe_physical=%" PRI__u64
1424 				       ", fe_length=%" PRI__u64
1425 				       ", ",
1426 				       fe->fe_logical, fe->fe_physical,
1427 				       fe->fe_length);
1428 				prfl_btrfs(fiemap_extent_flags, fe->fe_flags,
1429 					   "FIEMAP_EXTENT_???");
1430 				printf("}");
1431 			}
1432 			printf("]");
1433 		} else
1434 			printf("...");
1435 		printf("}) = 0\n");
1436 
1437 		args.inum = fiemap->fm_extents[0].fe_physical;
1438 		printf("ioctl(%d, %s, {logical=%" PRI__u64
1439 		       ", size=%" PRI__u64 ", flags=0, inodes=0x%" PRI__x64 "}",
1440 		       fd, ioc(BTRFS_IOC_LOGICAL_INO),
1441 		       args.inum, args.size, args.fspath);
1442 		ioctl(fd, BTRFS_IOC_LOGICAL_INO, &args);
1443 		printf(" => {inodes={bytes_left=%u, bytes_missing=%u, elem_cnt=%u, elem_missed=%u, ",
1444 			data->bytes_left, data->bytes_missing, data->elem_cnt,
1445 			data->elem_missed);
1446 		if (verbose) {
1447 			printf("val=[{inum=%llu, offset=0, root=5}]",
1448 			       (unsigned long long) si.st_ino);
1449 		} else
1450 			printf("...");
1451 		printf("}}) = 0\n");
1452 		close(fd);
1453 		free(fiemap);
1454 	}
1455 #endif /* HAVE_LINUX_FIEMAP_H */
1456 }
1457 
1458 /*
1459  * Consumes argument, returns argument:
1460  * - BTRFS_IOC_SET_RECEIVED_SUBVOL
1461  */
1462 static void
btrfs_test_set_received_subvol_ioctl(void)1463 btrfs_test_set_received_subvol_ioctl(void)
1464 {
1465 	struct btrfs_ioctl_received_subvol_args args = {
1466 		.stransid = 0x12345,
1467 		.stime = {
1468 			.sec = 1463193386,
1469 			.nsec = 12345,
1470 		},
1471 	};
1472 	int saved_errno;
1473 
1474 	memcpy(&args.uuid, uuid_reference, BTRFS_UUID_SIZE);
1475 
1476 	ioctl(-1, BTRFS_IOC_SET_RECEIVED_SUBVOL, NULL);
1477 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1478 	       ioc(BTRFS_IOC_SET_RECEIVED_SUBVOL));
1479 
1480 	ioctl(-1, BTRFS_IOC_SET_RECEIVED_SUBVOL, &args);
1481 	saved_errno = errno;
1482 	printf("ioctl(-1, %s, {uuid=%s, stransid=%" PRI__u64
1483 	       ", stime={sec=%" PRI__u64 ", nsec=%u}",
1484 	       ioc(BTRFS_IOC_SET_RECEIVED_SUBVOL), uuid_reference_string,
1485 	       args.stransid, args.stime.sec, args.stime.nsec);
1486 	print_time_t_nsec(args.stime.sec, args.stime.nsec, true);
1487 	errno = saved_errno;
1488 	printf(", flags=0}) = -1 EBADF (%m)\n");
1489 }
1490 
1491 /*
1492  * Consumes argument, returns nothing (output is via send_fd)
1493  * - BTRFS_IOC_SEND
1494  */
1495 static void
btrfs_test_send_ioctl(void)1496 btrfs_test_send_ioctl(void)
1497 {
1498 	uint64_t u64_array[2] = { 256, 257 };
1499 	struct btrfs_ioctl_send_args args = {
1500 		.send_fd = 4,
1501 		.parent_root = 257,
1502 		.flags = max_flags_plus_one(2),
1503 	};
1504 
1505 	ioctl(-1, BTRFS_IOC_SEND, NULL);
1506 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_SEND));
1507 
1508 	printf("ioctl(-1, %s, {send_fd=%d, clone_sources_count=%" PRI__u64
1509 	       ", clone_sources=NULL",
1510 	       ioc(BTRFS_IOC_SEND),
1511 	       (int) args.send_fd, args.clone_sources_count);
1512 	printf(", parent_root=");
1513 	btrfs_print_objectid(args.parent_root);
1514 	printf(", flags=");
1515 	prfl_btrfs(btrfs_send_flags, args.flags, "BTRFS_SEND_FLAGS_???");
1516 	ioctl(-1, BTRFS_IOC_SEND, &args);
1517 	printf("}) = -1 EBADF (%m)\n");
1518 
1519 	args.clone_sources_count = 2;
1520 	args.clone_sources = (__u64 *) (void *) u64_array;
1521 
1522 	printf("ioctl(-1, %s, {send_fd=%d, clone_sources_count=%" PRI__u64
1523 	       ", clone_sources=",
1524 	       ioc(BTRFS_IOC_SEND),
1525 	       (int) args.send_fd, args.clone_sources_count);
1526 	if (verbose) {
1527 		printf("[");
1528 		btrfs_print_objectid(u64_array[0]);
1529 		printf(", ");
1530 		btrfs_print_objectid(u64_array[1]);
1531 		printf("]");
1532 	} else
1533 		printf("%p", args.clone_sources);
1534 	printf(", parent_root=");
1535 	btrfs_print_objectid(args.parent_root);
1536 	printf(", flags=");
1537 	prfl_btrfs(btrfs_send_flags, args.flags, "BTRFS_SEND_FLAGS_???");
1538 	ioctl(-1, BTRFS_IOC_SEND, &args);
1539 	printf("}) = -1 EBADF (%m)\n");
1540 }
1541 
1542 /*
1543  * Consumes argument, returns nothing:
1544  * - BTRFS_IOC_QUOTA_CTL
1545  */
1546 static void
btrfs_test_quota_ctl_ioctl(void)1547 btrfs_test_quota_ctl_ioctl(void)
1548 {
1549 	struct btrfs_ioctl_quota_ctl_args args = {
1550 		.cmd = 1,
1551 	};
1552 
1553 	ioctl(-1, BTRFS_IOC_QUOTA_CTL, NULL);
1554 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1555 	       ioc(BTRFS_IOC_QUOTA_CTL));
1556 
1557 	ioctl(-1, BTRFS_IOC_QUOTA_CTL, &args);
1558 	printf("ioctl(-1, %s, {cmd=%sBTRFS_QUOTA_CTL_ENABLE%s}) "
1559 	       "= -1 EBADF (%m)\n",
1560 	       ioc(BTRFS_IOC_QUOTA_CTL),
1561 	       verbose_xlat ? "0x1 /* " : "",
1562 	       verbose_xlat ? " */" : "");
1563 
1564 	args.cmd = 2;
1565 	ioctl(-1, BTRFS_IOC_QUOTA_CTL, &args);
1566 	printf("ioctl(-1, %s, {cmd=%sBTRFS_QUOTA_CTL_DISABLE%s}) "
1567 	       "= -1 EBADF (%m)\n",
1568 	       ioc(BTRFS_IOC_QUOTA_CTL),
1569 	       verbose_xlat ? "0x2 /* " : "",
1570 	       verbose_xlat ? " */" : "");
1571 
1572 	args.cmd = 3;
1573 	ioctl(-1, BTRFS_IOC_QUOTA_CTL, &args);
1574 	printf("ioctl(-1, %s, "
1575 	       "{cmd=%sBTRFS_QUOTA_CTL_RESCAN__NOTUSED%s}) = -1 EBADF (%m)\n",
1576 	       ioc(BTRFS_IOC_QUOTA_CTL),
1577 	       verbose_xlat ? "0x3 /* " : "",
1578 	       verbose_xlat ? " */" : "");
1579 
1580 	args.cmd = 4;
1581 	ioctl(-1, BTRFS_IOC_QUOTA_CTL, &args);
1582 	printf("ioctl(-1, %s, "
1583 	       "{cmd=0x4 /* BTRFS_QUOTA_CTL_??? */}) = -1 EBADF (%m)\n",
1584 	       ioc(BTRFS_IOC_QUOTA_CTL));
1585 }
1586 
1587 /*
1588  * Consumes argument, returns nothing:
1589  * - BTRFS_IOC_QGROUP_ASSIGN
1590  */
1591 static void
btrfs_test_qgroup_assign_ioctl(void)1592 btrfs_test_qgroup_assign_ioctl(void)
1593 {
1594 	struct btrfs_ioctl_qgroup_assign_args args = {
1595 		.assign = 1,
1596 		.src = 257,
1597 		.dst = 258,
1598 	};
1599 
1600 	ioctl(-1, BTRFS_IOC_QGROUP_ASSIGN, NULL);
1601 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1602 	       ioc(BTRFS_IOC_QGROUP_ASSIGN));
1603 
1604 	ioctl(-1, BTRFS_IOC_QGROUP_ASSIGN, &args);
1605 	printf("ioctl(-1, %s, "
1606 	       "{assign=%" PRI__u64 ", src=%" PRI__u64 ", dst=%" PRI__u64
1607 	       "}) = -1 EBADF (%m)\n",
1608 	       ioc(BTRFS_IOC_QGROUP_ASSIGN), args.assign, args.src, args.dst);
1609 }
1610 
1611 /*
1612  * Consumes argument, returns nothing:
1613  * - BTRFS_IOC_QGROUP_CREATE
1614   */
1615 static void
btrfs_test_qgroup_create_ioctl(void)1616 btrfs_test_qgroup_create_ioctl(void)
1617 {
1618 	struct btrfs_ioctl_qgroup_create_args args = {
1619 		.create = 1,
1620 		.qgroupid = 257,
1621 	};
1622 
1623 	ioctl(-1, BTRFS_IOC_QGROUP_CREATE, NULL);
1624 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_QGROUP_CREATE));
1625 
1626 	ioctl(-1, BTRFS_IOC_QGROUP_CREATE, &args);
1627 	printf("ioctl(-1, %s, "
1628 	       "{create=%" PRI__u64 ", qgroupid=%" PRI__u64
1629 	       "}) = -1 EBADF (%m)\n",
1630 	       ioc(BTRFS_IOC_QGROUP_CREATE), args.create, args.qgroupid);
1631 }
1632 
1633 /*
1634  * Consumes nothing, returns nothing:
1635  * - BTRFS_IOC_QUOTA_RESCAN_WAIT
1636  * Consumes argument, returns nothing:
1637  * - BTRFS_IOC_QUOTA_RESCAN
1638  */
1639 static void
btrfs_test_quota_rescan_ioctl(void)1640 btrfs_test_quota_rescan_ioctl(void)
1641 {
1642 	struct btrfs_ioctl_quota_rescan_args args = {
1643 		.progress = 1,
1644 	};
1645 
1646 	ioctl(-1, BTRFS_IOC_QUOTA_RESCAN, NULL);
1647 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1648 	       ioc(BTRFS_IOC_QUOTA_RESCAN));
1649 
1650 	ioctl(-1, BTRFS_IOC_QUOTA_RESCAN, &args);
1651 	printf("ioctl(-1, %s, {flags=0}) = -1 EBADF (%m)\n",
1652 	       ioc(BTRFS_IOC_QUOTA_RESCAN));
1653 	ioctl(-1, BTRFS_IOC_QUOTA_RESCAN_WAIT, NULL);
1654 	printf("ioctl(-1, %s) = -1 EBADF (%m)\n",
1655 	       ioc(BTRFS_IOC_QUOTA_RESCAN_WAIT));
1656 
1657 }
1658 
1659 /*
1660  * Consumes argument, returns nothing:
1661  * - FS_IOC_SETFSLABEL
1662  *
1663  * Consumes no argument, returns argument:
1664  * - FS_IOC_GETFSLABEL
1665  */
1666 static void
btrfs_test_label_ioctls(void)1667 btrfs_test_label_ioctls(void)
1668 {
1669 	char label[BTRFS_LABEL_SIZE] = "btrfs-label";
1670 
1671 	ioctl(-1, FS_IOC_SETFSLABEL, NULL);
1672 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1673 	       ioc(FS_IOC_SETFSLABEL));
1674 
1675 	ioctl(-1, FS_IOC_SETFSLABEL, label);
1676 	printf("ioctl(-1, %s, \"%s\") = -1 EBADF (%m)\n",
1677 	       ioc(FS_IOC_SETFSLABEL), label);
1678 
1679 	if (write_ok) {
1680 		ioctl(btrfs_test_dir_fd, FS_IOC_SETFSLABEL, label);
1681 		printf("ioctl(%d, %s, \"%s\") = 0\n",
1682 			btrfs_test_dir_fd, ioc(FS_IOC_SETFSLABEL), label);
1683 
1684 		ioctl(btrfs_test_dir_fd, FS_IOC_GETFSLABEL, label);
1685 		printf("ioctl(%d, %s, \"%s\") = 0\n",
1686 			btrfs_test_dir_fd, ioc(FS_IOC_GETFSLABEL), label);
1687 	}
1688 }
1689 
1690 /*
1691  * Consumes argument, returns argument:
1692  * - BTRFS_IOC_GET_DEV_STATS
1693  */
1694 static void
btrfs_test_get_dev_stats_ioctl(void)1695 btrfs_test_get_dev_stats_ioctl(void)
1696 {
1697 	struct btrfs_ioctl_get_dev_stats args = {
1698 		.devid = 1,
1699 		.nr_items = 5,
1700 		.flags = max_flags_plus_one(0),
1701 	};
1702 
1703 	ioctl(-1, BTRFS_IOC_GET_DEV_STATS, NULL);
1704 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_GET_DEV_STATS));
1705 
1706 	printf("ioctl(-1, %s, {devid=makedev(%u, %u)"
1707 	       ", nr_items=%" PRI__u64 ", flags=",
1708 	       ioc(BTRFS_IOC_GET_DEV_STATS),
1709 	       major(args.devid), minor(args.devid), args.nr_items);
1710 	prfl_btrfs(btrfs_dev_stats_flags, args.flags,
1711 		     "BTRFS_DEV_STATS_???");
1712 	ioctl(-1, BTRFS_IOC_GET_DEV_STATS, &args);
1713 	printf("}) = -1 EBADF (%m)\n");
1714 
1715 	if (write_ok) {
1716 		unsigned int i;
1717 		args.flags = BTRFS_DEV_STATS_RESET;
1718 		printf("ioctl(%d, %s, {devid=makedev(%u, %u)"
1719 			", nr_items=%" PRI__u64 ", flags=",
1720 			btrfs_test_dir_fd, ioc(BTRFS_IOC_GET_DEV_STATS),
1721 			major(args.devid), minor(args.devid), args.nr_items);
1722 		prfl_btrfs(btrfs_dev_stats_flags, args.flags,
1723 			     "BTRFS_DEV_STATS_???");
1724 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_GET_DEV_STATS, &args);
1725 		printf("} => {nr_items=%" PRI__u64 ", flags=",
1726 			args.nr_items);
1727 		prfl_btrfs(btrfs_dev_stats_flags, args.flags,
1728 			   "BTRFS_DEV_STATS_???");
1729 		printf(", [");
1730 		for (i = 0; i < args.nr_items; i++) {
1731 			const char *name = xlookup(btrfs_dev_stats_values, i);
1732 			if (i)
1733 				printf(", ");
1734 
1735 			if (name) {
1736 				if (verbose_xlat)
1737 					printf("[%u /* %s */] = ", i, name);
1738 				else
1739 					printf("[%s] = ", name);
1740 			} else {
1741 				printf("[%u] = ", i);
1742 			}
1743 
1744 			printf("%" PRI__u64, args.values[i]);
1745 		}
1746 		printf("]}) = 0\n");
1747 	}
1748 }
1749 
1750 /*
1751  * Consumes argument, returns argument:
1752  * - BTRFS_IOC_DEV_REPLACE
1753  *
1754  * Test environment for this is more difficult; It's better to do it by hand.
1755  */
1756 static void
btrfs_test_dev_replace_ioctl(void)1757 btrfs_test_dev_replace_ioctl(void)
1758 {
1759 	struct btrfs_ioctl_dev_replace_args args = {
1760 		.cmd = BTRFS_IOCTL_DEV_REPLACE_CMD_START,
1761 	};
1762 	args.start.srcdevid = 1;
1763 	strcpy((char *)args.start.srcdev_name, "/dev/sda1");
1764 	strcpy((char *)args.start.tgtdev_name, "/dev/sdb1");
1765 
1766 	/* struct btrfs_ioctl_dev_replace_args */
1767 	ioctl(-1, BTRFS_IOC_DEV_REPLACE, NULL);
1768 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", ioc(BTRFS_IOC_DEV_REPLACE));
1769 
1770 	for (unsigned long i = 0; i < 3; i++) {
1771 		int saved_errno;
1772 
1773 		args.start.cont_reading_from_srcdev_mode = i;
1774 		ioctl(-1, BTRFS_IOC_DEV_REPLACE, &args);
1775 		saved_errno = errno;
1776 		printf("ioctl(-1, %s, "
1777 		       "{cmd=%sBTRFS_IOCTL_DEV_REPLACE_CMD_START%s"
1778 		       ", start={srcdevid=makedev(%u, %u)"
1779 		       ", cont_reading_from_srcdev_mode=",
1780 		       ioc(BTRFS_IOC_DEV_REPLACE),
1781 		       verbose_xlat ? "0 /* " : "", verbose_xlat ? " */" : "",
1782 		       major(args.start.srcdevid), minor(args.start.srcdevid));
1783 		prxval_btrfs(btrfs_cont_reading_from_srcdev_mode,
1784 			     args.start.cont_reading_from_srcdev_mode,
1785 			     "BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV"
1786 			     "_MODE_???", i < 2);
1787 		errno = saved_errno;
1788 		printf(", srcdev_name=\"%s\", tgtdev_name=\"%s\"}}) "
1789 		       "= -1 EBADF (%m)\n",
1790 		       (char *)args.start.srcdev_name,
1791 		       (char *)args.start.tgtdev_name);
1792 	}
1793 
1794 	args.cmd = 1;
1795 	ioctl(-1, BTRFS_IOC_DEV_REPLACE, &args);
1796 	printf("ioctl(-1, %s, {cmd=%sBTRFS_IOCTL_DEV_REPLACE_CMD_STATUS%s}) "
1797 	       "= -1 EBADF (%m)\n",
1798 	       ioc(BTRFS_IOC_DEV_REPLACE),
1799 	       verbose_xlat ? "0x1 /* " : "", verbose_xlat ? " */" : "");
1800 }
1801 
1802 static void
btrfs_test_extent_same_ioctl(void)1803 btrfs_test_extent_same_ioctl(void)
1804 {
1805 #ifdef BTRFS_IOC_FILE_EXTENT_SAME
1806 	struct file_dedupe_range args = {
1807 		.src_offset = 1024,
1808 		.src_length = 10240,
1809 	};
1810 	struct file_dedupe_range *argsp;
1811 
1812 	ioctl(-1, BTRFS_IOC_FILE_EXTENT_SAME, NULL);
1813 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1814 	       sprint_xlat_(BTRFS_IOC_FILE_EXTENT_SAME,
1815 			    "BTRFS_IOC_FILE_EXTENT_SAME or FIDEDUPERANGE"));
1816 
1817 	printf("ioctl(-1, %s, "
1818 	       "{src_offset=%" PRIu64
1819 	       ", src_length=%" PRIu64
1820 	       ", dest_count=%hu, info=[]",
1821 	       sprint_xlat_(BTRFS_IOC_FILE_EXTENT_SAME,
1822 			    "BTRFS_IOC_FILE_EXTENT_SAME or FIDEDUPERANGE"),
1823 		(uint64_t)args.src_offset,
1824 		(uint64_t)args.src_length, args.dest_count);
1825 	ioctl(-1, BTRFS_IOC_FILE_EXTENT_SAME, &args);
1826 	printf("}) = -1 EBADF (%m)\n");
1827 
1828 	argsp = malloc(sizeof(*argsp) + sizeof(argsp->info[0]) * 3);
1829 	if (!argsp)
1830 		perror_msg_and_fail("malloc failed");
1831 	memset(argsp, 0, sizeof(*argsp) + sizeof(argsp->info[0]) * 3);
1832 
1833 	*argsp = args;
1834 	argsp->dest_count = 3;
1835 	argsp->info[0].dest_fd = 2;
1836 	argsp->info[0].dest_offset = 0;
1837 	argsp->info[1].dest_fd = 2;
1838 	argsp->info[1].dest_offset = 10240;
1839 	argsp->info[2].dest_fd = 2;
1840 	argsp->info[2].dest_offset = 20480;
1841 
1842 	printf("ioctl(-1, %s, "
1843 	       "{src_offset=%" PRIu64
1844 	       ", src_length=%" PRIu64
1845 	       ", dest_count=%hu, info=",
1846 	       sprint_xlat_(BTRFS_IOC_FILE_EXTENT_SAME,
1847 			    "BTRFS_IOC_FILE_EXTENT_SAME or FIDEDUPERANGE"),
1848 		(int64_t)argsp->src_offset,
1849 		(uint64_t)argsp->src_length, argsp->dest_count);
1850 		printf("[{dest_fd=%" PRId64 ", dest_offset=%" PRIu64
1851 		       "}, {dest_fd=%" PRId64 ", dest_offset=%"PRIu64 "}",
1852 		       (int64_t)argsp->info[0].dest_fd,
1853 		       (uint64_t)argsp->info[0].dest_offset,
1854 		       (int64_t)argsp->info[1].dest_fd,
1855 		       (uint64_t)argsp->info[1].dest_offset);
1856 	if (verbose)
1857 		printf(", {dest_fd=%" PRId64 ", dest_offset=%" PRIu64 "}",
1858 		       (int64_t)argsp->info[2].dest_fd,
1859 		       (uint64_t)argsp->info[2].dest_offset);
1860 	else
1861 		printf(", ...");
1862 	printf("]");
1863 	ioctl(-1, BTRFS_IOC_FILE_EXTENT_SAME, argsp);
1864 	printf("}) = -1 EBADF (%m)\n");
1865 
1866 	if (write_ok) {
1867 		int fd1, fd2;
1868 		char buf[16384];
1869 
1870 		memset(buf, 0, sizeof(buf));
1871 
1872 		fd1 = openat(btrfs_test_dir_fd, "file1", O_RDWR|O_CREAT, 0600);
1873 		if (fd1 < 0)
1874 			perror_msg_and_fail("open file1 failed");
1875 
1876 		fd2 = openat(btrfs_test_dir_fd, "file2", O_RDWR|O_CREAT, 0600);
1877 		if (fd2 < 0)
1878 			perror_msg_and_fail("open file2 failed");
1879 
1880 		if (write(fd1, buf, sizeof(buf)) < 0)
1881 			perror_msg_and_fail("write: fd1");
1882 		if (write(fd1, buf, sizeof(buf)) < 0)
1883 			perror_msg_and_fail("write: fd1");
1884 		if (write(fd2, buf, sizeof(buf)) < 0)
1885 			perror_msg_and_fail("write: fd2");
1886 		if (write(fd2, buf, sizeof(buf)) < 0)
1887 			perror_msg_and_fail("write: fd2");
1888 
1889 		close(fd2);
1890 		fd2 = openat(btrfs_test_dir_fd, "file2", O_RDONLY);
1891 		if (fd2 < 0)
1892 			perror_msg_and_fail("open file2 failed");
1893 
1894 		memset(argsp, 0, sizeof(*argsp) + sizeof(argsp->info[0]) * 3);
1895 
1896 		argsp->src_offset = 0;
1897 		argsp->src_length = 4096;
1898 		argsp->dest_count = 3;
1899 		argsp->info[0].dest_fd = fd2;
1900 		argsp->info[0].dest_offset = 0;
1901 		argsp->info[1].dest_fd = fd2;
1902 		argsp->info[1].dest_offset = 10240;
1903 		argsp->info[2].dest_fd = fd2;
1904 		argsp->info[2].dest_offset = 20480;
1905 
1906 		printf("ioctl(%d, %s, "
1907 		       "{src_offset=%" PRIu64 ", src_length=%" PRIu64
1908 		       ", dest_count=%hu, info=", fd1,
1909 		       sprint_xlat_(BTRFS_IOC_FILE_EXTENT_SAME,
1910 				    "BTRFS_IOC_FILE_EXTENT_SAME"
1911 				    " or FIDEDUPERANGE"),
1912 		       (uint64_t)argsp->src_offset,
1913 		       (uint64_t)argsp->src_length, argsp->dest_count);
1914 		printf("[{dest_fd=%" PRId64 ", dest_offset=%" PRIu64
1915 		       "}, {dest_fd=%" PRId64 ", dest_offset=%"PRIu64 "}",
1916 		       (int64_t)argsp->info[0].dest_fd,
1917 		       (uint64_t)argsp->info[0].dest_offset,
1918 		       (int64_t)argsp->info[1].dest_fd,
1919 		       (uint64_t)argsp->info[1].dest_offset);
1920 		if (verbose)
1921 			printf(", {dest_fd=%" PRId64
1922 			       ", dest_offset=%" PRIu64 "}",
1923 			       (int64_t)argsp->info[2].dest_fd,
1924 			       (uint64_t)argsp->info[2].dest_offset);
1925 		else
1926 			printf(", ...");
1927 
1928 		ioctl(fd1, BTRFS_IOC_FILE_EXTENT_SAME, argsp);
1929 		printf("]} => {info=");
1930 		printf("[{bytes_deduped=%" PRIu64 ", status=%d}, "
1931 			"{bytes_deduped=%" PRIu64 ", status=%d}",
1932 		       (uint64_t)argsp->info[0].bytes_deduped,
1933 		       argsp->info[0].status,
1934 		       (uint64_t)argsp->info[1].bytes_deduped,
1935 		       argsp->info[1].status);
1936 		if (verbose)
1937 			printf(", {bytes_deduped=%" PRIu64 ", status=%d}",
1938 			       (uint64_t)argsp->info[2].bytes_deduped,
1939 			       argsp->info[2].status);
1940 		else
1941 			printf(", ...");
1942 		printf("]}) = 0\n");
1943 		close(fd1);
1944 		close(fd2);
1945 		unlinkat(btrfs_test_dir_fd, "file1", 0);
1946 		unlinkat(btrfs_test_dir_fd, "file2", 0);
1947 		close(fd1);
1948 		close(fd2);
1949 	}
1950 	free(argsp);
1951 #endif /* BTRFS_IOC_FILE_EXTENT_SAME */
1952 }
1953 
1954 static void
btrfs_print_features(struct btrfs_ioctl_feature_flags * flags)1955 btrfs_print_features(struct btrfs_ioctl_feature_flags *flags)
1956 {
1957 	printf("{compat_flags=");
1958 	printflags(btrfs_features_compat, flags->compat_flags,
1959 		   "BTRFS_FEATURE_COMPAT_???");
1960 
1961 	printf(", compat_ro_flags=");
1962 	prfl_btrfs(btrfs_features_compat_ro, flags->compat_ro_flags,
1963 		   "BTRFS_FEATURE_COMPAT_RO_???");
1964 
1965 	printf(", incompat_flags=");
1966 	prfl_btrfs(btrfs_features_incompat, flags->incompat_flags,
1967 		   "BTRFS_FEATURE_INCOMPAT_???");
1968 	printf("}");
1969 }
1970 
1971 /*
1972  * Consumes argument, returns nothing:
1973  * - BTRFS_IOC_SET_FEATURES
1974  *
1975  * Consumes nothing, returns argument:
1976  * - BTRFS_IOC_GET_FEATURES
1977  * - BTRFS_IOC_GET_SUPPORTED_FEATURES
1978  */
1979 static void
btrfs_test_features_ioctls(void)1980 btrfs_test_features_ioctls(void)
1981 {
1982 	struct btrfs_ioctl_feature_flags args[2] = {
1983 		{
1984 			.compat_flags = max_flags_plus_one(-1),
1985 			.incompat_flags = max_flags_plus_one(9),
1986 			.compat_ro_flags = max_flags_plus_one(0),
1987 		}, {
1988 			.compat_flags = max_flags_plus_one(-1),
1989 			.incompat_flags = max_flags_plus_one(9),
1990 			.compat_ro_flags = max_flags_plus_one(0),
1991 		},
1992 	};
1993 	struct btrfs_ioctl_feature_flags supported_features[3];
1994 
1995 	ioctl(-1, BTRFS_IOC_SET_FEATURES, NULL);
1996 	printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
1997 	       ioc(BTRFS_IOC_SET_FEATURES));
1998 
1999 	printf("ioctl(-1, %s, [", ioc(BTRFS_IOC_SET_FEATURES));
2000 	btrfs_print_features(&args[0]);
2001 	printf(", ");
2002 	btrfs_print_features(&args[1]);
2003 	ioctl(-1, BTRFS_IOC_SET_FEATURES, &args);
2004 	printf("]) = -1 EBADF (%m)\n");
2005 
2006 	if (btrfs_test_root) {
2007 		printf("ioctl(%d, %s, ",
2008 		       btrfs_test_dir_fd, ioc(BTRFS_IOC_GET_FEATURES));
2009 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_GET_FEATURES,
2010 		      &supported_features);
2011 		btrfs_print_features(&supported_features[0]);
2012 		printf(") = 0\n");
2013 
2014 		ioctl(btrfs_test_dir_fd, BTRFS_IOC_GET_SUPPORTED_FEATURES,
2015 		      &supported_features);
2016 		printf("ioctl(%d, %s, ",
2017 		       btrfs_test_dir_fd,
2018 		       ioc(BTRFS_IOC_GET_SUPPORTED_FEATURES));
2019 		printf("[");
2020 		btrfs_print_features(&supported_features[0]);
2021 		printf(" /* supported */, ");
2022 		btrfs_print_features(&supported_features[1]);
2023 		printf(" /* safe to set */, ");
2024 		btrfs_print_features(&supported_features[2]);
2025 		printf(" /* safe to clear */]) = 0\n");
2026 	}
2027 }
2028 
2029 static void
btrfs_test_read_ioctls(void)2030 btrfs_test_read_ioctls(void)
2031 {
2032 	static const struct xlat btrfs_read_cmd[] = {
2033 		XLAT(BTRFS_IOC_BALANCE_PROGRESS),
2034 		XLAT(BTRFS_IOC_FS_INFO),
2035 		XLAT(BTRFS_IOC_GET_FEATURES),
2036 		XLAT(FS_IOC_GETFSLABEL),
2037 		XLAT(BTRFS_IOC_GET_SUPPORTED_FEATURES),
2038 		XLAT(BTRFS_IOC_QGROUP_LIMIT),
2039 		XLAT(BTRFS_IOC_QUOTA_RESCAN_STATUS),
2040 		XLAT(BTRFS_IOC_START_SYNC),
2041 		XLAT(BTRFS_IOC_SUBVOL_GETFLAGS),
2042 	};
2043 
2044 	unsigned int i;
2045 	for (i = 0; i < ARRAY_SIZE(btrfs_read_cmd); ++i) {
2046 		ioctl(-1, (unsigned long) btrfs_read_cmd[i].val, 0);
2047 		printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n",
2048 		       sprint_xlat_(btrfs_read_cmd[i].val,
2049 				    btrfs_read_cmd[i].str));
2050 	}
2051 }
2052 
2053 static void
rm_test_dir(void)2054 rm_test_dir(void)
2055 {
2056 	int rootfd = open(path, O_RDONLY|O_DIRECTORY);
2057 
2058 	unlinkat(rootfd, dir_name, AT_REMOVEDIR);
2059 }
2060 
2061 int
main(int argc,char * argv[])2062 main(int argc, char *argv[])
2063 {
2064 
2065 	int opt;
2066 	int ret;
2067 
2068 	while ((opt = getopt(argc, argv, "wvX")) != -1) {
2069 		switch (opt) {
2070 		case 'v':
2071 			/*
2072 			 * These tests are incomplete, especially when
2073 			 * printing arrays of objects are involved.
2074 			 */
2075 			verbose = true;
2076 			break;
2077 		case 'w':
2078 			write_ok = true;
2079 			break;
2080 		case 'X':
2081 			verbose_xlat = true;
2082 			break;
2083 		default:
2084 			error_msg_and_fail("usage: btrfs [-vwX] [path]");
2085 		}
2086 	}
2087 
2088 	ret = snprintf(dir_name, sizeof(dir_name), dir_name_fmt, getpid());
2089 	if (ret < 0)
2090 		perror_msg_and_fail("snprintf(dir_name)");
2091 
2092 	/*
2093 	 * This will enable optional tests that require a valid file descriptor
2094 	 */
2095 	if (optind < argc) {
2096 		int rootfd;
2097 		struct statfs sfi;
2098 		path = argv[optind];
2099 
2100 		ret = statfs(path, &sfi);
2101 		if (ret)
2102 			perror_msg_and_fail("statfs(%s) failed", path);
2103 
2104 		if ((unsigned) sfi.f_type != BTRFS_SUPER_MAGIC)
2105 			error_msg_and_fail("%s is not a btrfs file system",
2106 					   path);
2107 
2108 		btrfs_test_root = path;
2109 		rootfd = open(path, O_RDONLY|O_DIRECTORY);
2110 		if (rootfd < 0)
2111 			perror_msg_and_fail("open(%s) failed", path);
2112 
2113 		ret = mkdirat(rootfd, dir_name, 0755);
2114 		if (ret < 0 && errno != EEXIST)
2115 			perror_msg_and_fail("mkdirat(%s) failed", dir_name);
2116 
2117 		/* Register removal of the created directory.  */
2118 		if (ret == 0)
2119 			atexit(rm_test_dir);
2120 
2121 		btrfs_test_dir_fd = openat(rootfd, dir_name,
2122 					   O_RDONLY|O_DIRECTORY);
2123 		if (btrfs_test_dir_fd < 0)
2124 			perror_msg_and_fail("openat(%s) failed", dir_name);
2125 		close(rootfd);
2126 	} else
2127 		write_ok = false;
2128 
2129 	if (btrfs_test_root) {
2130 		fprintf(stderr, "Testing live ioctls on %s (%s)\n",
2131 			btrfs_test_root, write_ok ? "read/write" : "read only");
2132 	}
2133 
2134 	btrfs_test_read_ioctls();
2135 	btrfs_test_trans_ioctls();
2136 	btrfs_test_sync_ioctls();
2137 	btrfs_test_subvol_ioctls();
2138 	btrfs_test_balance_ioctls();
2139 	btrfs_test_device_ioctls();
2140 	btrfs_test_clone_ioctls();
2141 	btrfs_test_defrag_ioctls();
2142 	btrfs_test_search_ioctls();
2143 	btrfs_test_ino_lookup_ioctl();
2144 	btrfs_test_space_info_ioctl();
2145 	btrfs_test_scrub_ioctls();
2146 	btrfs_test_dev_info_ioctl();
2147 	btrfs_test_ino_path_ioctls();
2148 	btrfs_test_set_received_subvol_ioctl();
2149 	btrfs_test_send_ioctl();
2150 	btrfs_test_quota_ctl_ioctl();
2151 	btrfs_test_qgroup_assign_ioctl();
2152 	btrfs_test_qgroup_create_ioctl();
2153 	btrfs_test_quota_rescan_ioctl();
2154 	btrfs_test_label_ioctls();
2155 	btrfs_test_get_dev_stats_ioctl();
2156 	btrfs_test_dev_replace_ioctl();
2157 	btrfs_test_extent_same_ioctl();
2158 	btrfs_test_features_ioctls();
2159 
2160 	puts("+++ exited with 0 +++");
2161 
2162 	return 0;
2163 }
2164 
2165 #else
2166 
2167 SKIP_MAIN_UNDEFINED("HAVE_LINUX_BTRFS_H")
2168 
2169 #endif
2170