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