blob: bc7c54717c71cb57b04325c3c89e2d9a82fd13d6 [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{
Dmitry V. Levin57888fa2016-05-24 02:07:47 +0000183 uint64_t u64val = 0xdeadbeefbadc0ded;
Jeff Mahoney35866792016-05-18 18:09:42 -0400184
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{
Dmitry V. Levin6ce6d3b2016-05-24 01:53:02 +0000238 printf("{fd=%d, flags=", (int) args->fd);
Jeff Mahoney35866792016-05-18 18:09:42 -0400239 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;
Dmitry V. Levin57888fa2016-05-24 02:07:47 +0000270 void *bad_pointer = (void *) (unsigned long) 0xdeadbeeffffffeed;
271 uint64_t u64val = 0xdeadbeefbadc0ded;
Jeff Mahoney35866792016-05-18 18:09:42 -0400272 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, "
Dmitry V. Levin6ce6d3b2016-05-24 01:53:02 +0000446 "{fd=%d, name=\"%.*s\"}) = 0\n",
447 btrfs_test_dir_fd, (int) vol_args.fd, 255, long_subvol_name);
Jeff Mahoney35866792016-05-18 18:09:42 -0400448
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, "
Dmitry V. Levin6ce6d3b2016-05-24 01:53:02 +0000452 "{fd=%d, name=\"%s\"}) = 0\n",
453 btrfs_test_dir_fd, (int) vol_args.fd, subvol_name);
Jeff Mahoney35866792016-05-18 18:09:42 -0400454
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, "
Dmitry V. Levin6ce6d3b2016-05-24 01:53:02 +0000605 "{fd=%d, name=\"%s\"}) = -1 EBADF (%m)\n",
606 (int) args.fd, args.name);
Jeff Mahoney35866792016-05-18 18:09:42 -0400607
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, "
Dmitry V. Levin6ce6d3b2016-05-24 01:53:02 +0000614 "{fd=%d, name=\"%s\"}) = -1 EBADF (%m)\n",
615 (int) args.fd, args.name);
Jeff Mahoney35866792016-05-18 18:09:42 -0400616
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, "
Dmitry V. Levin6ce6d3b2016-05-24 01:53:02 +0000622 "{fd=%d, name=\"%s\"}) = -1 EBADF (%m)\n",
623 (int) args.fd, args.name);
Jeff Mahoney35866792016-05-18 18:09:42 -0400624
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, "
Dmitry V. Levin6ce6d3b2016-05-24 01:53:02 +0000630 "{fd=%d, name=\"%s\"}) = -1 EBADF (%m)\n",
631 (int) args.fd, args.name);
Jeff Mahoney35866792016-05-18 18:09:42 -0400632
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, "
Dmitry V. Levin6ce6d3b2016-05-24 01:53:02 +0000661 "{src_fd=%d, src_offset=%llu, src_length=%llu, dest_offset=%llu}) = -1 EBADF (%m)\n",
662 (int) args.src_fd, args.src_offset, args.src_length,
Jeff Mahoney35866792016-05-18 18:09:42 -0400663 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, "
Dmitry V. Levin6ce6d3b2016-05-24 01:53:02 +00001317 "{send_fd=%d, clone_sources_count=%" PRI__u64
1318 ", clone_sources=",
1319 (int) args.send_fd, args.clone_sources_count);
Jeff Mahoney35866792016-05-18 18:09:42 -04001320 if (verbose)
1321 printf("NULL");
1322 else
1323 printf("...");
1324 printf(", parent_root=");
1325 btrfs_print_objectid(args.parent_root);
1326 printf(", flags=");
1327 printflags(btrfs_send_flags, args.flags, "BTRFS_SEND_FLAGS_???");
1328 ioctl(-1, BTRFS_IOC_SEND, &args);
1329 printf("}) = -1 EBADF (%m)\n");
1330
1331 args.clone_sources_count = 2;
1332 args.clone_sources = (__u64 *)u64_array;
1333
1334 printf("ioctl(-1, BTRFS_IOC_SEND, "
Dmitry V. Levin6ce6d3b2016-05-24 01:53:02 +00001335 "{send_fd=%d, clone_sources_count=%" PRI__u64
1336 ", clone_sources=",
1337 (int) args.send_fd, args.clone_sources_count);
Jeff Mahoney35866792016-05-18 18:09:42 -04001338 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)
Dmitry V. Levin9298c662016-05-24 01:33:08 +00001804 error_msg_and_fail("%s is not a btrfs file system",
1805 path);
Jeff Mahoney35866792016-05-18 18:09:42 -04001806
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