示例#1
0
文件: btrfs.c 项目: yunchih/strace
static void
btrfs_print_balance(struct tcb *tcp, const long arg, bool out)
{
	struct btrfs_ioctl_balance_args balance_args;

	if (umove_or_printaddr(tcp, arg, &balance_args))
		return;

	tprints("{flags=");
	printflags64(btrfs_balance_flags, balance_args.flags,
		     "BTRFS_BALANCE_???");
	if (out) {
		tprints(", state=");
		printflags64(btrfs_balance_state, balance_args.state,
			     "BTRFS_BALANCE_STATE_???");
	}

	if (balance_args.flags & BTRFS_BALANCE_DATA)
		btrfs_print_balance_args("data", &balance_args.data);
	if (balance_args.flags & BTRFS_BALANCE_METADATA)
		btrfs_print_balance_args("meta", &balance_args.meta);
	if (balance_args.flags & BTRFS_BALANCE_SYSTEM)
		btrfs_print_balance_args("sys", &balance_args.sys);
	tprints("}");
}
示例#2
0
static void
print_sched_attr(struct tcb *const tcp, const kernel_ulong_t addr,
		 unsigned int size)
{
	struct {
		uint32_t size;
		uint32_t sched_policy;
		uint64_t sched_flags;
		uint32_t sched_nice;
		uint32_t sched_priority;
		uint64_t sched_runtime;
		uint64_t sched_deadline;
		uint64_t sched_period;
	} attr = {};

	if (size > sizeof(attr))
		size = sizeof(attr);
	if (umoven_or_printaddr(tcp, addr, size, &attr))
		return;

	tprintf("{size=%u, sched_policy=", attr.size);
	printxval(schedulers, attr.sched_policy, "SCHED_???");
	tprints(", sched_flags=");
	printflags64(sched_flags, attr.sched_flags, "SCHED_FLAG_???");
	tprintf(", sched_nice=%d", attr.sched_nice);
	tprintf(", sched_priority=%u", attr.sched_priority);
	tprintf(", sched_runtime=%" PRIu64, attr.sched_runtime);
	tprintf(", sched_deadline=%" PRIu64, attr.sched_deadline);
	tprintf(", sched_period=%" PRIu64 "}", attr.sched_period);
}
示例#3
0
文件: btrfs.c 项目: yunchih/strace
static void
btrfs_print_qgroup_inherit(struct tcb *tcp, const uint64_t qgi_addr)
{
	struct btrfs_qgroup_inherit inherit;

	if (umove_or_printaddr(tcp, qgi_addr, &inherit))
		return;

	tprintf("{flags=");
	printflags64(btrfs_qgroup_inherit_flags, inherit.flags,
		     "BTRFS_QGROUP_INHERIT_???");
	tprintf(", num_qgroups=%" PRI__u64 ", num_ref_copies=%" PRI__u64
		", num_excl_copies=%" PRI__u64 ", lim=",
		inherit.num_qgroups, inherit.num_ref_copies,
		inherit.num_excl_copies);

	btrfs_print_qgroup_limit(&inherit.lim);

	tprints(", qgroups=");

	if (abbrev(tcp)) {
		tprints("...");
	} else {
		uint64_t record;
		print_array(tcp, qgi_addr + offsetof(typeof(inherit), qgroups),
			    inherit.num_qgroups, &record, sizeof(record),
			    umoven_or_printaddr, print_uint64, 0);
	}
	tprints("}");
}
示例#4
0
文件: btrfs.c 项目: yunchih/strace
static void
btrfs_print_features(const struct btrfs_ioctl_feature_flags *flags)
{
	tprints("{compat_flags=");
	printflags64(btrfs_features_compat, flags->compat_flags,
		     "BTRFS_FEATURE_COMPAT_???");

	tprints(", compat_ro_flags=");
	printflags64(btrfs_features_compat_ro, flags->compat_ro_flags,
		     "BTRFS_FEATURE_COMPAT_RO_???");

	tprints(", incompat_flags=");
	printflags64(btrfs_features_incompat, flags->incompat_flags,
		     "BTRFS_FEATURE_INCOMPAT_???");
	tprints("}");
}
示例#5
0
文件: btrfs.c 项目: yunchih/strace
static void
btrfs_print_balance_args(const char *name, const struct btrfs_balance_args *bba)
{
	tprintf(", %s={profiles=", name);
	printflags64(btrfs_space_info_flags, bba->profiles,
		     "BTRFS_BLOCK_GROUP_???");
	print_member_u64(bba, usage);
	print_member_u64(bba, devid);
	print_member_u64(bba, pstart);
	print_member_u64(bba, pend);
	print_member_u64(bba, vstart);
	print_member_u64(bba, vend);
	print_member_u64(bba, target);
	tprints(", flags=");
	printflags64(btrfs_balance_args, bba->flags, "BTRFS_BALANCE_ARGS_???");
	tprints("}");
}
示例#6
0
文件: btrfs.c 项目: yunchih/strace
static void
btrfs_print_qgroup_limit(const struct btrfs_qgroup_limit *lim)
{
	tprints("{flags=");
	printflags64(btrfs_qgroup_limit_flags, lim->flags,
		     "BTRFS_QGROUP_LIMIT_???");
	tprintf(", max_rfer=%" PRI__u64 ", max_excl=%" PRI__u64
		", rsv_rfer=%" PRI__u64 ", rsv_excl=%" PRI__u64 "}",
		lim->max_rfer, lim->max_excl,
		lim->rsv_rfer, lim->rsv_excl);
}
示例#7
0
文件: btrfs.c 项目: yunchih/strace
static bool
print_btrfs_ioctl_space_info(struct tcb *tcp, void *elem_buf,
			     size_t elem_size, void *data)
{
	const struct btrfs_ioctl_space_info *info = elem_buf;

	tprints("{flags=");
	printflags64(btrfs_space_info_flags, info->flags,
		     "BTRFS_SPACE_INFO_???");
	tprintf(", total_bytes=%" PRI__u64 ", used_bytes=%" PRI__u64 "}",
		info->total_bytes, info->used_bytes);

	return true;
}
static bool
print_fiemap_extent(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
{
	const struct fiemap_extent *fe = elem_buf;

	tprintf("{fe_logical=%" PRI__u64
		", fe_physical=%" PRI__u64
		", fe_length=%" PRI__u64 ", ",
		fe->fe_logical, fe->fe_physical, fe->fe_length);

	printflags64(fiemap_extent_flags, fe->fe_flags,
		     "FIEMAP_EXTENT_???");
	tprints("}");

	return true;
}
示例#9
0
文件: btrfs.c 项目: yunchih/strace
MPERS_PRINTER_DECL(int, btrfs_ioctl,
		   struct tcb *tcp, const unsigned int code, const long arg)
{
	switch (code) {
	/* Take no arguments; command only. */
	case BTRFS_IOC_TRANS_START:
	case BTRFS_IOC_TRANS_END:
	case BTRFS_IOC_SYNC:
	case BTRFS_IOC_SCRUB_CANCEL:
	case BTRFS_IOC_QUOTA_RESCAN_WAIT:
	/*
	 * The codes for these ioctls are based on each accepting a
	 * vol_args but none of them actually consume an argument.
	 */
	case BTRFS_IOC_DEFRAG:
	case BTRFS_IOC_BALANCE:
		break;

	/* takes a signed int */
	case BTRFS_IOC_BALANCE_CTL:
		tprints(", ");
		printxval(btrfs_balance_ctl_cmds, arg, "BTRFS_BALANCE_CTL_???");
		break;

	/* returns a 64 */
	case BTRFS_IOC_START_SYNC: /* R */
		if (entering(tcp))
			return 0;
	/* fall through */
	/* takes a u64 */
	case BTRFS_IOC_DEFAULT_SUBVOL: /* W */
	case BTRFS_IOC_WAIT_SYNC: /* W */
		tprints(", ");
		printnum_int64(tcp, arg, "%" PRIu64);
		break;

	/* u64 but describe a flags bitfield; we can make that symbolic */
	case BTRFS_IOC_SUBVOL_GETFLAGS: { /* R */
		uint64_t flags;

		if (entering(tcp))
			return 0;

		tprints(", ");

		if (umove_or_printaddr(tcp, arg, &flags))
			break;

		printflags64(btrfs_snap_flags_v2, flags, "BTRFS_SUBVOL_???");
		break;
	}

	case BTRFS_IOC_SUBVOL_SETFLAGS: { /* W */
		uint64_t flags;

		tprints(", ");

		if (umove_or_printaddr(tcp, arg, &flags))
			break;

		printflags64(btrfs_snap_flags_v2, flags, "BTRFS_SUBVOL_???");
		break;
	}

	/* More complex types */
	case BTRFS_IOC_BALANCE_V2: /* RW */
		if (entering(tcp)) {
			tprints(", ");
			btrfs_print_balance(tcp, arg, false);
			return 0;
		}

		if (syserror(tcp))
			break;

		tprints(" => ");
		btrfs_print_balance(tcp, arg, true);
		break;
	case BTRFS_IOC_BALANCE_PROGRESS: /* R */
		if (entering(tcp))
			return 0;

		tprints(", ");
		btrfs_print_balance(tcp, arg, true);
		break;

	case BTRFS_IOC_DEFRAG_RANGE: { /* W */
		struct btrfs_ioctl_defrag_range_args args;

		tprints(", ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{start=%" PRIu64 ", len=", (uint64_t)args.start);

		tprintf("%" PRIu64, (uint64_t) args.len);
		if (args.len == UINT64_MAX)
			tprints(" /* UINT64_MAX */");

		tprints(", flags=");
		printflags64(btrfs_defrag_flags, args.flags,
			     "BTRFS_DEFRAG_RANGE_???");
		tprintf(", extent_thresh=%u, compress_type=",
			args.extent_thresh);
		printxval(btrfs_compress_types, args.compress_type,
			  "BTRFS_COMPRESS_???");
		tprints("}");
		break;
	}

	case BTRFS_IOC_DEV_INFO: { /* RW */
		struct btrfs_ioctl_dev_info_args args;
		char uuid[UUID_STRING_SIZE+1];
		int valid;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;
		tprints("{");

		valid = btrfs_unparse_uuid(args.uuid, uuid);
		if (entering(tcp)) {
			tprintf("devid=%" PRI__u64, args.devid);
			if (valid)
				tprintf(", uuid=%s", uuid);
			tprints("}");
			return 0;
		}
		if (valid)
			tprintf("uuid=%s, ", uuid);
		tprintf("bytes_used=%" PRI__u64
			", total_bytes=%" PRI__u64 ", path=",
			args.bytes_used, args.total_bytes);
		print_quoted_string((const char *)args.path, sizeof(args.path),
				    QUOTE_0_TERMINATED);
		tprints("}");
		break;
	}

	case BTRFS_IOC_DEV_REPLACE: { /* RW */
		struct_btrfs_ioctl_dev_replace_args args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		if (entering(tcp)) {
			tprints("{cmd=");
			printxval64(btrfs_dev_replace_cmds, args.cmd,
				    "BTRFS_IOCTL_DEV_REPLACE_CMD_???");
			if (args.cmd == BTRFS_IOCTL_DEV_REPLACE_CMD_START) {
				const char *str;
				tprintf(", start={srcdevid=%" PRIu64
				   ", cont_reading_from_srcdev_mode=%" PRIu64
				   ", srcdev_name=",
				   (uint64_t) args.start.srcdevid,
				   (uint64_t) args.start.cont_reading_from_srcdev_mode);

				str = (const char*) args.start.srcdev_name;
				print_quoted_string(str,
						sizeof(args.start.srcdev_name),
						QUOTE_0_TERMINATED);
				tprints(", tgtdev_name=");
				str = (const char*) args.start.tgtdev_name;
				print_quoted_string(str,
						sizeof(args.start.tgtdev_name),
						QUOTE_0_TERMINATED);
				tprints("}");

			}
			tprints("}");
			return 0;
		}

		tprints("{result=");
		printxval64(btrfs_dev_replace_results, args.result,
			    "BTRFS_IOCTL_DEV_REPLACE_RESULT_???");
		if (args.cmd == BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS) {
			char buf[sizeof("HH:MM:SS") + 1];
			time_t time;
			tprints(", ");
			printxval64(btrfs_dev_replace_state,
				   args.status.replace_state,
				   "BTRFS_IOCTL_DEV_REPLACE_STATE_???");
			tprintf(", progress_1000=%" PRIu64 " /* ",
				(uint64_t) args.status.progress_1000);
			if (args.status.progress_1000 <= 1000)
				tprintf("%" PRIu64 ".%.2" PRIu64 "%%",
					(uint64_t) args.status.progress_1000 / 10,
					(uint64_t) args.status.progress_1000 % 10);
			else
				tprints("???");
			tprints(" */ ,");

			time = args.status.time_started;
			strftime(buf, sizeof(buf), "%T",
				 localtime(&time));
			tprintf("time_started=%" PRIu64" /* %s */, ",
				(uint64_t) args.status.time_started, buf);

			time = args.status.time_stopped;
			strftime(buf, sizeof(buf), "%T",
				 localtime(&time));
			tprintf("time_stopped=%" PRIu64" /* %s */, ",
				(uint64_t) args.status.time_stopped, buf);

			tprintf("num_write_errors=%" PRIu64
				", num_uncorrectable_read_errors=%" PRIu64,
				(uint64_t) args.status.num_write_errors,
				(uint64_t) args.status.num_uncorrectable_read_errors);
		}
		tprints("}");
		break;
	}

	case BTRFS_IOC_GET_FEATURES: { /* R */
		struct btrfs_ioctl_feature_flags flags;

		if (entering(tcp))
			return 0;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &flags))
			break;

		btrfs_print_features(&flags);
		break;
	}

	case BTRFS_IOC_SET_FEATURES: { /* W */
		struct btrfs_ioctl_feature_flags flarg[2];

		tprints(", ");

		if (umove_or_printaddr(tcp, arg, &flarg))
			break;

		tprints("[");
		btrfs_print_features(&flarg[0]);
		tprints(", ");
		btrfs_print_features(&flarg[1]);
		tprints("]");
		break;
	}

	case BTRFS_IOC_GET_SUPPORTED_FEATURES: { /* R */
		struct btrfs_ioctl_feature_flags flarg[3];

		if (entering(tcp))
			return 0;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &flarg))
			break;

		tprints("[ /* supported */ ");
		btrfs_print_features(&flarg[0]);

		tprints(", /* safe to set */ ");
		btrfs_print_features(&flarg[1]);

		tprints(", /* safe to clear */ ");
		btrfs_print_features(&flarg[2]);
		tprints("]");

		break;
	}

	case BTRFS_IOC_FS_INFO: { /* R */
		struct btrfs_ioctl_fs_info_args args;
		char uuid[UUID_STRING_SIZE+1];
		uint32_t nodesize, sectorsize, clone_alignment;
#ifndef HAVE_STRUCT_BTRFS_IOCTL_FS_INFO_ARGS_NODESIZE
		__u32 *reserved32;
#endif

		if (entering(tcp))
			return 0;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

#ifdef HAVE_STRUCT_BTRFS_IOCTL_FS_INFO_ARGS_NODESIZE
		nodesize = args.nodesize,
		sectorsize = args.sectorsize,
		clone_alignment = args.clone_alignment;
#else
		reserved32 = (__u32 *) (void *) args.reserved;
		nodesize = reserved32[0];
		sectorsize = reserved32[1];
		clone_alignment = reserved32[2];
#endif
		btrfs_unparse_uuid(args.fsid, uuid);

		tprints("{");
		tprintf("max_id=%" PRI__u64 ", num_devices=%" PRI__u64
			", fsid=%s, nodesize=%u, sectorsize=%u"
			", clone_alignment=%u",
			args.max_id, args.num_devices, uuid,
			nodesize, sectorsize, clone_alignment);
		tprints("}");
		break;
	}

	case BTRFS_IOC_GET_DEV_STATS: { /* RW */
		struct btrfs_ioctl_get_dev_stats args;
		uint64_t i;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{");

		if (entering(tcp))
			tprintf("devid=%" PRI__u64 ", ", args.devid);

		tprintf("nr_items=%" PRI__u64 ", flags=", args.nr_items);
		printflags64(btrfs_dev_stats_flags, args.flags,
			     "BTRFS_DEV_STATS_???");

		if (entering(tcp)) {
			tprints("}");
			return 0;
		}

		/*
		 * The structure has a 1k limit; Let's make sure we don't
		 * go off into the middle of nowhere with a bad nr_items
		 * value.
		 */
		tprints(", [");
		for (i = 0; i < args.nr_items; i++) {
			if (i)
				tprints(", ");
			if (i >= ARRAY_SIZE(args.values)) {
				tprints("...");
				break;
			}
			const char *name = xlookup(btrfs_dev_stats_values, i);
			if (name)
				tprintf("/* %s */ ", name);
			tprintf("%" PRI__u64, args.values[i]);
		}
		tprints("]}");
		break;
	}

	case BTRFS_IOC_INO_LOOKUP: { /* RW */
		struct btrfs_ioctl_ino_lookup_args args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		if (entering(tcp)) {
			/* Use subvolume id of the containing root */
			if (args.treeid == 0)
				set_tcb_priv_ulong(tcp, 1);

			tprints("{treeid=");
			btrfs_print_objectid(args.treeid);
			tprints(", objectid=");
			btrfs_print_objectid(args.objectid);
			tprints("}");
			return 0;
		}

		tprints("{");
		if (get_tcb_priv_ulong(tcp)) {
			tprints("treeid=");
			btrfs_print_objectid(args.treeid);
			tprints(", ");
		}

		tprints("name=");
		print_quoted_string(args.name, sizeof(args.name),
				    QUOTE_0_TERMINATED);
		tprints("}");
		break;
	}

	case BTRFS_IOC_INO_PATHS: { /* RW */
		struct btrfs_ioctl_ino_path_args args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{");

		if (entering(tcp)) {
			tprintf("inum=%" PRI__u64 ", size=%" PRI__u64,
				args.inum, args.size);
			tprintf(", fspath=0x%" PRI__x64 "}", args.fspath);
			return 0;
		}

		tprints("fspath=");
		btrfs_print_ino_path_container(tcp, args.fspath);

		tprints("}");
		break;
	}

	case BTRFS_IOC_LOGICAL_INO: { /* RW */
		struct btrfs_ioctl_logical_ino_args args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{");

		if (entering(tcp)) {
			tprintf("logical=%" PRI__u64 ", size=%" PRI__u64,
				args.logical, args.size);
			tprintf(", inodes=0x%" PRI__x64 "}", args.inodes);
			return 0;
		}

		tprints("inodes=");
		btrfs_print_logical_ino_container(tcp, args.inodes);

		tprints("}");
		break;
	}

	case BTRFS_IOC_QGROUP_ASSIGN: { /* W */
		struct btrfs_ioctl_qgroup_assign_args args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{assign=%" PRI__u64 ", src=%" PRI__u64
			", dst=%" PRI__u64 "}",
			args.assign, args.src, args.dst);
		break;
	}

	case BTRFS_IOC_QGROUP_CREATE: { /* W */
		struct btrfs_ioctl_qgroup_create_args args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{create=%" PRI__u64 ", qgroupid=%" PRI__u64 "}",
			args.create, args.qgroupid);
		break;
	}

	case BTRFS_IOC_QGROUP_LIMIT: { /* R */
		struct btrfs_ioctl_qgroup_limit_args args;

		if (entering(tcp))
			return 0;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{qgroupid=%" PRI__u64 ", lim=", args.qgroupid);
		btrfs_print_qgroup_limit(&args.lim);
		tprints("}");
		break;
	}

	case BTRFS_IOC_QUOTA_CTL: { /* W */
		struct btrfs_ioctl_quota_ctl_args args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		printxval64(btrfs_qgroup_ctl_cmds, args.cmd,
			    "BTRFS_QUOTA_CTL_???");
		tprints("}");

		break;
	}

	case BTRFS_IOC_QUOTA_RESCAN: { /* W */
		struct btrfs_ioctl_quota_rescan_args args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{flags=%" PRIu64 "}", (uint64_t) args.flags);
		break;
	}

	case BTRFS_IOC_QUOTA_RESCAN_STATUS: { /* R */
		struct btrfs_ioctl_quota_rescan_args args;

		if (entering(tcp))
			return 0;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{flags=%" PRIu64 ", progress=", (uint64_t) args.flags);
		btrfs_print_objectid(args.progress);
		tprints("}");
		break;
	}

	case BTRFS_IOC_SET_RECEIVED_SUBVOL: { /* RW */
		struct_btrfs_ioctl_received_subvol_args args;
		char uuid[UUID_STRING_SIZE+1];

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		if (entering(tcp)) {
			btrfs_unparse_uuid((unsigned char *)args.uuid, uuid);
			tprintf("{uuid=%s, stransid=%" PRIu64
				", stime=%" PRIu64 ".%u, flags=%" PRIu64
				"}", uuid, (uint64_t) args.stransid,
				(uint64_t) args.stime.sec, args.stime.nsec,
				(uint64_t) args.flags);
			return 0;
		}
		tprintf("{rtransid=%" PRIu64 ", rtime=%" PRIu64 ".%u}",
			(uint64_t) args.rtransid, (uint64_t) args.rtime.sec,
			args.rtime.nsec);
		break;
	}

	case BTRFS_IOC_SCRUB: /* RW */
	case BTRFS_IOC_SCRUB_PROGRESS: { /* RW */
		struct btrfs_ioctl_scrub_args args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		if (entering(tcp)) {
			tprintf("{devid=%" PRI__u64, args.devid);
			if (code == BTRFS_IOC_SCRUB) {
				tprintf(", start=%" PRI__u64 ", end=",
					args.start);
				tprintf("%" PRI__u64, args.end);
				if (args.end == UINT64_MAX)
					tprints(" /* UINT64_MAX */");
				tprints(", flags=");
				printflags64(btrfs_scrub_flags, args.flags,
					     "BTRFS_SCRUB_???");
			}
			tprints("}");
			return 0;
		}
		tprintf("{data_extents_scrubbed=%" PRI__u64
			", tree_extents_scrubbed=%" PRI__u64
			", data_bytes_scrubbed=%" PRI__u64
			", tree_bytes_scrubbed=%" PRI__u64
			", read_errors=%" PRI__u64
			", csum_errors=%" PRI__u64
			", verify_errors=%" PRI__u64
			", no_csum=%" PRI__u64
			", csum_discards=%" PRI__u64
			", super_errors=%" PRI__u64
			", malloc_errors=%" PRI__u64
			", uncorrectable_errors=%" PRI__u64
			", corrected_errors=%" PRI__u64
			", last_physical=%" PRI__u64
			", unverified_errors=%" PRI__u64 "}",
			args.progress.data_extents_scrubbed,
			args.progress.tree_extents_scrubbed,
			args.progress.data_bytes_scrubbed,
			args.progress.tree_bytes_scrubbed,
			args.progress.read_errors,
			args.progress.csum_errors,
			args.progress.verify_errors,
			args.progress.no_csum,
			args.progress.csum_discards,
			args.progress.super_errors,
			args.progress.malloc_errors,
			args.progress.uncorrectable_errors,
			args.progress.corrected_errors,
			args.progress.last_physical,
			args.progress.unverified_errors);
		break;
	}

	case BTRFS_IOC_TREE_SEARCH: { /* RW */
		struct btrfs_ioctl_search_args args;
		uint64_t buf_offset;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		buf_offset = offsetof(struct btrfs_ioctl_search_args, buf);
		btrfs_print_tree_search(tcp, &args.key, arg + buf_offset,
					sizeof(args.buf), false);
		if (entering(tcp))
			return 0;
		break;
	}

	case BTRFS_IOC_TREE_SEARCH_V2: { /* RW */
		struct btrfs_ioctl_search_args_v2 args;
		uint64_t buf_offset;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp)) {
			if (tcp->u_error == EOVERFLOW) {
				tprints(" => ");
				tcp->u_error = 0;
				if (!umove_or_printaddr(tcp, arg, &args))
					tprintf("{buf_size=%" PRIu64 "}",
						(uint64_t)args.buf_size);
				tcp->u_error = EOVERFLOW;
			}
			break;
		} else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		buf_offset = offsetof(struct btrfs_ioctl_search_args_v2, buf);
		btrfs_print_tree_search(tcp, &args.key, arg + buf_offset,
					args.buf_size, true);
		if (entering(tcp))
			return 0;
		break;
	}

	case BTRFS_IOC_SEND: { /* W */
		struct_btrfs_ioctl_send_args args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{send_fd=");
		printfd(tcp, args.send_fd);
		tprintf(", clone_sources_count=%" PRIu64 ", clone_sources=",
			(uint64_t) args.clone_sources_count);

		if (abbrev(tcp))
			tprints("...");
		else {
			uint64_t record;
			print_array(tcp, (unsigned long) args.clone_sources,
				    args.clone_sources_count,
				    &record, sizeof(record),
				    umoven_or_printaddr,
				    print_objectid_callback, 0);
		}
		tprints(", parent_root=");
		btrfs_print_objectid(args.parent_root);
		tprints(", flags=");
		printflags64(btrfs_send_flags, args.flags,
			     "BTRFS_SEND_FLAGS_???");
		tprints("}");
		break;
	}

	case BTRFS_IOC_SPACE_INFO: { /* RW */
		struct btrfs_ioctl_space_args args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{");
		if (entering(tcp)) {
			tprintf("space_slots=%" PRI__u64 "}", args.space_slots);
			return 0;
		}

		tprintf("total_spaces=%" PRI__u64, args.total_spaces);

		if (args.space_slots == 0 && args.total_spaces) {
			tprints("}");
			break;
		}

		tprints(", spaces=");

		if (abbrev(tcp))
			tprints("...");
		else {
			struct btrfs_ioctl_space_info info;
			print_array(tcp, arg + offsetof(typeof(args), spaces),
				    args.total_spaces,
				    &info, sizeof(info), umoven_or_printaddr,
				    print_btrfs_ioctl_space_info, 0);
		}
		tprints("}");
		break;
	}

	case BTRFS_IOC_SNAP_CREATE:
	case BTRFS_IOC_RESIZE:
	case BTRFS_IOC_SCAN_DEV:
	case BTRFS_IOC_ADD_DEV:
	case BTRFS_IOC_RM_DEV:
	case BTRFS_IOC_SUBVOL_CREATE:
	case BTRFS_IOC_SNAP_DESTROY:
	case BTRFS_IOC_DEVICES_READY: { /* W */
		struct btrfs_ioctl_vol_args args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{fd=");
		printfd(tcp, args.fd);
		tprints(", name=");
		print_quoted_string(args.name, sizeof(args.name),
				    QUOTE_0_TERMINATED);
		tprints("}");
		break;
	}

	case BTRFS_IOC_SNAP_CREATE_V2:
	case BTRFS_IOC_SUBVOL_CREATE_V2: { /* code is W, but is actually RW */
		struct btrfs_ioctl_vol_args_v2 args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		if (entering(tcp)) {
			tprints("{fd=");
			printfd(tcp, args.fd);
			tprints(", flags=");
			printflags64(btrfs_snap_flags_v2, args.flags,
				     "BTRFS_SUBVOL_???");
			if (args.flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
				tprintf(", size=%" PRI__u64 ", qgroup_inherit=",
					args.size);

				btrfs_print_qgroup_inherit(tcp,
					(unsigned long)args.qgroup_inherit);
			}
			tprintf(", name=");
			print_quoted_string(args.name, sizeof(args.name),
					    QUOTE_0_TERMINATED);
			tprints("}");
			return 0;
		}
		tprintf("{transid=%" PRI__u64 "}", args.transid);
		break;
	}

	case BTRFS_IOC_GET_FSLABEL: /* R */
		if (entering(tcp))
			return 0;
		/* fall through */
	case BTRFS_IOC_SET_FSLABEL: { /* W */
		char label[BTRFS_LABEL_SIZE];

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &label))
			break;
		print_quoted_string(label, sizeof(label), QUOTE_0_TERMINATED);
		break;
	}

	case BTRFS_IOC_CLONE:			/* FICLONE */
	case BTRFS_IOC_CLONE_RANGE:		/* FICLONERANGE */
#ifdef BTRFS_IOC_FILE_EXTENT_SAME
	case BTRFS_IOC_FILE_EXTENT_SAME:	/* FIDEDUPERANGE */
#endif
		/*
		 * FICLONE, FICLONERANGE, and FIDEDUPERANGE started out as
		 * btrfs ioctls and the code was kept for the generic
		 * implementations.  We use the BTRFS_* names here because
		 * they will be available on older systems.
		 */
		return file_ioctl(tcp, code, arg);

	default:
		return RVAL_DECODED;
	};
	return RVAL_DECODED | 1;
}
int
file_ioctl(struct tcb *const tcp, const unsigned int code,
	   const kernel_ulong_t arg)
{
	switch (code) {
	case FICLONE:	/* W */
		tprintf(", %d", (int) arg);
		break;

	case FICLONERANGE: { /* W */
		struct file_clone_range args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{src_fd=");
		printfd(tcp, args.src_fd);
		tprintf(", src_offset=%" PRIu64
			", src_length=%" PRIu64
			", dest_offset=%" PRIu64 "}",
			(uint64_t) args.src_offset,
			(uint64_t) args.src_length,
			(uint64_t) args.dest_offset);
		break;
	}

	case FIDEDUPERANGE: { /* RW */
		struct file_dedupe_range args;
		struct file_dedupe_range_info info;
		unsigned int *limit = NULL;
		unsigned int count = 2;
		bool rc;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{");
		if (entering(tcp)) {
			tprintf("src_offset=%" PRIu64
				", src_length=%" PRIu64
				", dest_count=%hu, ",
				(uint64_t) args.src_offset,
				(uint64_t) args.src_length,
				(uint16_t) args.dest_count);
		}

		tprints("info=");

		/* Limit how many elements we print in abbrev mode. */
		if (abbrev(tcp) && args.dest_count > count)
			limit = &count;

		rc = print_array(tcp, arg + offsetof(typeof(args), info),
				 args.dest_count, &info, sizeof(info),
				 tfetch_mem,
				 print_file_dedupe_range_info, limit);

		tprints("}");
		if (!rc || exiting(tcp))
			break;

		return 0;
	}

#ifdef HAVE_LINUX_FIEMAP_H
	case FS_IOC_FIEMAP: {
		struct fiemap args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		if (entering(tcp)) {
			tprintf("{fm_start=%" PRI__u64 ", "
				"fm_length=%" PRI__u64 ", "
				"fm_flags=",
				args.fm_start, args.fm_length);
			printflags64(fiemap_flags, args.fm_flags,
				     "FIEMAP_FLAG_???");
			tprintf(", fm_extent_count=%u}", args.fm_extent_count);
			return 0;
		}

		tprints("{fm_flags=");
		printflags64(fiemap_flags, args.fm_flags,
			     "FIEMAP_FLAG_???");
		tprintf(", fm_mapped_extents=%u",
			args.fm_mapped_extents);
		if (abbrev(tcp)) {
			tprints(", ...");
		} else {
			struct fiemap_extent fe;
			tprints(", fm_extents=");
			print_array(tcp,
				    arg + offsetof(typeof(args), fm_extents),
				    args.fm_mapped_extents, &fe, sizeof(fe),
				    tfetch_mem,
				    print_fiemap_extent, 0);
		}
		tprints("}");

		break;
	}
#endif /* HAVE_LINUX_FIEMAP_H */

	default:
		return RVAL_DECODED;
	};

	return RVAL_IOCTL_DECODED;
}
示例#11
0
int
uffdio_ioctl(struct tcb *const tcp, const unsigned int code,
	     const kernel_ulong_t arg)
{
	switch (code) {
	case UFFDIO_API: {
		struct uffdio_api ua;
		if (entering(tcp)) {
			tprints(", ");
			if (umove_or_printaddr(tcp, arg, &ua))
				return RVAL_DECODED | 1;
			/* Features is intended to contain some flags, but
			 * there aren't any defined yet.
			 */
			tprintf("{api=%#" PRI__x64
				", features=%#" PRI__x64,
				ua.api, ua.features);
		} else {
			if (!syserror(tcp) && !umove(tcp, arg, &ua)) {
				tprintf(", features.out=%#" PRI__x64
					", ioctls=", ua.features);
				printflags64(uffd_api_flags, ua.ioctls,
					     "_UFFDIO_???");
			}
			tprints("}");
		}
		return 1;
	}

	case UFFDIO_COPY: {
		struct uffdio_copy uc;
		if (entering(tcp)) {
			tprints(", ");
			if (umove_or_printaddr(tcp, arg, &uc))
				return RVAL_DECODED | 1;
			tprintf("{dst=%#" PRI__x64 ", src=%#" PRI__x64
				", len=%#" PRI__x64 ", mode=",
				uc.dst, uc.src, uc.len);
			printflags64(uffd_copy_flags, uc.mode,
				     "UFFDIO_COPY_???");
		} else {
			if (!syserror(tcp) && !umove(tcp, arg, &uc))
				tprintf(", copy=%#" PRI__x64, uc.copy);
			tprints("}");
		}
		return 1;
	}

	case UFFDIO_REGISTER: {
		struct uffdio_register ur;
		if (entering(tcp)) {
			tprints(", ");
			if (umove_or_printaddr(tcp, arg, &ur))
				return RVAL_DECODED | 1;
			tprints("{range=");
			tprintf_uffdio_range(&ur.range);
			tprints(", mode=");
			printflags64(uffd_register_mode_flags, ur.mode,
				     "UFFDIO_REGISTER_MODE_???");
		} else {
			if (!syserror(tcp) && !umove(tcp, arg, &ur)) {
				tprints(", ioctls=");
				printflags64(uffd_register_ioctl_flags,
					     ur.ioctls, "UFFDIO_???");
			}
			tprints("}");
		}
		return 1;
	}

	case UFFDIO_UNREGISTER:
	case UFFDIO_WAKE: {
		struct uffdio_range ura;
		tprints(", ");
		if (!umove_or_printaddr(tcp, arg, &ura))
			tprintf_uffdio_range(&ura);
		return RVAL_DECODED | 1;
	}

	case UFFDIO_ZEROPAGE: {
		struct uffdio_zeropage uz;
		if (entering(tcp)) {
			tprints(", ");
			if (umove_or_printaddr(tcp, arg, &uz))
				return RVAL_DECODED | 1;
			tprints("{range=");
			tprintf_uffdio_range(&uz.range);
			tprints(", mode=");
			printflags64(uffd_zeropage_flags, uz.mode,
				     "UFFDIO_ZEROPAGE_???");
		} else {
			if (!syserror(tcp) && !umove(tcp, arg, &uz))
				tprintf(", zeropage=%#" PRI__x64, uz.zeropage);
			tprints("}");
		}
		return 1;
	}

	default:
		return RVAL_DECODED;
	}
}