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