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