btrfs.c revision d57cc26bf098d2a362a51fb26def39dec0bb4fd4
1/*
2 * Copyright (c) 2016 Jeff Mahoney <jeffm@suse.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 *    derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "defs.h"
29#include <linux/fs.h>
30#ifdef HAVE_LINUX_BTRFS_H
31/*
32 * Prior to Linux 3.12, the BTRFS_IOC_DEFAULT_SUBVOL used u64 in
33 * its definition, which isn't exported by the kernel.
34 */
35typedef __u64 u64;
36
37#include <linux/btrfs.h>
38
39#ifndef HAVE_STRUCT_BTRFS_IOCTL_FEATURE_FLAGS_COMPAT_FLAGS
40struct btrfs_ioctl_feature_flags {
41	uint64_t compat_flags;
42	uint64_t compat_ro_flags;
43	uint64_t incompat_flags;
44};
45#endif
46
47#ifndef HAVE_STRUCT_BTRFS_IOCTL_DEFRAG_RANGE_ARGS_START
48struct btrfs_ioctl_defrag_range_args {
49	uint64_t start;
50	uint64_t len;
51	uint64_t flags;
52	uint32_t extent_thresh;
53	uint32_t compress_type;
54	uint32_t unused[4];
55};
56#endif
57
58#ifndef BTRFS_LABEL_SIZE
59# define BTRFS_LABEL_SIZE 256
60#endif
61
62#ifndef BTRFS_FIRST_FREE_OBJECTID
63# define BTRFS_FIRST_FREE_OBJECTID 256ULL
64#endif
65
66#ifndef BTRFS_IOC_GET_FEATURES
67# define BTRFS_IOC_GET_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \
68					struct btrfs_ioctl_feature_flags)
69# define BTRFS_IOC_SET_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 57, \
70					struct btrfs_ioctl_feature_flags[2])
71# define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \
72					struct btrfs_ioctl_feature_flags[3])
73#endif
74
75#ifndef BTRFS_IOC_TREE_SEARCH_V2
76# define BTRFS_IOC_TREE_SEARCH_V2 _IOWR(BTRFS_IOCTL_MAGIC, 17, \
77					struct btrfs_ioctl_search_args_v2)
78struct btrfs_ioctl_search_args_v2 {
79	struct btrfs_ioctl_search_key key; /* in/out - search parameters */
80	uint64_t buf_size;		   /* in - size of buffer
81					    * out - on EOVERFLOW: needed size
82					    *       to store item */
83	uint64_t buf[0];		   /* out - found items */
84};
85#endif
86
87#include "xlat/btrfs_balance_args.h"
88#include "xlat/btrfs_balance_ctl_cmds.h"
89#include "xlat/btrfs_balance_flags.h"
90#include "xlat/btrfs_balance_state.h"
91#include "xlat/btrfs_compress_types.h"
92#include "xlat/btrfs_defrag_flags.h"
93#include "xlat/btrfs_dev_replace_cmds.h"
94#include "xlat/btrfs_dev_replace_results.h"
95#include "xlat/btrfs_dev_replace_state.h"
96#include "xlat/btrfs_dev_stats_flags.h"
97#include "xlat/btrfs_dev_stats_values.h"
98#include "xlat/btrfs_features_compat.h"
99#include "xlat/btrfs_features_compat_ro.h"
100#include "xlat/btrfs_features_incompat.h"
101#include "xlat/btrfs_key_types.h"
102#include "xlat/btrfs_qgroup_ctl_cmds.h"
103#include "xlat/btrfs_qgroup_inherit_flags.h"
104#include "xlat/btrfs_qgroup_limit_flags.h"
105#include "xlat/btrfs_qgroup_status_flags.h"
106#include "xlat/btrfs_scrub_flags.h"
107#include "xlat/btrfs_send_flags.h"
108#include "xlat/btrfs_snap_flags_v2.h"
109#include "xlat/btrfs_space_info_flags.h"
110#include "xlat/btrfs_tree_objectids.h"
111
112static inline char
113prnibble(char v)
114{
115	if (v >= 10)
116		return 'a' + (v - 10);
117	return '0' + v;
118}
119
120/* 8-4-4-4-12 = 36 characters */
121#define UUID_STRING_SIZE 36
122
123/* Formats uuid, returns 0 if it's all zeroes */
124static int
125btrfs_unparse_uuid(unsigned char *uuid, char *out)
126{
127	int i;
128	int ret = 0;
129	for (i = 0; i < BTRFS_UUID_SIZE; i++) {
130		if (i == 4 || i == 6 || i == 8 || i == 10)
131			*out++ = '-';
132		*out++ = prnibble(uuid[i] >> 4);
133		*out++ = prnibble(uuid[i] & 0xf);
134		if (uuid[i])
135			ret = 1;
136	}
137	*out = '\0';
138	return ret;
139}
140
141static void
142print_u64(const char *name, uint64_t value)
143{
144	tprintf(", %s=%" PRIu64, name, value);
145	if (value == UINT64_MAX)
146		tprints(" /* UINT64_MAX */");
147}
148
149#define print_member_u64(obj, name) print_u64(#name, obj->name)
150
151static void
152btrfs_print_balance_args(const char *name, const struct btrfs_balance_args *bba)
153{
154	tprintf(", %s={profiles=", name);
155	printflags64(btrfs_space_info_flags, bba->profiles,
156		     "BTRFS_BLOCK_GROUP_???");
157	print_member_u64(bba, usage);
158	print_member_u64(bba, devid);
159	print_member_u64(bba, pstart);
160	print_member_u64(bba, pend);
161	print_member_u64(bba, vstart);
162	print_member_u64(bba, vend);
163	print_member_u64(bba, target);
164	tprints(", flags=");
165	printflags64(btrfs_balance_args, bba->flags, "BTRFS_BALANCE_ARGS_???");
166	tprints("}");
167}
168
169static void
170btrfs_print_balance(struct tcb *tcp, const long arg, bool out)
171{
172	struct btrfs_ioctl_balance_args balance_args;
173
174	if (umove_or_printaddr(tcp, arg, &balance_args))
175		return;
176
177	tprints("{flags=");
178	printflags64(btrfs_balance_flags, balance_args.flags,
179		     "BTRFS_BALANCE_???");
180	if (out) {
181		tprints(", state=");
182		printflags64(btrfs_balance_state, balance_args.state,
183			     "BTRFS_BALANCE_STATE_???");
184	}
185
186	if (balance_args.flags & BTRFS_BALANCE_DATA)
187		btrfs_print_balance_args("data", &balance_args.data);
188	if (balance_args.flags & BTRFS_BALANCE_METADATA)
189		btrfs_print_balance_args("meta", &balance_args.meta);
190	if (balance_args.flags & BTRFS_BALANCE_SYSTEM)
191		btrfs_print_balance_args("sys", &balance_args.sys);
192	tprints("}");
193}
194
195static void
196btrfs_print_features(const struct btrfs_ioctl_feature_flags *flags)
197{
198	tprints("{compat_flags=");
199	printflags64(btrfs_features_compat, flags->compat_flags,
200		     "BTRFS_FEATURE_COMPAT_???");
201
202	tprints(", compat_ro_flags=");
203	printflags64(btrfs_features_compat_ro, flags->compat_ro_flags,
204		     "BTRFS_FEATURE_COMPAT_RO_???");
205
206	tprints(", incompat_flags=");
207	printflags64(btrfs_features_incompat, flags->incompat_flags,
208		     "BTRFS_FEATURE_INCOMPAT_???");
209	tprints("}");
210}
211
212static void
213btrfs_print_qgroup_limit(const struct btrfs_qgroup_limit *lim)
214{
215	tprints("{flags=");
216	printflags64(btrfs_qgroup_limit_flags, lim->flags,
217		     "BTRFS_QGROUP_LIMIT_???");
218	tprintf(", max_rfer=%" PRI__u64 ", max_excl=%" PRI__u64
219		", rsv_rfer=%" PRI__u64 ", rsv_excl=%" PRI__u64 "}",
220		lim->max_rfer, lim->max_excl,
221		lim->rsv_rfer, lim->rsv_excl);
222}
223
224static void
225btrfs_print_key_type(uint32_t type)
226{
227	const char *str = xlookup(btrfs_key_types, type);
228	tprintf("%u", type);
229	if (str)
230		tprintf(" /* %s */", str);
231}
232
233static void
234btrfs_print_objectid(uint64_t objectid)
235{
236	const char *str = xlookup(btrfs_tree_objectids, objectid);
237	tprintf("%" PRIu64, objectid);
238	if (str)
239		tprintf(" /* %s */", str);
240}
241
242static void
243btrfs_print_data_container_header(const struct btrfs_data_container *container)
244{
245	tprintf("{bytes_left=%u, bytes_missing=%u"
246		", elem_cnt=%u, elem_missed=%u, val=",
247		container->bytes_left, container->bytes_missing,
248		container->elem_cnt, container->elem_missed);
249}
250
251static void
252btrfs_print_data_container_footer(void)
253{
254	tprints("}");
255}
256
257static bool
258print_btrfs_data_container_logical_ino(struct tcb *tcp, void *elem_buf,
259				       size_t elem_size, void *data)
260{
261	const uint64_t *const record = elem_buf;
262
263	tprintf("{inum=%" PRIu64 ", offset=%" PRIu64 ", root=%" PRIu64 "}",
264		record[0], record[1], record[2]);
265
266	return true;
267}
268
269static void
270btrfs_print_logical_ino_container(struct tcb *tcp,
271				  const uint64_t inodes_addr)
272{
273	struct btrfs_data_container container;
274
275	if (umove_or_printaddr(tcp, inodes_addr, &container))
276		return;
277
278	btrfs_print_data_container_header(&container);
279
280	if (abbrev(tcp)) {
281		tprints("...");
282	} else {
283		const uint64_t val_addr =
284			inodes_addr + offsetof(typeof(container), val);
285		uint64_t record[3];
286		print_array(tcp, val_addr, container.elem_cnt,
287			    record, sizeof(record),
288			    umoven_or_printaddr,
289			    print_btrfs_data_container_logical_ino, 0);
290	}
291
292	btrfs_print_data_container_footer();
293}
294
295static bool
296print_btrfs_data_container_ino_path(struct tcb *tcp, void *elem_buf,
297				       size_t elem_size, void *data)
298{
299	const uint64_t *const offset = elem_buf;
300	const uint64_t *const val_addr = data;
301
302	printpath(tcp, *val_addr + *offset);
303
304	return true;
305}
306
307static void
308btrfs_print_ino_path_container(struct tcb *tcp,
309			       const uint64_t fspath_addr)
310{
311	struct btrfs_data_container container;
312
313	if (umove_or_printaddr(tcp, fspath_addr, &container))
314		return;
315
316	btrfs_print_data_container_header(&container);
317
318	if (abbrev(tcp)) {
319		tprints("...");
320	} else {
321		uint64_t val_addr =
322			fspath_addr + offsetof(typeof(container), val);
323		uint64_t offset;
324		print_array(tcp, val_addr, container.elem_cnt,
325			    &offset, sizeof(offset),
326			    umoven_or_printaddr,
327			    print_btrfs_data_container_ino_path, &val_addr);
328	}
329
330	btrfs_print_data_container_footer();
331}
332
333static bool
334print_uint64(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
335{
336	tprintf("%" PRIu64, * (uint64_t *) elem_buf);
337
338	return true;
339}
340
341static void
342btrfs_print_qgroup_inherit(struct tcb *tcp, const uint64_t qgi_addr)
343{
344	struct btrfs_qgroup_inherit inherit;
345
346	if (umove_or_printaddr(tcp, qgi_addr, &inherit))
347		return;
348
349	tprintf("{flags=");
350	printflags64(btrfs_qgroup_inherit_flags, inherit.flags,
351		     "BTRFS_QGROUP_INHERIT_???");
352	tprintf(", num_qgroups=%" PRI__u64 ", num_ref_copies=%" PRI__u64
353		", num_excl_copies=%" PRI__u64 ", lim=",
354		inherit.num_qgroups, inherit.num_ref_copies,
355		inherit.num_excl_copies);
356
357	btrfs_print_qgroup_limit(&inherit.lim);
358
359	tprints(", qgroups=");
360
361	if (abbrev(tcp)) {
362		tprints("...");
363	} else {
364		uint64_t record;
365		print_array(tcp, qgi_addr + offsetof(typeof(inherit), qgroups),
366			    inherit.num_qgroups, &record, sizeof(record),
367			    umoven_or_printaddr, print_uint64, 0);
368	}
369	tprints("}");
370}
371
372static void
373print_key_value_internal(struct tcb *tcp, const char *name, uint64_t value)
374{
375	if (value) {
376		tprintf(", %s=%" PRIu64, name, value);
377		if (value == UINT64_MAX)
378			tprints(" /* UINT64_MAX */");
379	}
380}
381#define print_key_value(tcp, key, name)					\
382	print_key_value_internal((tcp), #name, (key)->name)
383
384static bool
385print_btrfs_ioctl_search_header(struct tcb *tcp, void *elem_buf,
386				size_t elem_size, void *data)
387{
388	const struct btrfs_ioctl_search_header *sh = elem_buf;
389
390	tprintf("{transid=%" PRI__u64 ", objectid=", sh->transid);
391	btrfs_print_objectid(sh->objectid);
392	tprintf(", offset=%" PRI__u64 ", type=", sh->offset);
393	btrfs_print_key_type(sh->type);
394	tprintf(", len=%u}", sh->len);
395
396	return true;
397}
398
399static void
400btrfs_print_tree_search(struct tcb *tcp, struct btrfs_ioctl_search_key *key,
401			uint64_t buf_addr, uint64_t buf_size, bool print_size)
402{
403	if (entering(tcp)) {
404		tprintf("{key={tree_id=");
405		btrfs_print_objectid(key->tree_id);
406
407		if (key->min_objectid != BTRFS_FIRST_FREE_OBJECTID ||
408		    !abbrev(tcp)) {
409			tprints(", min_objectid=");
410			btrfs_print_objectid(key->min_objectid);
411		}
412
413		if (key->max_objectid != BTRFS_LAST_FREE_OBJECTID ||
414		    !abbrev(tcp)) {
415			tprints(", max_objectid=");
416			btrfs_print_objectid(key->max_objectid);
417		}
418
419		print_key_value(tcp, key, min_offset);
420		print_key_value(tcp, key, max_offset);
421		print_key_value(tcp, key, min_transid);
422		print_key_value(tcp, key, max_transid);
423
424		tprints(", min_type=");
425		btrfs_print_key_type(key->min_type);
426		tprints(", max_type=");
427		btrfs_print_key_type(key->max_type);
428		tprintf(", nr_items=%u}", key->nr_items);
429		if (print_size)
430			tprintf(", buf_size=%" PRIu64, buf_size);
431		tprints("}");
432	} else {
433		tprintf("{key={nr_items=%u}", key->nr_items);
434		if (print_size)
435			tprintf(", buf_size=%" PRIu64, buf_size);
436		tprints(", buf=");
437		if (abbrev(tcp))
438			tprints("...");
439		else {
440			struct btrfs_ioctl_search_header sh;
441
442			print_array(tcp, buf_addr, key->nr_items,
443				    &sh, sizeof(sh),
444				    umoven_or_printaddr,
445				    print_btrfs_ioctl_search_header, 0);
446		}
447		tprints("}");
448	}
449}
450
451static bool
452print_objectid_callback(struct tcb *tcp, void *elem_buf,
453			size_t elem_size, void *data)
454{
455	btrfs_print_objectid(* (uint64_t *) elem_buf);
456
457	return true;
458}
459
460static bool
461print_btrfs_ioctl_space_info(struct tcb *tcp, void *elem_buf,
462			     size_t elem_size, void *data)
463{
464	const struct btrfs_ioctl_space_info *info = elem_buf;
465
466	tprints("{flags=");
467	printflags64(btrfs_space_info_flags, info->flags,
468		     "BTRFS_SPACE_INFO_???");
469	tprintf(", total_bytes=%" PRI__u64 ", used_bytes=%" PRI__u64 "}",
470		info->total_bytes, info->used_bytes);
471
472	return true;
473}
474
475int
476btrfs_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
477{
478	switch (code) {
479	/* Take no arguments; command only. */
480	case BTRFS_IOC_TRANS_START:
481	case BTRFS_IOC_TRANS_END:
482	case BTRFS_IOC_SYNC:
483	case BTRFS_IOC_SCRUB_CANCEL:
484	case BTRFS_IOC_QUOTA_RESCAN_WAIT:
485	/*
486	 * The codes for these ioctls are based on each accepting a
487	 * vol_args but none of them actually consume an argument.
488	 */
489	case BTRFS_IOC_DEFRAG:
490	case BTRFS_IOC_BALANCE:
491		break;
492
493	/* takes a signed int */
494	case BTRFS_IOC_BALANCE_CTL:
495		tprints(", ");
496		printxval(btrfs_balance_ctl_cmds, arg, "BTRFS_BALANCE_CTL_???");
497		break;
498
499	/* returns a 64 */
500	case BTRFS_IOC_START_SYNC: /* R */
501		if (entering(tcp))
502			return 0;
503	/* fall through */
504	/* takes a u64 */
505	case BTRFS_IOC_DEFAULT_SUBVOL: /* W */
506	case BTRFS_IOC_WAIT_SYNC: /* W */
507		tprints(", ");
508		printnum_int64(tcp, arg, "%" PRIu64);
509		break;
510
511	/* u64 but describe a flags bitfield; we can make that symbolic */
512	case BTRFS_IOC_SUBVOL_GETFLAGS: { /* R */
513		uint64_t flags;
514
515		if (entering(tcp))
516			return 0;
517
518		tprints(", ");
519
520		if (umove_or_printaddr(tcp, arg, &flags))
521			break;
522
523		printflags64(btrfs_snap_flags_v2, flags, "BTRFS_SUBVOL_???");
524		break;
525	}
526
527	case BTRFS_IOC_SUBVOL_SETFLAGS: { /* W */
528		uint64_t flags;
529
530		tprints(", ");
531
532		if (umove_or_printaddr(tcp, arg, &flags))
533			break;
534
535		printflags64(btrfs_snap_flags_v2, flags, "BTRFS_SUBVOL_???");
536		break;
537	}
538
539	/* More complex types */
540	case BTRFS_IOC_BALANCE_V2: /* RW */
541		if (entering(tcp)) {
542			tprints(", ");
543			btrfs_print_balance(tcp, arg, false);
544			return 0;
545		}
546
547		if (syserror(tcp))
548			break;
549
550		tprints(" => ");
551		btrfs_print_balance(tcp, arg, true);
552		break;
553	case BTRFS_IOC_BALANCE_PROGRESS: /* R */
554		if (entering(tcp))
555			return 0;
556
557		tprints(", ");
558		btrfs_print_balance(tcp, arg, true);
559		break;
560
561	case BTRFS_IOC_DEFRAG_RANGE: { /* W */
562		struct btrfs_ioctl_defrag_range_args args;
563
564		tprints(", ");
565
566		if (umove_or_printaddr(tcp, arg, &args))
567			break;
568
569		tprintf("{start=%" PRIu64 ", len=", (uint64_t)args.start);
570
571		tprintf("%" PRIu64, args.len);
572		if (args.len == UINT64_MAX)
573			tprints(" /* UINT64_MAX */");
574
575		tprints(", flags=");
576		printflags64(btrfs_defrag_flags, args.flags,
577			     "BTRFS_DEFRAG_RANGE_???");
578		tprintf(", extent_thresh=%u, compress_type=",
579			args.extent_thresh);
580		printxval(btrfs_compress_types, args.compress_type,
581			  "BTRFS_COMPRESS_???");
582		tprints("}");
583		break;
584	}
585
586	case BTRFS_IOC_DEV_INFO: { /* RW */
587		struct btrfs_ioctl_dev_info_args args;
588		char uuid[UUID_STRING_SIZE+1];
589		int valid;
590
591		if (entering(tcp))
592			tprints(", ");
593		else if (syserror(tcp))
594			break;
595		else
596			tprints(" => ");
597		if (umove_or_printaddr(tcp, arg, &args))
598			break;
599		tprints("{");
600
601		valid = btrfs_unparse_uuid(args.uuid, uuid);
602		if (entering(tcp)) {
603			tprintf("devid=%" PRI__u64, args.devid);
604			if (valid)
605				tprintf(", uuid=%s", uuid);
606			tprints("}");
607			return 0;
608		}
609		if (valid)
610			tprintf("uuid=%s, ", uuid);
611		tprintf("bytes_used=%" PRI__u64
612			", total_bytes=%" PRI__u64 ", path=",
613			args.bytes_used, args.total_bytes);
614		print_quoted_string((const char *)args.path, sizeof(args.path),
615				    QUOTE_0_TERMINATED);
616		tprints("}");
617		break;
618	}
619
620	case BTRFS_IOC_DEV_REPLACE: { /* RW */
621		struct btrfs_ioctl_dev_replace_args args;
622
623		if (entering(tcp))
624			tprints(", ");
625		else if (syserror(tcp))
626			break;
627		else
628			tprints(" => ");
629
630		if (umove_or_printaddr(tcp, arg, &args))
631			break;
632
633		if (entering(tcp)) {
634			tprints("{cmd=");
635			printxval64(btrfs_dev_replace_cmds, args.cmd,
636				    "BTRFS_IOCTL_DEV_REPLACE_CMD_???");
637			if (args.cmd == BTRFS_IOCTL_DEV_REPLACE_CMD_START) {
638				const char *str;
639				tprintf(", start={srcdevid=%" PRI__u64
640				   ", cont_reading_from_srcdev_mode=%" PRI__u64
641				   ", srcdev_name=",
642				   args.start.srcdevid,
643				   args.start.cont_reading_from_srcdev_mode);
644
645				str = (const char*) args.start.srcdev_name;
646				print_quoted_string(str,
647						sizeof(args.start.srcdev_name),
648						QUOTE_0_TERMINATED);
649				tprints(", tgtdev_name=");
650				str = (const char*) args.start.tgtdev_name;
651				print_quoted_string(str,
652						sizeof(args.start.tgtdev_name),
653						QUOTE_0_TERMINATED);
654				tprints("}");
655
656			}
657			tprints("}");
658			return 0;
659		}
660
661		tprints("{result=");
662		printxval64(btrfs_dev_replace_results, args.result,
663			    "BTRFS_IOCTL_DEV_REPLACE_RESULT_???");
664		if (args.cmd == BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS) {
665			char buf[sizeof("HH:MM:SS") + 1];
666			time_t time;
667			tprints(", ");
668			printxval64(btrfs_dev_replace_state,
669				   args.status.replace_state,
670				   "BTRFS_IOCTL_DEV_REPLACE_STATE_???");
671			tprintf(", progress_1000=%" PRI__u64 " /* ",
672				args.status.progress_1000);
673			if (args.status.progress_1000 <= 1000)
674				tprintf("%" PRI__u64 ".%.2" PRI__u64 "%%",
675					args.status.progress_1000 / 10,
676					args.status.progress_1000 % 10);
677			else
678				tprints("???");
679			tprints(" */ ,");
680
681			time = args.status.time_started;
682			strftime(buf, sizeof(buf), "%T",
683				 localtime(&time));
684			tprintf("time_started=%" PRI__u64" /* %s */, ",
685				args.status.time_started, buf);
686
687			time = args.status.time_stopped;
688			strftime(buf, sizeof(buf), "%T",
689				 localtime(&time));
690			tprintf("time_stopped=%" PRI__u64" /* %s */, ",
691				args.status.time_stopped, buf);
692
693			tprintf("num_write_errors=%" PRI__u64
694				", num_uncorrectable_read_errors=%" PRI__u64,
695				args.status.num_write_errors,
696				args.status.num_uncorrectable_read_errors);
697		}
698		tprints("}");
699		break;
700	}
701
702	case BTRFS_IOC_GET_FEATURES: { /* R */
703		struct btrfs_ioctl_feature_flags flags;
704
705		if (entering(tcp))
706			return 0;
707
708		tprints(", ");
709		if (umove_or_printaddr(tcp, arg, &flags))
710			break;
711
712		btrfs_print_features(&flags);
713		break;
714	}
715
716	case BTRFS_IOC_SET_FEATURES: { /* W */
717		struct btrfs_ioctl_feature_flags flarg[2];
718
719		tprints(", ");
720
721		if (umove_or_printaddr(tcp, arg, &flarg))
722			break;
723
724		tprints("[");
725		btrfs_print_features(&flarg[0]);
726		tprints(", ");
727		btrfs_print_features(&flarg[1]);
728		tprints("]");
729		break;
730	}
731
732	case BTRFS_IOC_GET_SUPPORTED_FEATURES: { /* R */
733		struct btrfs_ioctl_feature_flags flarg[3];
734
735		if (entering(tcp))
736			return 0;
737
738		tprints(", ");
739		if (umove_or_printaddr(tcp, arg, &flarg))
740			break;
741
742		tprints("[ /* supported */ ");
743		btrfs_print_features(&flarg[0]);
744
745		tprints(", /* safe to set */ ");
746		btrfs_print_features(&flarg[1]);
747
748		tprints(", /* safe to clear */ ");
749		btrfs_print_features(&flarg[2]);
750		tprints("]");
751
752		break;
753	}
754
755	case BTRFS_IOC_FS_INFO: { /* R */
756		struct btrfs_ioctl_fs_info_args args;
757		char uuid[UUID_STRING_SIZE+1];
758		uint32_t nodesize, sectorsize, clone_alignment;
759#ifndef HAVE_STRUCT_BTRFS_IOCTL_FS_INFO_ARGS_NODESIZE
760		__u32 *reserved32;
761#endif
762
763		if (entering(tcp))
764			return 0;
765
766		tprints(", ");
767		if (umove_or_printaddr(tcp, arg, &args))
768			break;
769
770#ifdef HAVE_STRUCT_BTRFS_IOCTL_FS_INFO_ARGS_NODESIZE
771		nodesize = args.nodesize,
772		sectorsize = args.sectorsize,
773		clone_alignment = args.clone_alignment;
774#else
775		reserved32 = (__u32 *)args.reserved;
776		nodesize = reserved32[0];
777		sectorsize = reserved32[1];
778		clone_alignment = reserved32[2];
779#endif
780		btrfs_unparse_uuid(args.fsid, uuid);
781
782		tprints("{");
783		tprintf("max_id=%" PRI__u64 ", num_devices=%" PRI__u64
784			", fsid=%s, nodesize=%u, sectorsize=%u"
785			", clone_alignment=%u",
786			args.max_id, args.num_devices, uuid,
787			nodesize, sectorsize, clone_alignment);
788		tprints("}");
789		break;
790	}
791
792	case BTRFS_IOC_GET_DEV_STATS: { /* RW */
793		struct btrfs_ioctl_get_dev_stats args;
794		uint64_t i;
795
796		if (entering(tcp))
797			tprints(", ");
798		else if (syserror(tcp))
799			break;
800		else
801			tprints(" => ");
802		if (umove_or_printaddr(tcp, arg, &args))
803			break;
804
805		tprints("{");
806
807		if (entering(tcp))
808			tprintf("devid=%" PRI__u64 ", ", args.devid);
809
810		tprintf("nr_items=%" PRI__u64 ", flags=", args.nr_items);
811		printflags64(btrfs_dev_stats_flags, args.flags,
812			     "BTRFS_DEV_STATS_???");
813
814		if (entering(tcp)) {
815			tprints("}");
816			return 0;
817		}
818
819		/*
820		 * The structure has a 1k limit; Let's make sure we don't
821		 * go off into the middle of nowhere with a bad nr_items
822		 * value.
823		 */
824		tprints(", [");
825		for (i = 0; i < args.nr_items; i++) {
826			if (i)
827				tprints(", ");
828			if (i >= ARRAY_SIZE(args.values)) {
829				tprints("...");
830				break;
831			}
832			const char *name = xlookup(btrfs_dev_stats_values, i);
833			if (name)
834				tprintf("/* %s */ ", name);
835			tprintf("%" PRI__u64, args.values[i]);
836		}
837		tprints("]}");
838		break;
839	}
840
841	case BTRFS_IOC_INO_LOOKUP: { /* RW */
842		struct btrfs_ioctl_ino_lookup_args args;
843
844		if (entering(tcp))
845			tprints(", ");
846		else if (syserror(tcp))
847			break;
848		else
849			tprints(" => ");
850
851		if (umove_or_printaddr(tcp, arg, &args))
852			break;
853
854		if (entering(tcp)) {
855			/* Use subvolume id of the containing root */
856			if (args.treeid == 0)
857				/* abuse of auxstr to retain state */
858				tcp->auxstr = (void *)1;
859			else
860				tcp->auxstr = NULL;
861
862			tprints("{treeid=");
863			btrfs_print_objectid(args.treeid);
864			tprints(", objectid=");
865			btrfs_print_objectid(args.objectid);
866			tprints("}");
867			return 0;
868		}
869
870		tprints("{");
871		if (tcp->auxstr) {
872			tcp->auxstr = NULL;
873			tprints("treeid=");
874			btrfs_print_objectid(args.treeid);
875			tprints(", ");
876		}
877
878		tprints("name=");
879		print_quoted_string(args.name, sizeof(args.name),
880				    QUOTE_0_TERMINATED);
881		tprints("}");
882		break;
883	}
884
885	case BTRFS_IOC_INO_PATHS: { /* RW */
886		struct btrfs_ioctl_ino_path_args args;
887
888		if (entering(tcp))
889			tprints(", ");
890		else if (syserror(tcp))
891			break;
892		else
893			tprints(" => ");
894
895		if (umove_or_printaddr(tcp, arg, &args))
896			break;
897
898		tprints("{");
899
900		if (entering(tcp)) {
901			tprintf("inum=%" PRI__u64 ", size=%" PRI__u64,
902				args.inum, args.size);
903			tprintf(", fspath=0x%" PRI__x64 "}", args.fspath);
904			return 0;
905		}
906
907		tprints("fspath=");
908		btrfs_print_ino_path_container(tcp, args.fspath);
909
910		tprints("}");
911		break;
912	}
913
914	case BTRFS_IOC_LOGICAL_INO: { /* RW */
915		struct btrfs_ioctl_logical_ino_args args;
916
917		if (entering(tcp))
918			tprints(", ");
919		else if (syserror(tcp))
920			break;
921		else
922			tprints(" => ");
923
924		if (umove_or_printaddr(tcp, arg, &args))
925			break;
926
927		tprints("{");
928
929		if (entering(tcp)) {
930			tprintf("logical=%" PRI__u64 ", size=%" PRI__u64,
931				args.logical, args.size);
932			tprintf(", inodes=0x%" PRI__x64 "}", args.inodes);
933			return 0;
934		}
935
936		tprints("inodes=");
937		btrfs_print_logical_ino_container(tcp, args.inodes);
938
939		tprints("}");
940		break;
941	}
942
943	case BTRFS_IOC_QGROUP_ASSIGN: { /* W */
944		struct btrfs_ioctl_qgroup_assign_args args;
945
946		tprints(", ");
947		if (umove_or_printaddr(tcp, arg, &args))
948			break;
949
950		tprintf("{assign=%" PRI__u64 ", src=%" PRI__u64
951			", dst=%" PRI__u64 "}",
952			args.assign, args.src, args.dst);
953		break;
954	}
955
956	case BTRFS_IOC_QGROUP_CREATE: { /* W */
957		struct btrfs_ioctl_qgroup_create_args args;
958
959		tprints(", ");
960		if (umove_or_printaddr(tcp, arg, &args))
961			break;
962
963		tprintf("{create=%" PRI__u64 ", qgroupid=%" PRI__u64 "}",
964			args.create, args.qgroupid);
965		break;
966	}
967
968	case BTRFS_IOC_QGROUP_LIMIT: { /* R */
969		struct btrfs_ioctl_qgroup_limit_args args;
970
971		if (entering(tcp))
972			return 0;
973
974		tprints(", ");
975		if (umove_or_printaddr(tcp, arg, &args))
976			break;
977
978		tprintf("{qgroupid=%" PRI__u64 ", lim=", args.qgroupid);
979		btrfs_print_qgroup_limit(&args.lim);
980		tprints("}");
981		break;
982	}
983
984	case BTRFS_IOC_QUOTA_CTL: { /* W */
985		struct btrfs_ioctl_quota_ctl_args args;
986
987		tprints(", ");
988		if (umove_or_printaddr(tcp, arg, &args))
989			break;
990
991		printxval64(btrfs_qgroup_ctl_cmds, args.cmd,
992			    "BTRFS_QUOTA_CTL_???");
993		tprints("}");
994
995		break;
996	}
997
998	case BTRFS_IOC_QUOTA_RESCAN: { /* W */
999		struct btrfs_ioctl_quota_rescan_args args;
1000
1001		tprints(", ");
1002		if (umove_or_printaddr(tcp, arg, &args))
1003			break;
1004
1005		tprintf("{flags=%" PRI__u64 "}", args.flags);
1006		break;
1007	}
1008
1009	case BTRFS_IOC_QUOTA_RESCAN_STATUS: { /* R */
1010		struct btrfs_ioctl_quota_rescan_args args;
1011
1012		if (entering(tcp))
1013			return 0;
1014
1015		tprints(", ");
1016		if (umove_or_printaddr(tcp, arg, &args))
1017			break;
1018
1019		tprintf("{flags=%" PRI__u64 ", progress=", args.flags);
1020		btrfs_print_objectid(args.progress);
1021		tprints("}");
1022		break;
1023	}
1024
1025	case BTRFS_IOC_SET_RECEIVED_SUBVOL: { /* RW */
1026#ifdef BTRFS_IOC_SET_RECEIVED_SUBVOL_32
1027	case BTRFS_IOC_SET_RECEIVED_SUBVOL_32: { /* RW */
1028		struct btrfs_ioctl_received_subvol_args_32 args32;
1029#endif
1030		struct btrfs_ioctl_received_subvol_args args;
1031		char uuid[UUID_STRING_SIZE+1];
1032
1033		if (entering(tcp))
1034			tprints(", ");
1035		else if (syserror(tcp))
1036			break;
1037		else
1038			tprints(" => ");
1039
1040#ifdef BTRFS_IOC_SET_RECEIVED_SUBVOL_32
1041		/*
1042		 * This is a compat ioctl for 32 bit tools on
1043		 * 64 bit systems.
1044		 */
1045		if (code == BTRFS_IOC_SET_RECEIVED_SUBVOL_32) {
1046			if (umove_or_printaddr(tcp, arg, &args32))
1047				break;
1048			memcpy(args.uuid, args32.uuid, sizeof(uuid));
1049			args.stransid = args32.stransid;
1050			args.rtransid = args32.rtransid;
1051			args.stime.sec = args32.stime.sec;
1052			args.stime.nsec = args32.stime.nsec;
1053			args.rtime.sec = args32.rtime.sec;
1054			args.rtime.nsec = args32.rtime.nsec;
1055			args.flags = args32.flags;
1056		} else
1057#endif
1058		if (umove_or_printaddr(tcp, arg, &args))
1059			break;
1060
1061		if (entering(tcp)) {
1062			btrfs_unparse_uuid((unsigned char *)args.uuid, uuid);
1063			tprintf("{uuid=%s, stransid=%" PRI__u64
1064				", stime=%" PRI__u64 ".%u, flags=%" PRI__u64
1065				"}", uuid, args.stransid, args.stime.sec,
1066				args.stime.nsec, args.flags);
1067			return 0;
1068		}
1069		tprintf("{rtransid=%" PRI__u64 ", rtime=%" PRI__u64 ".%u}",
1070			args.rtransid, args.rtime.sec, args.rtime.nsec);
1071		break;
1072	}
1073
1074	case BTRFS_IOC_SCRUB: /* RW */
1075	case BTRFS_IOC_SCRUB_PROGRESS: { /* RW */
1076		struct btrfs_ioctl_scrub_args args;
1077
1078		if (entering(tcp))
1079			tprints(", ");
1080		else if (syserror(tcp))
1081			break;
1082		else
1083			tprints(" => ");
1084
1085		if (umove_or_printaddr(tcp, arg, &args))
1086			break;
1087
1088		if (entering(tcp)) {
1089			tprintf("{devid=%" PRI__u64, args.devid);
1090			if (code == BTRFS_IOC_SCRUB) {
1091				tprintf(", start=%" PRI__u64 ", end=",
1092					args.start);
1093				tprintf("%" PRI__u64, args.end);
1094				if (args.end == UINT64_MAX)
1095					tprints(" /* UINT64_MAX */");
1096				tprints(", flags=");
1097				printflags64(btrfs_scrub_flags, args.flags,
1098					     "BTRFS_SCRUB_???");
1099			}
1100			tprints("}");
1101			return 0;
1102		}
1103		tprintf("{data_extents_scrubbed=%" PRI__u64
1104			", tree_extents_scrubbed=%" PRI__u64
1105			", data_bytes_scrubbed=%" PRI__u64
1106			", tree_bytes_scrubbed=%" PRI__u64
1107			", read_errors=%" PRI__u64
1108			", csum_errors=%" PRI__u64
1109			", verify_errors=%" PRI__u64
1110			", no_csum=%" PRI__u64
1111			", csum_discards=%" PRI__u64
1112			", super_errors=%" PRI__u64
1113			", malloc_errors=%" PRI__u64
1114			", uncorrectable_errors=%" PRI__u64
1115			", corrected_errors=%" PRI__u64
1116			", last_physical=%" PRI__u64
1117			", unverified_errors=%" PRI__u64 "}",
1118			args.progress.data_extents_scrubbed,
1119			args.progress.tree_extents_scrubbed,
1120			args.progress.data_bytes_scrubbed,
1121			args.progress.tree_bytes_scrubbed,
1122			args.progress.read_errors,
1123			args.progress.csum_errors,
1124			args.progress.verify_errors,
1125			args.progress.no_csum,
1126			args.progress.csum_discards,
1127			args.progress.super_errors,
1128			args.progress.malloc_errors,
1129			args.progress.uncorrectable_errors,
1130			args.progress.corrected_errors,
1131			args.progress.last_physical,
1132			args.progress.unverified_errors);
1133		break;
1134	}
1135
1136	case BTRFS_IOC_TREE_SEARCH: { /* RW */
1137		struct btrfs_ioctl_search_args args;
1138		uint64_t buf_offset;
1139
1140		if (entering(tcp))
1141			tprints(", ");
1142		else if (syserror(tcp))
1143			break;
1144		else
1145			tprints(" => ");
1146
1147		if (umove_or_printaddr(tcp, arg, &args))
1148			break;
1149
1150		buf_offset = offsetof(struct btrfs_ioctl_search_args, buf);
1151		btrfs_print_tree_search(tcp, &args.key, arg + buf_offset,
1152					sizeof(args.buf), false);
1153		if (entering(tcp))
1154			return 0;
1155		break;
1156	}
1157
1158	case BTRFS_IOC_TREE_SEARCH_V2: { /* RW */
1159		struct btrfs_ioctl_search_args_v2 args;
1160		uint64_t buf_offset;
1161
1162		if (entering(tcp))
1163			tprints(", ");
1164		else if (syserror(tcp)) {
1165			if (tcp->u_error == EOVERFLOW) {
1166				tprints(" => ");
1167				tcp->u_error = 0;
1168				if (!umove_or_printaddr(tcp, arg, &args))
1169					tprintf("{buf_size=%" PRIu64 "}",
1170						(uint64_t)args.buf_size);
1171				tcp->u_error = EOVERFLOW;
1172			}
1173			break;
1174		} else
1175			tprints(" => ");
1176
1177		if (umove_or_printaddr(tcp, arg, &args))
1178			break;
1179
1180		buf_offset = offsetof(struct btrfs_ioctl_search_args_v2, buf);
1181		btrfs_print_tree_search(tcp, &args.key, arg + buf_offset,
1182					args.buf_size, true);
1183		if (entering(tcp))
1184			return 0;
1185		break;
1186	}
1187
1188	case BTRFS_IOC_SEND: { /* W */
1189		struct btrfs_ioctl_send_args args;
1190
1191		tprints(", ");
1192		if (umove_or_printaddr(tcp, arg, &args))
1193			break;
1194
1195		tprintf("{send_fd=%" PRI__d64 ", clone_sources_count=%" PRI__u64
1196			", clone_sources=", args.send_fd,
1197			args.clone_sources_count);
1198
1199		if (abbrev(tcp))
1200			tprints("...");
1201		else {
1202			uint64_t record;
1203			print_array(tcp, (unsigned long) args.clone_sources,
1204				    args.clone_sources_count,
1205				    &record, sizeof(record),
1206				    umoven_or_printaddr,
1207				    print_objectid_callback, 0);
1208		}
1209		tprints(", parent_root=");
1210		btrfs_print_objectid(args.parent_root);
1211		tprints(", flags=");
1212		printflags64(btrfs_send_flags, args.flags,
1213			     "BTRFS_SEND_FLAGS_???");
1214		tprints("}");
1215		break;
1216	}
1217
1218	case BTRFS_IOC_SPACE_INFO: { /* RW */
1219		struct btrfs_ioctl_space_args args;
1220
1221		if (entering(tcp))
1222			tprints(", ");
1223		else if (syserror(tcp))
1224			break;
1225		else
1226			tprints(" => ");
1227
1228		if (umove_or_printaddr(tcp, arg, &args))
1229			break;
1230
1231		tprints("{");
1232		if (entering(tcp)) {
1233			tprintf("space_slots=%" PRI__u64 "}", args.space_slots);
1234			return 0;
1235		}
1236
1237		tprintf("total_spaces=%" PRI__u64, args.total_spaces);
1238
1239		if (args.space_slots == 0 && args.total_spaces) {
1240			tprints("}");
1241			break;
1242		}
1243
1244		tprints(", spaces=");
1245
1246		if (abbrev(tcp))
1247			tprints("...");
1248		else {
1249			struct btrfs_ioctl_space_info info;
1250			print_array(tcp, arg + offsetof(typeof(args), spaces),
1251				    args.total_spaces,
1252				    &info, sizeof(info), umoven_or_printaddr,
1253				    print_btrfs_ioctl_space_info, 0);
1254		}
1255		tprints("}");
1256		break;
1257	}
1258
1259	case BTRFS_IOC_SNAP_CREATE:
1260	case BTRFS_IOC_RESIZE:
1261	case BTRFS_IOC_SCAN_DEV:
1262	case BTRFS_IOC_ADD_DEV:
1263	case BTRFS_IOC_RM_DEV:
1264	case BTRFS_IOC_SUBVOL_CREATE:
1265	case BTRFS_IOC_SNAP_DESTROY:
1266	case BTRFS_IOC_DEVICES_READY: { /* W */
1267		struct btrfs_ioctl_vol_args args;
1268
1269		tprints(", ");
1270		if (umove_or_printaddr(tcp, arg, &args))
1271			break;
1272
1273		tprintf("{fd=%" PRI__d64 ", name=", args.fd);
1274		print_quoted_string(args.name, sizeof(args.name),
1275				    QUOTE_0_TERMINATED);
1276		tprints("}");
1277		break;
1278	}
1279
1280	case BTRFS_IOC_SNAP_CREATE_V2:
1281	case BTRFS_IOC_SUBVOL_CREATE_V2: { /* code is W, but is actually RW */
1282		struct btrfs_ioctl_vol_args_v2 args;
1283
1284		if (entering(tcp))
1285			tprints(", ");
1286		else if (syserror(tcp))
1287			break;
1288		else
1289			tprints(" => ");
1290
1291		if (umove_or_printaddr(tcp, arg, &args))
1292			break;
1293
1294		if (entering(tcp)) {
1295			tprintf("{fd=%" PRI__d64 ", flags=", args.fd);
1296			printflags64(btrfs_snap_flags_v2, args.flags,
1297				     "BTRFS_SUBVOL_???");
1298			if (args.flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
1299				tprintf(", size=%" PRI__u64 ", qgroup_inherit=",
1300					args.size);
1301
1302				btrfs_print_qgroup_inherit(tcp,
1303					(unsigned long)args.qgroup_inherit);
1304			}
1305			tprintf(", name=");
1306			print_quoted_string(args.name, sizeof(args.name),
1307					    QUOTE_0_TERMINATED);
1308			tprints("}");
1309			return 0;
1310		}
1311		tprintf("{transid=%" PRI__u64 "}", args.transid);
1312		break;
1313	}
1314
1315	case BTRFS_IOC_GET_FSLABEL: /* R */
1316		if (entering(tcp))
1317			return 0;
1318		/* fall through */
1319	case BTRFS_IOC_SET_FSLABEL: { /* W */
1320		char label[BTRFS_LABEL_SIZE];
1321
1322		tprints(", ");
1323		if (umove_or_printaddr(tcp, arg, &label))
1324			break;
1325		print_quoted_string(label, sizeof(label), QUOTE_0_TERMINATED);
1326		break;
1327	}
1328
1329	case BTRFS_IOC_CLONE:			/* FICLONE */
1330	case BTRFS_IOC_CLONE_RANGE:		/* FICLONERANGE */
1331	case BTRFS_IOC_FILE_EXTENT_SAME:	/* FIDEDUPERANGE */
1332		/*
1333		 * FICLONE, FICLONERANGE, and FIDEDUPERANGE started out as
1334		 * btrfs ioctls and the code was kept for the generic
1335		 * implementations.  We use the BTRFS_* names here because
1336		 * they will be available on older systems.
1337		 */
1338		return file_ioctl(tcp, code, arg);
1339
1340	default:
1341		return RVAL_DECODED;
1342	};
1343	return RVAL_DECODED | 1;
1344}
1345#endif /* HAVE_LINUX_BTRFS_H */
1346