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