Skip to contentSkip to conversation

btrfs-progs: qgroups usability

PATCH Superseded [email protected] 2 participants 31 messages Mar 8, 2018 – May 3, 2018

Subsystems (3)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

v2 cover btrfs-progs: qgroups usability

From: Jeff Mahoney <[email protected]>

Thanks to Qu Wenruo, Nikolay Borisov, and Tomohiro Misono for taking the time to review my previous patchset. I've incorporated your suggestions into this version.

Obviously this one is quite a bit longer than the first version. After I posted it, Dave and I talked offline about whether it would make sense to add the ability to output in JSON to other commands. If it does, and we agreed that it did, it would make sense for the choice of format to be a global option. In order to do that, I've had to rework some of how we handle command definition and execution. Mostly that is around how to pass format flags and how to inform the user about which output formats are available for each command.

So, here's the updated series:

* btrfs-progs: quota: Add -W option to rescan to wait without starting rescan
- unchanged

* btrfs-progs: qgroups: fix misleading index check
- unchanged

* btrfs-progs: constify pathnames passed as arguments
- removed stray formatting change in send-utils.c

* btrfs-progs: btrfs-list: add rb_entry helpers for root_info
- new patch, accessors for root_info rb_nodes

* btrfs-progs: btrfs-list: add btrfs_cleanup_root_info
- new patch, adds a helper to clean up strings attached to root_info

* btrfs-progs: qgroups: add pathname to show output
- Fixed help text to be more accurate
- Fixed coding style issues
- Added checks for NULL pathname
- Free root_info strings after looking up pathname
- Free pathname during teardown

* btrfs-progs: qgroups: introduce and use info and limit structures
- edited to 80 columns

* btrfs-progs: qgroups: introduce btrfs_qgroup_query
- Fixed issue with ENOENT vs ENOTTY
- Added filter for search results
- Use temporary key for search header
- Cache passed search key for comparison since the loop modifies it

* btrfs-progs: subvolume: add quota info to btrfs sub show
- Fixed/improved error reporting

* btrfs-progs: help: convert ints used as bools to bool
- new patch

* btrfs-progs: reorder placement of help declarations for send/receive
- new patch, required to remove usage declarations from commands.h

* btrfs-progs: filesystem balance: split out special handling
- new patch, stop directly aliasing 'filesystem balance' to 'balance' -- it still does the right thing for normal execution but help says "go read the balance help instead"

* btrfs-progs: use cmd_struct as command entry point
- new patch, removes most command callback and usage declarations
- replaces with cmd_struct declarations that are used in command group arrays directly, similar to how sysfs attributes are defined

* btrfs-progs: pass cmd_struct to command callback function
- new patch, required to pass flags and have access to usage array

* btrfs-progs: pass cmd_struct to clean_args_no_options{,_relaxed}
- new patch, required to pass cmd_struct to usage()

* btrfs-progs: pass cmd_struct to usage()
- new patch, required to dynamically print what output formats are available based on flags defined in command

* btrfs-progs: add support for output formats
- new patch, adds infrastructure for output formats, including passing caller context to commands

* btrfs-progs: add generic support for json output
- new patch, split out JSON library detection from qgroups patch

* btrfs-progs: handle command groups directly for common case
- new patch, remove most simple command group callbacks

* btrfs-progs: qgroups: add json output for usage command
- remove -j and --compat-json options in favor of global --format json

    or --format json:compat

- added macro for qgroupid format buffer length
- handle NULL pathnames better

-Jeff

Jeff Mahoney (20):
btrfs-progs: quota: Add -W option to rescan to wait without starting
rescan
btrfs-progs: qgroups: fix misleading index check
btrfs-progs: constify pathnames passed as arguments
btrfs-progs: btrfs-list: add rb_entry helpers for root_info
btrfs-progs: btrfs-list: add btrfs_cleanup_root_info
btrfs-progs: qgroups: add pathname to show output
btrfs-progs: qgroups: introduce and use info and limit structures
btrfs-progs: qgroups: introduce btrfs_qgroup_query
btrfs-progs: subvolume: add quota info to btrfs sub show
btrfs-progs: help: convert ints used as bools to bool
btrfs-progs: reorder placement of help declarations for send/receive
btrfs-progs: filesystem balance: split out special handling
btrfs-progs: use cmd_struct as command entry point
btrfs-progs: pass cmd_struct to command callback function
btrfs-progs: pass cmd_struct to clean_args_no_options{,_relaxed}
btrfs-progs: pass cmd_struct to usage()
btrfs-progs: add support for output formats
btrfs-progs: add generic support for json output
btrfs-progs: qgroups: add json output for usage command
btrfs-progs: handle command groups directly for common case

 Documentation/btrfs-qgroup.asciidoc |   7 +
 Documentation/btrfs-quota.asciidoc  |  10 +-
 Makefile.inc.in                     |   4 +-
 btrfs-calc-size.c                   |   5 +-
 btrfs-debug-tree.c                  |   6 +-
 btrfs-list.c                        |  48 ++-
 btrfs-list.h                        |   1 +
 btrfs-show-super.c                  |   6 +-
 btrfs.c                             | 174 ++++++++---
 check/main.c                        |  10 +-
 chunk-recover.c                     |   4 +-
 cmds-balance.c                      |  74 +++--
 cmds-device.c                       |  96 +++---
 cmds-fi-du.c                        |  11 +-
 cmds-fi-usage.c                     |  17 +-
 cmds-filesystem.c                   | 113 ++++---
 cmds-inspect-dump-super.c           |  11 +-
 cmds-inspect-dump-tree.c            |  11 +-
 cmds-inspect-tree-stats.c           |  11 +-
 cmds-inspect.c                      |  78 ++---
 cmds-property.c                     |  55 ++--
 cmds-qgroup.c                       | 125 +++++---
 cmds-quota.c                        |  63 ++--
 cmds-receive.c                      |  70 +++--
 cmds-replace.c                      |  45 +--
 cmds-rescue.c                       |  60 ++--
 cmds-restore.c                      |  12 +-
 cmds-scrub.c                        |  64 ++--
 cmds-send.c                         |  74 ++---
 cmds-subvolume.c                    | 167 +++++++---
 commands.h                          | 165 ++++++----
 configure.ac                        |   6 +
 help.c                              | 121 +++++---
 help.h                              |  15 +-
 kerncompat.h                        |   1 +
 qgroup.c                            | 601 ++++++++++++++++++++++++++++++------
 qgroup.h                            |  25 +-
 utils.c                             |  23 +-
 utils.h                             |   2 +
 39 files changed, 1647 insertions(+), 744 deletions(-)
Signature · 1 line
2.12.3
#1 lore raw

PATCH v2 1/20 btrfs-progs: quota: Add -W option to rescan to wait without starting rescan

From: Jeff Mahoney <[email protected]>

This patch adds a new -W option to wait for a rescan without starting a new operation. This is useful for things like xfstests where we want do to do a "btrfs quota enable" and not continue until the subsequent rescan has finished.

In addition to documenting the new option in the man page, I've cleaned up the rescan entry to document the -w option a bit better.

---
 Documentation/btrfs-quota.asciidoc | 10 +++++++---
 cmds-quota.c                       | 20 ++++++++++++++------
 2 files changed, 21 insertions(+), 9 deletions(-)
Documentation/btrfs-quota.asciidoc +7 -3
index 85ebf729..0b64a69b 100644
@@ -238,15 +238,19 @@ Disable subvolume quota support for a filesystem.
 *enable* <path>::
 Enable subvolume quota support for a filesystem.
 
-*rescan* [-s] <path>::
+*rescan* [-s|-w|-W] <path>::
 Trash all qgroup numbers and scan the metadata again with the current config.
 +
 `Options`
 +
 -s::::
-show status of a running rescan operation.
+Show status of a running rescan operation.
+
 -w::::
-wait for rescan operation to finish(can be already in progress).
+Start rescan operation and wait until it has finished before exiting.  If a rescan is already running, wait until it finishes and then exit without starting a new one.
+
+-W::::
+Wait for rescan operation to finish and then exit.  If a rescan is not already running, exit silently.
 
 EXIT STATUS
 -----------
cmds-quota.c +14 -6
index 745889d1..7f933495 100644
@@ -120,14 +120,20 @@ static int cmd_quota_rescan(int argc, char **argv)
 	int wait_for_completion = 0;
 
 	while (1) {
-		int c = getopt(argc, argv, "sw");
+		int c = getopt(argc, argv, "swW");
 		if (c < 0)
 			break;
 		switch (c) {
 		case 's':
 			ioctlnum = BTRFS_IOC_QUOTA_RESCAN_STATUS;
 			break;
+		case 'W':
+			ioctlnum = 0;
+			wait_for_completion = 1;
+			break;
 		case 'w':
+			/* Reset it in case the user did both -W and -w */
+			ioctlnum = BTRFS_IOC_QUOTA_RESCAN;
 			wait_for_completion = 1;
 			break;
 		default:
@@ -135,8 +141,8 @@ static int cmd_quota_rescan(int argc, char **argv)
 		}
 	}
 
-	if (ioctlnum != BTRFS_IOC_QUOTA_RESCAN && wait_for_completion) {
-		error("switch -w cannot be used with -s");
+	if (ioctlnum == BTRFS_IOC_QUOTA_RESCAN_STATUS && wait_for_completion) {
+		error("switches -w/-W cannot be used with -s");
 		return 1;
 	}
 
@@ -150,8 +156,10 @@ static int cmd_quota_rescan(int argc, char **argv)
 	if (fd < 0)
 		return 1;
 
-	ret = ioctl(fd, ioctlnum, &args);
-	e = errno;
+	if (ioctlnum) {
+		ret = ioctl(fd, ioctlnum, &args);
+		e = errno;
+	}
 
 	if (ioctlnum == BTRFS_IOC_QUOTA_RESCAN_STATUS) {
 		close_file_or_dir(fd, dirstream);
@@ -167,7 +175,7 @@ static int cmd_quota_rescan(int argc, char **argv)
 		return 0;
 	}
 
-	if (ret == 0) {
+	if (ioctlnum == BTRFS_IOC_QUOTA_RESCAN && ret == 0) {
 		printf("quota rescan started\n");
 		fflush(stdout);
 	} else if (ret < 0 && (!wait_for_completion || e != EINPROGRESS)) {
Signature · 1 line
2.12.3
#2 lore raw

Re: [PATCH 01/20] btrfs-progs: quota: Add -W option to rescan to wait without starting rescan

Gentle ping.

This patch can be applied independently and is pretty critical to expose rescan and transaction race.

It would be quite an important part for crafting test case.

Thanks,
Qu

Quoted 104 lines · On 2018年03月08日 10:40, [email protected] wrote:

From: Jeff Mahoney <[email protected]>

This patch adds a new -W option to wait for a rescan without starting a new operation. This is useful for things like xfstests where we want do to do a "btrfs quota enable" and not continue until the subsequent rescan has finished.

In addition to documenting the new option in the man page, I've cleaned up the rescan entry to document the -w option a bit better.

---
 Documentation/btrfs-quota.asciidoc | 10 +++++++---
 cmds-quota.c                       | 20 ++++++++++++++------
 2 files changed, 21 insertions(+), 9 deletions(-)
Documentation/btrfs-quota.asciidoc +7 -3
index 85ebf729..0b64a69b 100644
@@ -238,15 +238,19 @@ Disable subvolume quota support for a filesystem.
 *enable* <path>::
 Enable subvolume quota support for a filesystem.
 
-*rescan* [-s] <path>::
+*rescan* [-s|-w|-W] <path>::
 Trash all qgroup numbers and scan the metadata again with the current config.
 +
 `Options`
 +
 -s::::
-show status of a running rescan operation.
+Show status of a running rescan operation.
+
 -w::::
-wait for rescan operation to finish(can be already in progress).
+Start rescan operation and wait until it has finished before exiting.  If a rescan is already running, wait until it finishes and then exit without starting a new one.
+
+-W::::
+Wait for rescan operation to finish and then exit.  If a rescan is not already running, exit silently.
 
 EXIT STATUS
 -----------
cmds-quota.c +14 -6
index 745889d1..7f933495 100644
@@ -120,14 +120,20 @@ static int cmd_quota_rescan(int argc, char **argv)
 	int wait_for_completion = 0;
 
 	while (1) {
-		int c = getopt(argc, argv, "sw");
+		int c = getopt(argc, argv, "swW");
 		if (c < 0)
 			break;
 		switch (c) {
 		case 's':
 			ioctlnum = BTRFS_IOC_QUOTA_RESCAN_STATUS;
 			break;
+		case 'W':
+			ioctlnum = 0;
+			wait_for_completion = 1;
+			break;
 		case 'w':
+			/* Reset it in case the user did both -W and -w */
+			ioctlnum = BTRFS_IOC_QUOTA_RESCAN;
 			wait_for_completion = 1;
 			break;
 		default:
@@ -135,8 +141,8 @@ static int cmd_quota_rescan(int argc, char **argv)
 		}
 	}
 
-	if (ioctlnum != BTRFS_IOC_QUOTA_RESCAN && wait_for_completion) {
-		error("switch -w cannot be used with -s");
+	if (ioctlnum == BTRFS_IOC_QUOTA_RESCAN_STATUS && wait_for_completion) {
+		error("switches -w/-W cannot be used with -s");
 		return 1;
 	}
 
@@ -150,8 +156,10 @@ static int cmd_quota_rescan(int argc, char **argv)
 	if (fd < 0)
 		return 1;
 
-	ret = ioctl(fd, ioctlnum, &args);
-	e = errno;
+	if (ioctlnum) {
+		ret = ioctl(fd, ioctlnum, &args);
+		e = errno;
+	}
 
 	if (ioctlnum == BTRFS_IOC_QUOTA_RESCAN_STATUS) {
 		close_file_or_dir(fd, dirstream);
@@ -167,7 +175,7 @@ static int cmd_quota_rescan(int argc, char **argv)
 		return 0;
 	}
 
-	if (ret == 0) {
+	if (ioctlnum == BTRFS_IOC_QUOTA_RESCAN && ret == 0) {
 		printf("quota rescan started\n");
 		fflush(stdout);
 	} else if (ret < 0 && (!wait_for_completion || e != EINPROGRESS)) {
#3 lore raw

PATCH v2 2/20 btrfs-progs: qgroups: fix misleading index check

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

In print_single_qgroup_table we check the loop index against BTRFS_QGROUP_CHILD, but what we really mean is "last column." Since we have an enum value to indicate the last value, use that instead of assuming that BTRFS_QGROUP_CHILD is always last.

---
 qgroup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
qgroup.c +1 -1
index 11659e83..67bc0738 100644
@@ -267,7 +267,7 @@ static void print_single_qgroup_table(struct btrfs_qgroup *qgroup)
 			continue;
 		print_qgroup_column(qgroup, i);
 
-		if (i != BTRFS_QGROUP_CHILD)
+		if (i != BTRFS_QGROUP_ALL - 1)
 			printf(" ");
 	}
 	printf("\n");
Signature · 1 line
2.12.3
#4 lore raw

PATCH v2 3/20 btrfs-progs: constify pathnames passed as arguments

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

It's unlikely we're going to modify a pathname argument, so codify that and use const.

---
 chunk-recover.c | 4 ++--
 cmds-device.c   | 2 +-
 cmds-fi-usage.c | 6 +++---
 cmds-rescue.c   | 4 ++--
 4 files changed, 8 insertions(+), 8 deletions(-)
chunk-recover.c +2 -2
index 705bcf52..1d30db51 100644
@@ -1492,7 +1492,7 @@ out:
 	return ERR_PTR(ret);
 }
 
-static int recover_prepare(struct recover_control *rc, char *path)
+static int recover_prepare(struct recover_control *rc, const char *path)
 {
 	int ret;
 	int fd;
@@ -2296,7 +2296,7 @@ static void validate_rebuild_chunks(struct recover_control *rc)
 /*
  * Return 0 when successful, < 0 on error and > 0 if aborted by user
  */
-int btrfs_recover_chunk_tree(char *path, int verbose, int yes)
+int btrfs_recover_chunk_tree(const char *path, int verbose, int yes)
 {
 	int ret = 0;
 	struct btrfs_root *root = NULL;
cmds-device.c +1 -1
index 86459d1b..a49c9d9d 100644
@@ -526,7 +526,7 @@ static const char * const cmd_device_usage_usage[] = {
 	NULL
 };
 
-static int _cmd_device_usage(int fd, char *path, unsigned unit_mode)
+static int _cmd_device_usage(int fd, const char *path, unsigned unit_mode)
 {
 	int i;
 	int ret = 0;
cmds-fi-usage.c +3 -3
index de7ad668..9a1c76ab 100644
@@ -227,7 +227,7 @@ static int cmp_btrfs_ioctl_space_info(const void *a, const void *b)
 /*
  * This function load all the information about the space usage
  */
-static struct btrfs_ioctl_space_args *load_space_info(int fd, char *path)
+static struct btrfs_ioctl_space_args *load_space_info(int fd, const char *path)
 {
 	struct btrfs_ioctl_space_args *sargs = NULL, *sargs_orig = NULL;
 	int ret, count;
@@ -305,7 +305,7 @@ static void get_raid56_used(struct chunk_info *chunks, int chunkcount,
 #define	MIN_UNALOCATED_THRESH	SZ_16M
 static int print_filesystem_usage_overall(int fd, struct chunk_info *chunkinfo,
 		int chunkcount, struct device_info *devinfo, int devcount,
-		char *path, unsigned unit_mode)
+		const char *path, unsigned unit_mode)
 {
 	struct btrfs_ioctl_space_args *sargs = NULL;
 	int i;
@@ -931,7 +931,7 @@ static void _cmd_filesystem_usage_linear(unsigned unit_mode,
 static int print_filesystem_usage_by_chunk(int fd,
 		struct chunk_info *chunkinfo, int chunkcount,
 		struct device_info *devinfo, int devcount,
-		char *path, unsigned unit_mode, int tabular)
+		const char *path, unsigned unit_mode, int tabular)
 {
 	struct btrfs_ioctl_space_args *sargs;
 	int ret = 0;
cmds-rescue.c +2 -2
index c40088ad..c61145bc 100644
@@ -32,8 +32,8 @@ static const char * const rescue_cmd_group_usage[] = {
 	NULL
 };
 
-int btrfs_recover_chunk_tree(char *path, int verbose, int yes);
-int btrfs_recover_superblocks(char *path, int verbose, int yes);
+int btrfs_recover_chunk_tree(const char *path, int verbose, int yes);
+int btrfs_recover_superblocks(const char *path, int verbose, int yes);
 
 static const char * const cmd_rescue_chunk_recover_usage[] = {
 	"btrfs rescue chunk-recover [options] <device>",
Signature · 1 line
2.12.3
#5 lore raw

PATCH v2 4/20 btrfs-progs: btrfs-list: add rb_entry helpers for root_info

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

We use rb_entry all over the place for the root_info pointers. Add a helper to make the code more readable.

---
 btrfs-list.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)
btrfs-list.c +20 -10
index e01c5899..90c98be1 100644
@@ -44,6 +44,16 @@ struct root_lookup {
 	struct rb_root root;
 };
 
+static inline struct root_info *to_root_info(struct rb_node *node)
+{
+	return rb_entry(node, struct root_info, rb_node);
+}
+
+static inline struct root_info *to_root_info_sorted(struct rb_node *node)
+{
+	return rb_entry(node, struct root_info, sort_node);
+}
+
 static struct {
 	char	*name;
 	char	*column_name;
@@ -309,7 +319,7 @@ static int sort_tree_insert(struct root_lookup *sort_tree,
 
 	while (*p) {
 		parent = *p;
-		curr = rb_entry(parent, struct root_info, sort_node);
+		curr = to_root_info_sorted(parent);
 
 		ret = sort_comp(ins, curr, comp_set);
 		if (ret < 0)
@@ -340,7 +350,7 @@ static int root_tree_insert(struct root_lookup *root_tree,
 
 	while(*p) {
 		parent = *p;
-		curr = rb_entry(parent, struct root_info, rb_node);
+		curr = to_root_info(parent);
 
 		ret = comp_entry_with_rootid(ins, curr, 0);
 		if (ret < 0)
@@ -371,7 +381,7 @@ static struct root_info *root_tree_search(struct root_lookup *root_tree,
 	tmp.root_id = root_id;
 
 	while(n) {
-		entry = rb_entry(n, struct root_info, rb_node);
+		entry = to_root_info(n);
 
 		ret = comp_entry_with_rootid(&tmp, entry, 0);
 		if (ret < 0)
@@ -528,7 +538,7 @@ static void free_root_info(struct rb_node *node)
 {
 	struct root_info *ri;
 
-	ri = rb_entry(node, struct root_info, rb_node);
+	ri = to_root_info(node);
 	free(ri->name);
 	free(ri->path);
 	free(ri->full_path);
@@ -1268,7 +1278,7 @@ static void filter_and_sort_subvol(struct root_lookup *all_subvols,
 
 	n = rb_last(&all_subvols->root);
 	while (n) {
-		entry = rb_entry(n, struct root_info, rb_node);
+		entry = to_root_info(n);
 
 		ret = resolve_root(all_subvols, entry, top_id);
 		if (ret == -ENOENT) {
@@ -1300,7 +1310,7 @@ static int list_subvol_fill_paths(int fd, struct root_lookup *root_lookup)
 	while (n) {
 		struct root_info *entry;
 		int ret;
-		entry = rb_entry(n, struct root_info, rb_node);
+		entry = to_root_info(n);
 		ret = lookup_ino_path(fd, entry);
 		if (ret && ret != -ENOENT)
 			return ret;
@@ -1467,7 +1477,7 @@ static void print_all_subvol_info(struct root_lookup *sorted_tree,
 
 	n = rb_first(&sorted_tree->root);
 	while (n) {
-		entry = rb_entry(n, struct root_info, sort_node);
+		entry = to_root_info_sorted(n);
 
 		/* The toplevel subvolume is not listed by default */
 		if (entry->root_id == BTRFS_FS_TREE_OBJECTID)
@@ -1558,7 +1568,7 @@ int btrfs_get_toplevel_subvol(int fd, struct root_info *the_ri)
 		return ret;
 
 	rbn = rb_first(&rl.root);
-	ri = rb_entry(rbn, struct root_info, rb_node);
+	ri = to_root_info(rbn);
 
 	if (ri->root_id != BTRFS_FS_TREE_OBJECTID)
 		return -ENOENT;
@@ -1590,7 +1600,7 @@ int btrfs_get_subvol(int fd, struct root_info *the_ri)
 
 	rbn = rb_first(&rl.root);
 	while(rbn) {
-		ri = rb_entry(rbn, struct root_info, rb_node);
+		ri = to_root_info(rbn);
 		rr = resolve_root(&rl, ri, root_id);
 		if (rr == -ENOENT) {
 			ret = -ENOENT;
@@ -1814,7 +1824,7 @@ char *btrfs_list_path_for_root(int fd, u64 root)
 	while (n) {
 		struct root_info *entry;
 
-		entry = rb_entry(n, struct root_info, rb_node);
+		entry = to_root_info(n);
 		ret = resolve_root(&root_lookup, entry, top_id);
 		if (ret == -ENOENT && entry->root_id == root) {
 			ret_path = NULL;
Signature · 1 line
2.12.3
#6 lore raw

PATCH v2 5/20 btrfs-progs: btrfs-list: add btrfs_cleanup_root_info

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

Currently we can pass back root_info structures to callers but have to free the strings manually. This adds a helper to do it and uses it in cmd_subvol_show.

---
 btrfs-list.c     | 18 +++++++++++++++---
 btrfs-list.h     |  1 +
 cmds-subvolume.c |  5 +----
 3 files changed, 17 insertions(+), 7 deletions(-)
btrfs-list.c +15 -3
index 90c98be1..2fe31e9c 100644
@@ -533,15 +533,27 @@ static int add_root_backref(struct root_lookup *root_lookup, u64 root_id,
 			name_len, 0, 0, 0, NULL, NULL, NULL);
 }
 
+static void __btrfs_free_root_info_strings(struct root_info *ri)
+{
+	free(ri->name);
+	free(ri->path);
+	free(ri->full_path);
+}
+
+void btrfs_cleanup_root_info(struct root_info *ri)
+{
+	__btrfs_free_root_info_strings(ri);
+	ri->name = NULL;
+	ri->path = NULL;
+	ri->full_path = NULL;
+}
 
 static void free_root_info(struct rb_node *node)
 {
 	struct root_info *ri;
 
 	ri = to_root_info(node);
-	free(ri->name);
-	free(ri->path);
-	free(ri->full_path);
+	__btrfs_free_root_info_strings(ri);
 	free(ri);
 }
 
btrfs-list.h +1 -0
index 6e5fc778..9d0478b8 100644
@@ -176,5 +176,6 @@ char *btrfs_list_path_for_root(int fd, u64 root);
 int btrfs_list_get_path_rootid(int fd, u64 *treeid);
 int btrfs_get_subvol(int fd, struct root_info *the_ri);
 int btrfs_get_toplevel_subvol(int fd, struct root_info *the_ri);
+void btrfs_cleanup_root_info(struct root_info *ri);
 
 #endif
cmds-subvolume.c +1 -4
index 8a473f7a..769d2a76 100644
@@ -1113,10 +1113,7 @@ static int cmd_subvol_show(int argc, char **argv)
 			1, raw_prefix);
 
 out:
-	/* clean up */
-	free(get_ri.path);
-	free(get_ri.name);
-	free(get_ri.full_path);
+	btrfs_cleanup_root_info(&get_ri);
 	free(filter_set);
 
 	close_file_or_dir(fd, dirstream1);
Signature · 1 line
2.12.3
#7 lore raw

PATCH v2 6/20 btrfs-progs: qgroups: add pathname to show output

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

The btrfs qgroup show command currently only exports qgroup IDs, forcing the user to resolve which subvolume each corresponds to.

This patch adds pathname resolution to qgroup show so that when the -P option is used, the last column contains the pathname of the root of the subvolume it describes. In the case of nested qgroups, it will show the number of member qgroups or the paths of the members if the -v option is used.

Pathname can also be used as a sort parameter.

---
 Documentation/btrfs-qgroup.asciidoc |   4 +
 cmds-qgroup.c                       |  18 ++++-
 kerncompat.h                        |   1 +
 qgroup.c                            | 152 ++++++++++++++++++++++++++++++++----
 qgroup.h                            |   4 +-
 utils.c                             |  23 ++++--
 utils.h                             |   2 +
 7 files changed, 178 insertions(+), 26 deletions(-)
Documentation/btrfs-qgroup.asciidoc +4 -0
index 3108457c..360b3269 100644
@@ -97,10 +97,14 @@ print child qgroup id.
 print limit of referenced size of qgroup.
 -e::::
 print limit of exclusive size of qgroup.
+-P::::
+print pathname to the root of the subvolume managed by qgroup.  For nested qgroups, the number of members will be printed unless -v is specified.
 -F::::
 list all qgroups which impact the given path(include ancestral qgroups)
 -f::::
 list all qgroups which impact the given path(exclude ancestral qgroups)
+-v::::
+Be more verbose.  Print pathnames of member qgroups when nested.
 --raw::::
 raw numbers in bytes, without the 'B' suffix.
 --human-readable::::
cmds-qgroup.c +15 -3
index 48686436..d704aeaf 100644
@@ -280,8 +280,11 @@ static const char * const cmd_qgroup_show_usage[] = {
 	"               (including ancestral qgroups)",
 	"-f             list all qgroups which impact the given path",
 	"               (excluding ancestral qgroups)",
+	"-P             print first-level qgroups using pathname",
+	"               - nested qgroups will be reported as a count",
+	"-v             verbose, prints pathnames for all nested qgroups",
 	HELPINFO_UNITS_LONG,
-	"--sort=qgroupid,rfer,excl,max_rfer,max_excl",
+	"--sort=qgroupid,rfer,excl,max_rfer,max_excl,pathname",
 	"               list qgroups sorted by specified items",
 	"               you can use '+' or '-' in front of each item.",
 	"               (+:ascending, -:descending, ascending default)",
@@ -299,6 +302,7 @@ static int cmd_qgroup_show(int argc, char **argv)
 	int filter_flag = 0;
 	unsigned unit_mode;
 	int sync = 0;
+	bool verbose = false;
 
 	struct btrfs_qgroup_comparer_set *comparer_set;
 	struct btrfs_qgroup_filter_set *filter_set;
@@ -316,10 +320,11 @@ static int cmd_qgroup_show(int argc, char **argv)
 		static const struct option long_options[] = {
 			{"sort", required_argument, NULL, GETOPT_VAL_SORT},
 			{"sync", no_argument, NULL, GETOPT_VAL_SYNC},
+			{"verbose", no_argument, NULL, 'v'},
 			{ NULL, 0, NULL, 0 }
 		};
 
-		c = getopt_long(argc, argv, "pcreFf", long_options, NULL);
+		c = getopt_long(argc, argv, "pPcreFfv", long_options, NULL);
 		if (c < 0)
 			break;
 		switch (c) {
@@ -327,6 +332,10 @@ static int cmd_qgroup_show(int argc, char **argv)
 			btrfs_qgroup_setup_print_column(
 				BTRFS_QGROUP_PARENT);
 			break;
+		case 'P':
+			btrfs_qgroup_setup_print_column(
+				BTRFS_QGROUP_PATHNAME);
+			break;
 		case 'c':
 			btrfs_qgroup_setup_print_column(
 				BTRFS_QGROUP_CHILD);
@@ -354,6 +363,9 @@ static int cmd_qgroup_show(int argc, char **argv)
 		case GETOPT_VAL_SYNC:
 			sync = 1;
 			break;
+		case 'v':
+			verbose = true;
+			break;
 		default:
 			usage(cmd_qgroup_show_usage);
 		}
@@ -394,7 +406,7 @@ static int cmd_qgroup_show(int argc, char **argv)
 					BTRFS_QGROUP_FILTER_PARENT,
 					qgroupid);
 	}
-	ret = btrfs_show_qgroups(fd, filter_set, comparer_set);
+	ret = btrfs_show_qgroups(fd, filter_set, comparer_set, verbose);
 	close_file_or_dir(fd, dirstream);
 	free(filter_set);
 	free(comparer_set);
kerncompat.h +1 -0
index fa96715f..f97495ee 100644
@@ -29,6 +29,7 @@
 #include <stddef.h>
 #include <linux/types.h>
 #include <stdint.h>
+#include <stdbool.h>
 
 #include <features.h>
 
qgroup.c +137 -15

286 lines not on this page · raw message

qgroup.h +3 -1
index 875fbdf3..f7ab7de5 100644
@@ -59,11 +59,13 @@ enum btrfs_qgroup_column_enum {
 	BTRFS_QGROUP_MAX_EXCL,
 	BTRFS_QGROUP_PARENT,
 	BTRFS_QGROUP_CHILD,
+	BTRFS_QGROUP_PATHNAME,
 	BTRFS_QGROUP_ALL,
 };
 
 enum btrfs_qgroup_comp_enum {
 	BTRFS_QGROUP_COMP_QGROUPID,
+	BTRFS_QGROUP_COMP_PATHNAME,
 	BTRFS_QGROUP_COMP_RFER,
 	BTRFS_QGROUP_COMP_EXCL,
 	BTRFS_QGROUP_COMP_MAX_RFER,
@@ -80,7 +82,7 @@ enum btrfs_qgroup_filter_enum {
 int btrfs_qgroup_parse_sort_string(const char *opt_arg,
 				struct btrfs_qgroup_comparer_set **comps);
 int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *,
-		       struct btrfs_qgroup_comparer_set *);
+		       struct btrfs_qgroup_comparer_set *, bool verbose);
 void btrfs_qgroup_setup_print_column(enum btrfs_qgroup_column_enum column);
 void btrfs_qgroup_setup_units(unsigned unit_mode);
 struct btrfs_qgroup_filter_set *btrfs_qgroup_alloc_filter_set(void);
utils.c +16 -7
index e9cb3a82..7b7f87f1 100644
@@ -2556,15 +2556,9 @@ out:
 	return ret;
 }
 
-int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri, u64 r_id)
+int get_subvol_info_by_rootid_fd(int fd, struct root_info *get_ri, u64 r_id)
 {
-	int fd;
 	int ret;
-	DIR *dirstream = NULL;
-
-	fd = btrfs_open_dir(mnt, &dirstream, 1);
-	if (fd < 0)
-		return -EINVAL;
 
 	memset(get_ri, 0, sizeof(*get_ri));
 	get_ri->root_id = r_id;
@@ -2574,6 +2568,21 @@ int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri, u64 r_i
 	else
 		ret = btrfs_get_subvol(fd, get_ri);
 
+	return ret;
+}
+
+int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri,
+			      u64 r_id)
+{
+	int fd;
+	int ret;
+	DIR *dirstream = NULL;
+
+	fd = btrfs_open_dir(mnt, &dirstream, 1);
+	if (fd < 0)
+		return -EINVAL;
+
+	ret = get_subvol_info_by_rootid_fd(fd, get_ri, r_id);
 	if (ret)
 		error("can't find rootid '%llu' on '%s': %d", r_id, mnt, ret);
 
utils.h +2 -0
index b871c9ff..722d3c48 100644
@@ -154,6 +154,8 @@ int test_isdir(const char *path);
 
 const char *subvol_strip_mountpoint(const char *mnt, const char *full_path);
 int get_subvol_info(const char *fullpath, struct root_info *get_ri);
+int get_subvol_info_by_rootid_fd(int fd, struct root_info *get_ri,
+				 u64 rootid_arg);
 int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri,
 							u64 rootid_arg);
 int get_subvol_info_by_uuid(const char *mnt, struct root_info *get_ri,
Signature · 1 line
2.12.3
Reviewed-by on v2 6/20
#8 lore raw

Re: [PATCH 06/20] btrfs-progs: qgroups: add pathname to show output

Quoted 11 lines · On 2018年03月08日 10:40, [email protected] wrote:

From: Jeff Mahoney <[email protected]>

The btrfs qgroup show command currently only exports qgroup IDs, forcing the user to resolve which subvolume each corresponds to.

This patch adds pathname resolution to qgroup show so that when the -P option is used, the last column contains the pathname of the root of the subvolume it describes. In the case of nested qgroups, it will show the number of member qgroups or the paths of the members if the -v option is used.

Quoted 3 lines

Pathname can also be used as a sort parameter.

Except one nitpick inlined below.

[snip]

qgroup.c static void __free_btrfs_qgroup(struct btrfs_qgroup *bq) · line 835

Quoted 3 lines
qgroup.c +2 -0
 	}
+	if (bq->pathname)
+		free((void *)bq->pathname);

What about just free(bq->pathname);?

Is this (void *) used to get around the const prefix?

Thanks,
Qu

Quoted 141 lines
qgroup.c +7 -6
 	free(bq);
 }
@@ -1107,7 +1228,7 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 				info = (struct btrfs_qgroup_info_item *)
 				       (args.buf + off);
 
-				ret = update_qgroup_info(qgroup_lookup,
+				ret = update_qgroup_info(fd, qgroup_lookup,
 							 qgroupid, info);
 				break;
 			case BTRFS_QGROUP_LIMIT_KEY:
@@ -1115,7 +1236,7 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 				limit = (struct btrfs_qgroup_limit_item *)
 					(args.buf + off);
 
-				ret = update_qgroup_limit(qgroup_lookup,
+				ret = update_qgroup_limit(fd, qgroup_lookup,
 							  qgroupid, limit);
 				break;
 			case BTRFS_QGROUP_RELATION_KEY:
@@ -1159,7 +1280,7 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 	return ret;
 }
 
-static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup)
+static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup, bool verbose)
 {
 
 	struct rb_node *n;
@@ -1170,14 +1291,15 @@ static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup)
 	n = rb_first(&qgroup_lookup->root);
 	while (n) {
 		entry = rb_entry(n, struct btrfs_qgroup, sort_node);
-		print_single_qgroup_table(entry);
+		print_single_qgroup_table(entry, verbose);
 		n = rb_next(n);
 	}
 }
 
 int btrfs_show_qgroups(int fd,
 		       struct btrfs_qgroup_filter_set *filter_set,
-		       struct btrfs_qgroup_comparer_set *comp_set)
+		       struct btrfs_qgroup_comparer_set *comp_set,
+		       bool verbose)
 {
 
 	struct qgroup_lookup qgroup_lookup;
@@ -1189,7 +1311,7 @@ int btrfs_show_qgroups(int fd,
 		return ret;
 	__filter_and_sort_qgroups(&qgroup_lookup, &sort_tree,
 				  filter_set, comp_set);
-	print_all_qgroups(&sort_tree);
+	print_all_qgroups(&sort_tree, verbose);
 
 	__free_all_qgroups(&qgroup_lookup);
 	return ret;
qgroup.h +3 -1
index 875fbdf3..f7ab7de5 100644
@@ -59,11 +59,13 @@ enum btrfs_qgroup_column_enum {
 	BTRFS_QGROUP_MAX_EXCL,
 	BTRFS_QGROUP_PARENT,
 	BTRFS_QGROUP_CHILD,
+	BTRFS_QGROUP_PATHNAME,
 	BTRFS_QGROUP_ALL,
 };
 
 enum btrfs_qgroup_comp_enum {
 	BTRFS_QGROUP_COMP_QGROUPID,
+	BTRFS_QGROUP_COMP_PATHNAME,
 	BTRFS_QGROUP_COMP_RFER,
 	BTRFS_QGROUP_COMP_EXCL,
 	BTRFS_QGROUP_COMP_MAX_RFER,
@@ -80,7 +82,7 @@ enum btrfs_qgroup_filter_enum {
 int btrfs_qgroup_parse_sort_string(const char *opt_arg,
 				struct btrfs_qgroup_comparer_set **comps);
 int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *,
-		       struct btrfs_qgroup_comparer_set *);
+		       struct btrfs_qgroup_comparer_set *, bool verbose);
 void btrfs_qgroup_setup_print_column(enum btrfs_qgroup_column_enum column);
 void btrfs_qgroup_setup_units(unsigned unit_mode);
 struct btrfs_qgroup_filter_set *btrfs_qgroup_alloc_filter_set(void);
utils.c +16 -7
index e9cb3a82..7b7f87f1 100644
@@ -2556,15 +2556,9 @@ out:
 	return ret;
 }
 
-int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri, u64 r_id)
+int get_subvol_info_by_rootid_fd(int fd, struct root_info *get_ri, u64 r_id)
 {
-	int fd;
 	int ret;
-	DIR *dirstream = NULL;
-
-	fd = btrfs_open_dir(mnt, &dirstream, 1);
-	if (fd < 0)
-		return -EINVAL;
 
 	memset(get_ri, 0, sizeof(*get_ri));
 	get_ri->root_id = r_id;
@@ -2574,6 +2568,21 @@ int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri, u64 r_i
 	else
 		ret = btrfs_get_subvol(fd, get_ri);
 
+	return ret;
+}
+
+int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri,
+			      u64 r_id)
+{
+	int fd;
+	int ret;
+	DIR *dirstream = NULL;
+
+	fd = btrfs_open_dir(mnt, &dirstream, 1);
+	if (fd < 0)
+		return -EINVAL;
+
+	ret = get_subvol_info_by_rootid_fd(fd, get_ri, r_id);
 	if (ret)
 		error("can't find rootid '%llu' on '%s': %d", r_id, mnt, ret);
 
utils.h +2 -0
index b871c9ff..722d3c48 100644
@@ -154,6 +154,8 @@ int test_isdir(const char *path);
 
 const char *subvol_strip_mountpoint(const char *mnt, const char *full_path);
 int get_subvol_info(const char *fullpath, struct root_info *get_ri);
+int get_subvol_info_by_rootid_fd(int fd, struct root_info *get_ri,
+				 u64 rootid_arg);
 int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri,
 							u64 rootid_arg);
 int get_subvol_info_by_uuid(const char *mnt, struct root_info *get_ri,
#9 lore raw

Re: [PATCH 06/20] btrfs-progs: qgroups: add pathname to show output

Quoted 22 lines · Qu Wenruo
Quoted 11 lines · On 2018年03月08日 10:40, [email protected] wrote:

From: Jeff Mahoney <[email protected]>

The btrfs qgroup show command currently only exports qgroup IDs, forcing the user to resolve which subvolume each corresponds to.

This patch adds pathname resolution to qgroup show so that when the -P option is used, the last column contains the pathname of the root of the subvolume it describes. In the case of nested qgroups, it will show the number of member qgroups or the paths of the members if the -v option is used.

Quoted 3 lines

Pathname can also be used as a sort parameter.

Except one nitpick inlined below.

Quoted 8 lines

[snip]

qgroup.c static void __free_btrfs_qgroup(struct btrfs_qgroup *bq) · line 835

Quoted 3 lines
qgroup.c +2 -0
 	}
+	if (bq->pathname)
+		free((void *)bq->pathname);

What about just free(bq->pathname);?

Is this (void *) used to get around the const prefix?

Yes.

Thanks,

-Jeff

Signature · 2 lines
Jeff Mahoney
SUSE Labs
#10 lore raw

PATCH v2 7/20 btrfs-progs: qgroups: introduce and use info and limit structures

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

We use structures to pass the info and limit from the kernel as items but store the individual values separately in btrfs_qgroup. We already have a btrfs_qgroup_limit structure that's used for setting the limit.

This patch introduces a btrfs_qgroup_info structure and uses that and btrfs_qgroup_limit in btrfs_qgroup.

---
 qgroup.c | 82 ++++++++++++++++++++++++++++++++++------------------------------
 qgroup.h |  8 +++++++
 2 files changed, 52 insertions(+), 38 deletions(-)
qgroup.c +44 -38
index 5600da99..57815718 100644
@@ -46,20 +46,12 @@ struct btrfs_qgroup {
 	/*
 	 * info_item
 	 */
-	u64 generation;
-	u64 rfer;	/*referenced*/
-	u64 rfer_cmpr;	/*referenced compressed*/
-	u64 excl;	/*exclusive*/
-	u64 excl_cmpr;	/*exclusive compressed*/
+	struct btrfs_qgroup_info info;
 
 	/*
 	 *limit_item
 	 */
-	u64 flags;	/*which limits are set*/
-	u64 max_rfer;
-	u64 max_excl;
-	u64 rsv_rfer;
-	u64 rsv_excl;
+	struct btrfs_qgroup_limit limit;
 
 	/*qgroups this group is member of*/
 	struct list_head qgroups;
@@ -260,6 +252,11 @@ void print_pathname_column(struct btrfs_qgroup *qgroup, bool verbose)
 		fputs("<missing>", stdout);
 }
 
+static int print_u64(u64 value, int unit_mode, int max_len)
+{
+	return printf("%*s", max_len, pretty_size_mode(value, unit_mode));
+}
+
 static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 				enum btrfs_qgroup_column_enum column,
 				bool verbose)
@@ -279,24 +276,26 @@ static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 		print_qgroup_column_add_blank(BTRFS_QGROUP_QGROUPID, len);
 		break;
 	case BTRFS_QGROUP_RFER:
-		len = printf("%*s", max_len, pretty_size_mode(qgroup->rfer, unit_mode));
+		len = print_u64(qgroup->info.referenced, unit_mode, max_len);
 		break;
 	case BTRFS_QGROUP_EXCL:
-		len = printf("%*s", max_len, pretty_size_mode(qgroup->excl, unit_mode));
+		len = print_u64(qgroup->info.exclusive, unit_mode, max_len);
 		break;
 	case BTRFS_QGROUP_PARENT:
 		len = print_parent_column(qgroup);
 		print_qgroup_column_add_blank(BTRFS_QGROUP_PARENT, len);
 		break;
 	case BTRFS_QGROUP_MAX_RFER:
-		if (qgroup->flags & BTRFS_QGROUP_LIMIT_MAX_RFER)
-			len = printf("%*s", max_len, pretty_size_mode(qgroup->max_rfer, unit_mode));
+		if (qgroup->limit.flags & BTRFS_QGROUP_LIMIT_MAX_RFER)
+			len = print_u64(qgroup->limit.max_referenced,
+					unit_mode, max_len);
 		else
 			len = printf("%*s", max_len, "none");
 		break;
 	case BTRFS_QGROUP_MAX_EXCL:
-		if (qgroup->flags & BTRFS_QGROUP_LIMIT_MAX_EXCL)
-			len = printf("%*s", max_len, pretty_size_mode(qgroup->max_excl, unit_mode));
+		if (qgroup->limit.flags & BTRFS_QGROUP_LIMIT_MAX_EXCL)
+			len = print_u64(qgroup->limit.max_exclusive,
+					unit_mode, max_len);
 		else
 			len = printf("%*s", max_len, "none");
 		break;
@@ -439,9 +438,9 @@ static int comp_entry_with_rfer(struct btrfs_qgroup *entry1,
 {
 	int ret;
 
-	if (entry1->rfer > entry2->rfer)
+	if (entry1->info.referenced > entry2->info.referenced)
 		ret = 1;
-	else if (entry1->rfer < entry2->rfer)
+	else if (entry1->info.referenced < entry2->info.referenced)
 		ret = -1;
 	else
 		ret = 0;
@@ -455,9 +454,9 @@ static int comp_entry_with_excl(struct btrfs_qgroup *entry1,
 {
 	int ret;
 
-	if (entry1->excl > entry2->excl)
+	if (entry1->info.exclusive > entry2->info.exclusive)
 		ret = 1;
-	else if (entry1->excl < entry2->excl)
+	else if (entry1->info.exclusive < entry2->info.exclusive)
 		ret = -1;
 	else
 		ret = 0;
@@ -471,9 +470,9 @@ static int comp_entry_with_max_rfer(struct btrfs_qgroup *entry1,
 {
 	int ret;
 
-	if (entry1->max_rfer > entry2->max_rfer)
+	if (entry1->limit.max_referenced > entry2->limit.max_referenced)
 		ret = 1;
-	else if (entry1->max_rfer < entry2->max_rfer)
+	else if (entry1->limit.max_referenced < entry2->limit.max_referenced)
 		ret = -1;
 	else
 		ret = 0;
@@ -487,9 +486,9 @@ static int comp_entry_with_max_excl(struct btrfs_qgroup *entry1,
 {
 	int ret;
 
-	if (entry1->max_excl > entry2->max_excl)
+	if (entry1->limit.max_exclusive > entry2->limit.max_exclusive)
 		ret = 1;
-	else if (entry1->max_excl < entry2->max_excl)
+	else if (entry1->limit.max_exclusive < entry2->limit.max_exclusive)
 		ret = -1;
 	else
 		ret = 0;
@@ -747,11 +746,13 @@ static int update_qgroup_info(int fd, struct qgroup_lookup *qgroup_lookup,
 	if (IS_ERR_OR_NULL(bq))
 		return PTR_ERR(bq);
 
-	bq->generation = btrfs_stack_qgroup_info_generation(info);
-	bq->rfer = btrfs_stack_qgroup_info_referenced(info);
-	bq->rfer_cmpr = btrfs_stack_qgroup_info_referenced_compressed(info);
-	bq->excl = btrfs_stack_qgroup_info_exclusive(info);
-	bq->excl_cmpr = btrfs_stack_qgroup_info_exclusive_compressed(info);
+	bq->info.generation = btrfs_stack_qgroup_info_generation(info);
+	bq->info.referenced = btrfs_stack_qgroup_info_referenced(info);
+	bq->info.referenced_compressed =
+			btrfs_stack_qgroup_info_referenced_compressed(info);
+	bq->info.exclusive = btrfs_stack_qgroup_info_exclusive(info);
+	bq->info.exclusive_compressed =
+			btrfs_stack_qgroup_info_exclusive_compressed(info);
 
 	return 0;
 }
@@ -766,11 +767,14 @@ static int update_qgroup_limit(int fd, struct qgroup_lookup *qgroup_lookup,
 	if (IS_ERR_OR_NULL(bq))
 		return PTR_ERR(bq);
 
-	bq->flags = btrfs_stack_qgroup_limit_flags(limit);
-	bq->max_rfer = btrfs_stack_qgroup_limit_max_referenced(limit);
-	bq->max_excl = btrfs_stack_qgroup_limit_max_exclusive(limit);
-	bq->rsv_rfer = btrfs_stack_qgroup_limit_rsv_referenced(limit);
-	bq->rsv_excl = btrfs_stack_qgroup_limit_rsv_exclusive(limit);
+	bq->limit.flags = btrfs_stack_qgroup_limit_flags(limit);
+	bq->limit.max_referenced =
+			btrfs_stack_qgroup_limit_max_referenced(limit);
+	bq->limit.max_exclusive =
+			btrfs_stack_qgroup_limit_max_exclusive(limit);
+	bq->limit.rsv_referenced =
+			btrfs_stack_qgroup_limit_rsv_referenced(limit);
+	bq->limit.rsv_exclusive = btrfs_stack_qgroup_limit_rsv_exclusive(limit);
 
 	return 0;
 }
@@ -1063,22 +1067,24 @@ static void __update_columns_max_len(struct btrfs_qgroup *bq,
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_RFER:
-		len = strlen(pretty_size_mode(bq->rfer, unit_mode));
+		len = strlen(pretty_size_mode(bq->info.referenced, unit_mode));
 		if (btrfs_qgroup_columns[column].max_len < len)
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_EXCL:
-		len = strlen(pretty_size_mode(bq->excl, unit_mode));
+		len = strlen(pretty_size_mode(bq->info.exclusive, unit_mode));
 		if (btrfs_qgroup_columns[column].max_len < len)
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_MAX_RFER:
-		len = strlen(pretty_size_mode(bq->max_rfer, unit_mode));
+		len = strlen(pretty_size_mode(bq->limit.max_referenced,
+			     unit_mode));
 		if (btrfs_qgroup_columns[column].max_len < len)
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_MAX_EXCL:
-		len = strlen(pretty_size_mode(bq->max_excl, unit_mode));
+		len = strlen(pretty_size_mode(bq->limit.max_exclusive,
+			     unit_mode));
 		if (btrfs_qgroup_columns[column].max_len < len)
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
qgroup.h +8 -0
index f7ab7de5..5e71349c 100644
@@ -79,6 +79,14 @@ enum btrfs_qgroup_filter_enum {
 	BTRFS_QGROUP_FILTER_MAX,
 };
 
+struct btrfs_qgroup_info {
+	u64 generation;
+	u64 referenced;
+	u64 referenced_compressed;
+	u64 exclusive;
+	u64 exclusive_compressed;
+};
+
 int btrfs_qgroup_parse_sort_string(const char *opt_arg,
 				struct btrfs_qgroup_comparer_set **comps);
 int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *,
Signature · 1 line
2.12.3
Reviewed-by on v2 7/20
#11 lore raw

Re: [PATCH 07/20] btrfs-progs: qgroups: introduce and use info and limit structures

Quoted 10 lines · On 2018年03月08日 10:40, [email protected] wrote:

From: Jeff Mahoney <[email protected]>

We use structures to pass the info and limit from the kernel as items but store the individual values separately in btrfs_qgroup. We already have a btrfs_qgroup_limit structure that's used for setting the limit.

This patch introduces a btrfs_qgroup_info structure and uses that and btrfs_qgroup_limit in btrfs_qgroup.

Thanks,
Qu

Quoted 213 lines
---
 qgroup.c | 82 ++++++++++++++++++++++++++++++++++------------------------------
 qgroup.h |  8 +++++++
 2 files changed, 52 insertions(+), 38 deletions(-)
qgroup.c +44 -38
index 5600da99..57815718 100644
@@ -46,20 +46,12 @@ struct btrfs_qgroup {
 	/*
 	 * info_item
 	 */
-	u64 generation;
-	u64 rfer;	/*referenced*/
-	u64 rfer_cmpr;	/*referenced compressed*/
-	u64 excl;	/*exclusive*/
-	u64 excl_cmpr;	/*exclusive compressed*/
+	struct btrfs_qgroup_info info;
 
 	/*
 	 *limit_item
 	 */
-	u64 flags;	/*which limits are set*/
-	u64 max_rfer;
-	u64 max_excl;
-	u64 rsv_rfer;
-	u64 rsv_excl;
+	struct btrfs_qgroup_limit limit;
 
 	/*qgroups this group is member of*/
 	struct list_head qgroups;
@@ -260,6 +252,11 @@ void print_pathname_column(struct btrfs_qgroup *qgroup, bool verbose)
 		fputs("<missing>", stdout);
 }
 
+static int print_u64(u64 value, int unit_mode, int max_len)
+{
+	return printf("%*s", max_len, pretty_size_mode(value, unit_mode));
+}
+
 static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 				enum btrfs_qgroup_column_enum column,
 				bool verbose)
@@ -279,24 +276,26 @@ static void print_qgroup_column(struct btrfs_qgroup *qgroup,
 		print_qgroup_column_add_blank(BTRFS_QGROUP_QGROUPID, len);
 		break;
 	case BTRFS_QGROUP_RFER:
-		len = printf("%*s", max_len, pretty_size_mode(qgroup->rfer, unit_mode));
+		len = print_u64(qgroup->info.referenced, unit_mode, max_len);
 		break;
 	case BTRFS_QGROUP_EXCL:
-		len = printf("%*s", max_len, pretty_size_mode(qgroup->excl, unit_mode));
+		len = print_u64(qgroup->info.exclusive, unit_mode, max_len);
 		break;
 	case BTRFS_QGROUP_PARENT:
 		len = print_parent_column(qgroup);
 		print_qgroup_column_add_blank(BTRFS_QGROUP_PARENT, len);
 		break;
 	case BTRFS_QGROUP_MAX_RFER:
-		if (qgroup->flags & BTRFS_QGROUP_LIMIT_MAX_RFER)
-			len = printf("%*s", max_len, pretty_size_mode(qgroup->max_rfer, unit_mode));
+		if (qgroup->limit.flags & BTRFS_QGROUP_LIMIT_MAX_RFER)
+			len = print_u64(qgroup->limit.max_referenced,
+					unit_mode, max_len);
 		else
 			len = printf("%*s", max_len, "none");
 		break;
 	case BTRFS_QGROUP_MAX_EXCL:
-		if (qgroup->flags & BTRFS_QGROUP_LIMIT_MAX_EXCL)
-			len = printf("%*s", max_len, pretty_size_mode(qgroup->max_excl, unit_mode));
+		if (qgroup->limit.flags & BTRFS_QGROUP_LIMIT_MAX_EXCL)
+			len = print_u64(qgroup->limit.max_exclusive,
+					unit_mode, max_len);
 		else
 			len = printf("%*s", max_len, "none");
 		break;
@@ -439,9 +438,9 @@ static int comp_entry_with_rfer(struct btrfs_qgroup *entry1,
 {
 	int ret;
 
-	if (entry1->rfer > entry2->rfer)
+	if (entry1->info.referenced > entry2->info.referenced)
 		ret = 1;
-	else if (entry1->rfer < entry2->rfer)
+	else if (entry1->info.referenced < entry2->info.referenced)
 		ret = -1;
 	else
 		ret = 0;
@@ -455,9 +454,9 @@ static int comp_entry_with_excl(struct btrfs_qgroup *entry1,
 {
 	int ret;
 
-	if (entry1->excl > entry2->excl)
+	if (entry1->info.exclusive > entry2->info.exclusive)
 		ret = 1;
-	else if (entry1->excl < entry2->excl)
+	else if (entry1->info.exclusive < entry2->info.exclusive)
 		ret = -1;
 	else
 		ret = 0;
@@ -471,9 +470,9 @@ static int comp_entry_with_max_rfer(struct btrfs_qgroup *entry1,
 {
 	int ret;
 
-	if (entry1->max_rfer > entry2->max_rfer)
+	if (entry1->limit.max_referenced > entry2->limit.max_referenced)
 		ret = 1;
-	else if (entry1->max_rfer < entry2->max_rfer)
+	else if (entry1->limit.max_referenced < entry2->limit.max_referenced)
 		ret = -1;
 	else
 		ret = 0;
@@ -487,9 +486,9 @@ static int comp_entry_with_max_excl(struct btrfs_qgroup *entry1,
 {
 	int ret;
 
-	if (entry1->max_excl > entry2->max_excl)
+	if (entry1->limit.max_exclusive > entry2->limit.max_exclusive)
 		ret = 1;
-	else if (entry1->max_excl < entry2->max_excl)
+	else if (entry1->limit.max_exclusive < entry2->limit.max_exclusive)
 		ret = -1;
 	else
 		ret = 0;
@@ -747,11 +746,13 @@ static int update_qgroup_info(int fd, struct qgroup_lookup *qgroup_lookup,
 	if (IS_ERR_OR_NULL(bq))
 		return PTR_ERR(bq);
 
-	bq->generation = btrfs_stack_qgroup_info_generation(info);
-	bq->rfer = btrfs_stack_qgroup_info_referenced(info);
-	bq->rfer_cmpr = btrfs_stack_qgroup_info_referenced_compressed(info);
-	bq->excl = btrfs_stack_qgroup_info_exclusive(info);
-	bq->excl_cmpr = btrfs_stack_qgroup_info_exclusive_compressed(info);
+	bq->info.generation = btrfs_stack_qgroup_info_generation(info);
+	bq->info.referenced = btrfs_stack_qgroup_info_referenced(info);
+	bq->info.referenced_compressed =
+			btrfs_stack_qgroup_info_referenced_compressed(info);
+	bq->info.exclusive = btrfs_stack_qgroup_info_exclusive(info);
+	bq->info.exclusive_compressed =
+			btrfs_stack_qgroup_info_exclusive_compressed(info);
 
 	return 0;
 }
@@ -766,11 +767,14 @@ static int update_qgroup_limit(int fd, struct qgroup_lookup *qgroup_lookup,
 	if (IS_ERR_OR_NULL(bq))
 		return PTR_ERR(bq);
 
-	bq->flags = btrfs_stack_qgroup_limit_flags(limit);
-	bq->max_rfer = btrfs_stack_qgroup_limit_max_referenced(limit);
-	bq->max_excl = btrfs_stack_qgroup_limit_max_exclusive(limit);
-	bq->rsv_rfer = btrfs_stack_qgroup_limit_rsv_referenced(limit);
-	bq->rsv_excl = btrfs_stack_qgroup_limit_rsv_exclusive(limit);
+	bq->limit.flags = btrfs_stack_qgroup_limit_flags(limit);
+	bq->limit.max_referenced =
+			btrfs_stack_qgroup_limit_max_referenced(limit);
+	bq->limit.max_exclusive =
+			btrfs_stack_qgroup_limit_max_exclusive(limit);
+	bq->limit.rsv_referenced =
+			btrfs_stack_qgroup_limit_rsv_referenced(limit);
+	bq->limit.rsv_exclusive = btrfs_stack_qgroup_limit_rsv_exclusive(limit);
 
 	return 0;
 }
@@ -1063,22 +1067,24 @@ static void __update_columns_max_len(struct btrfs_qgroup *bq,
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_RFER:
-		len = strlen(pretty_size_mode(bq->rfer, unit_mode));
+		len = strlen(pretty_size_mode(bq->info.referenced, unit_mode));
 		if (btrfs_qgroup_columns[column].max_len < len)
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_EXCL:
-		len = strlen(pretty_size_mode(bq->excl, unit_mode));
+		len = strlen(pretty_size_mode(bq->info.exclusive, unit_mode));
 		if (btrfs_qgroup_columns[column].max_len < len)
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_MAX_RFER:
-		len = strlen(pretty_size_mode(bq->max_rfer, unit_mode));
+		len = strlen(pretty_size_mode(bq->limit.max_referenced,
+			     unit_mode));
 		if (btrfs_qgroup_columns[column].max_len < len)
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
 	case BTRFS_QGROUP_MAX_EXCL:
-		len = strlen(pretty_size_mode(bq->max_excl, unit_mode));
+		len = strlen(pretty_size_mode(bq->limit.max_exclusive,
+			     unit_mode));
 		if (btrfs_qgroup_columns[column].max_len < len)
 			btrfs_qgroup_columns[column].max_len = len;
 		break;
qgroup.h +8 -0
index f7ab7de5..5e71349c 100644
@@ -79,6 +79,14 @@ enum btrfs_qgroup_filter_enum {
 	BTRFS_QGROUP_FILTER_MAX,
 };
 
+struct btrfs_qgroup_info {
+	u64 generation;
+	u64 referenced;
+	u64 referenced_compressed;
+	u64 exclusive;
+	u64 exclusive_compressed;
+};
+
 int btrfs_qgroup_parse_sort_string(const char *opt_arg,
 				struct btrfs_qgroup_comparer_set **comps);
 int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *,
#12 lore raw

PATCH v2 8/20 btrfs-progs: qgroups: introduce btrfs_qgroup_query

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

The only mechanism we have in the progs for searching qgroups is to load all of them and filter the results. This works for qgroup show but to add quota information to 'btrfs subvoluem show' it's pretty wasteful.

This patch splits out setting up the search and performing the search so we can search for a single qgroupid more easily. Since TREE_SEARCH will give results that don't strictly match the search terms, we add a filter to match only the results we care about.

---
 qgroup.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++---------------
 qgroup.h |   7 ++++
 2 files changed, 116 insertions(+), 34 deletions(-)
qgroup.c +109 -34
index 57815718..d076b1de 100644
@@ -1165,11 +1165,30 @@ static inline void print_status_flag_warning(u64 flags)
 		warning("qgroup data inconsistent, rescan recommended");
 }
 
-static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
+static bool key_in_range(const struct btrfs_key *key,
+			 const struct btrfs_ioctl_search_key *sk)
+{
+	if (key->objectid < sk->min_objectid ||
+	    key->objectid > sk->max_objectid)
+		return false;
+
+	if (key->type < sk->min_type ||
+	    key->type > sk->max_type)
+		return false;
+
+	if (key->offset < sk->min_offset ||
+	    key->offset > sk->max_offset)
+		return false;
+
+	return true;
+}
+
+static int __qgroups_search(int fd, struct btrfs_ioctl_search_args *args,
+			    struct qgroup_lookup *qgroup_lookup)
 {
 	int ret;
-	struct btrfs_ioctl_search_args args;
-	struct btrfs_ioctl_search_key *sk = &args.key;
+	struct btrfs_ioctl_search_key *sk = &args->key;
+	struct btrfs_ioctl_search_key filter_key = args->key;
 	struct btrfs_ioctl_search_header *sh;
 	unsigned long off = 0;
 	unsigned int i;
@@ -1180,30 +1199,15 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 	u64 qgroupid;
 	u64 qgroupid1;
 
-	memset(&args, 0, sizeof(args));
-
-	sk->tree_id = BTRFS_QUOTA_TREE_OBJECTID;
-	sk->max_type = BTRFS_QGROUP_RELATION_KEY;
-	sk->min_type = BTRFS_QGROUP_STATUS_KEY;
-	sk->max_objectid = (u64)-1;
-	sk->max_offset = (u64)-1;
-	sk->max_transid = (u64)-1;
-	sk->nr_items = 4096;
-
 	qgroup_lookup_init(qgroup_lookup);
 
 	while (1) {
-		ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
+		ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, args);
 		if (ret < 0) {
-			if (errno == ENOENT) {
-				error("can't list qgroups: quotas not enabled");
+			if (errno == ENOENT)
 				ret = -ENOTTY;
-			} else {
-				error("can't list qgroups: %s",
-				       strerror(errno));
+			else
 				ret = -errno;
-			}
-
 			break;
 		}
 
@@ -1217,37 +1221,46 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 		 * read the root_ref item it contains
 		 */
 		for (i = 0; i < sk->nr_items; i++) {
-			sh = (struct btrfs_ioctl_search_header *)(args.buf +
+			struct btrfs_key key;
+
+			sh = (struct btrfs_ioctl_search_header *)(args->buf +
 								  off);
 			off += sizeof(*sh);
 
-			switch (btrfs_search_header_type(sh)) {
+			key.objectid = btrfs_search_header_objectid(sh);
+			key.type = btrfs_search_header_type(sh);
+			key.offset = btrfs_search_header_offset(sh);
+
+			if (!key_in_range(&key, &filter_key))
+				goto next;
+
+			switch (key.type) {
 			case BTRFS_QGROUP_STATUS_KEY:
 				si = (struct btrfs_qgroup_status_item *)
-				     (args.buf + off);
+				     (args->buf + off);
 				flags = btrfs_stack_qgroup_status_flags(si);
 
 				print_status_flag_warning(flags);
 				break;
 			case BTRFS_QGROUP_INFO_KEY:
-				qgroupid = btrfs_search_header_offset(sh);
+				qgroupid = key.offset;
 				info = (struct btrfs_qgroup_info_item *)
-				       (args.buf + off);
+				       (args->buf + off);
 
 				ret = update_qgroup_info(fd, qgroup_lookup,
 							 qgroupid, info);
 				break;
 			case BTRFS_QGROUP_LIMIT_KEY:
-				qgroupid = btrfs_search_header_offset(sh);
+				qgroupid = key.offset;
 				limit = (struct btrfs_qgroup_limit_item *)
-					(args.buf + off);
+					(args->buf + off);
 
 				ret = update_qgroup_limit(fd, qgroup_lookup,
 							  qgroupid, limit);
 				break;
 			case BTRFS_QGROUP_RELATION_KEY:
-				qgroupid = btrfs_search_header_offset(sh);
-				qgroupid1 = btrfs_search_header_objectid(sh);
+				qgroupid = key.offset;
+				qgroupid1 = key.objectid;
 
 				if (qgroupid < qgroupid1)
 					break;
@@ -1262,15 +1275,16 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 			if (ret)
 				return ret;
 
+next:
 			off += btrfs_search_header_len(sh);
 
 			/*
 			 * record the mins in sk so we can make sure the
 			 * next search doesn't repeat this root
 			 */
-			sk->min_type = btrfs_search_header_type(sh);
-			sk->min_offset = btrfs_search_header_offset(sh);
-			sk->min_objectid = btrfs_search_header_objectid(sh);
+			sk->min_type = key.type;
+			sk->min_offset = key.offset;
+			sk->min_objectid = key.objectid;
 		}
 		sk->nr_items = 4096;
 		/*
@@ -1286,6 +1300,67 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 	return ret;
 }
 
+static int qgroups_search_all(int fd, struct qgroup_lookup *qgroup_lookup)
+{
+	struct btrfs_ioctl_search_args args = {
+		.key = {
+			.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
+			.max_type = BTRFS_QGROUP_RELATION_KEY,
+			.min_type = BTRFS_QGROUP_STATUS_KEY,
+			.max_objectid = (u64)-1,
+			.max_offset = (u64)-1,
+			.max_transid = (u64)-1,
+			.nr_items = 4096,
+		},
+	};
+	int ret;
+
+	ret = __qgroups_search(fd, &args, qgroup_lookup);
+	if (ret == -ENOTTY)
+		error("can't list qgroups: quotas not enabled");
+	else if (ret < 0)
+		error("can't list qgroups: %s", strerror(-ret));
+	return ret;
+}
+
+int btrfs_qgroup_query(int fd, u64 qgroupid, struct btrfs_qgroup_stats *stats)
+{
+	struct btrfs_ioctl_search_args args = {
+		.key = {
+			.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
+			.min_type = BTRFS_QGROUP_INFO_KEY,
+			.max_type = BTRFS_QGROUP_LIMIT_KEY,
+			.max_objectid = 0,
+			.min_offset = qgroupid,
+			.max_offset = qgroupid,
+			.max_transid = (u64)-1,
+			.nr_items = 4096,
+		},
+	};
+	struct qgroup_lookup qgroup_lookup;
+	struct btrfs_qgroup *qgroup;
+	struct rb_node *n;
+	int ret;
+
+	ret = __qgroups_search(fd, &args, &qgroup_lookup);
+	if (ret < 0)
+		return ret;
+
+	ret = -ENODATA;
+	n = rb_first(&qgroup_lookup.root);
+	if (n) {
+		qgroup = rb_entry(n, struct btrfs_qgroup, rb_node);
+		stats->qgroupid = qgroup->qgroupid;
+		stats->info = qgroup->info;
+		stats->limit = qgroup->limit;
+
+		ret = 0;
+	}
+
+	__free_all_qgroups(&qgroup_lookup);
+	return ret;
+}
+
 static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup, bool verbose)
 {
 
@@ -1312,7 +1387,7 @@ int btrfs_show_qgroups(int fd,
 	struct qgroup_lookup sort_tree;
 	int ret;
 
-	ret = __qgroups_search(fd, &qgroup_lookup);
+	ret = qgroups_search_all(fd, &qgroup_lookup);
 	if (ret)
 		return ret;
 	__filter_and_sort_qgroups(&qgroup_lookup, &sort_tree,
qgroup.h +7 -0
index 5e71349c..688f92b2 100644
@@ -87,6 +87,12 @@ struct btrfs_qgroup_info {
 	u64 exclusive_compressed;
 };
 
+struct btrfs_qgroup_stats {
+	u64 qgroupid;
+	struct btrfs_qgroup_info info;
+	struct btrfs_qgroup_limit limit;
+};
+
 int btrfs_qgroup_parse_sort_string(const char *opt_arg,
 				struct btrfs_qgroup_comparer_set **comps);
 int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *,
@@ -105,4 +111,5 @@ int qgroup_inherit_add_group(struct btrfs_qgroup_inherit **inherit, char *arg);
 int qgroup_inherit_add_copy(struct btrfs_qgroup_inherit **inherit, char *arg,
 			    int type);
 
+int btrfs_qgroup_query(int fd, u64 qgroupid, struct btrfs_qgroup_stats *stats);
 #endif
Signature · 1 line
2.12.3
#13 lore raw

Re: [PATCH 08/20] btrfs-progs: qgroups: introduce btrfs_qgroup_query

Quoted 33 lines · On 2018年03月08日 10:40, [email protected] wrote:

From: Jeff Mahoney <[email protected]>

The only mechanism we have in the progs for searching qgroups is to load all of them and filter the results. This works for qgroup show but to add quota information to 'btrfs subvoluem show' it's pretty wasteful.

This patch splits out setting up the search and performing the search so we can search for a single qgroupid more easily. Since TREE_SEARCH will give results that don't strictly match the search terms, we add a filter to match only the results we care about.

---
 qgroup.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++---------------
 qgroup.h |   7 ++++
 2 files changed, 116 insertions(+), 34 deletions(-)
qgroup.c +7 -1
index 57815718..d076b1de 100644
@@ -1165,11 +1165,30 @@ static inline void print_status_flag_warning(u64 flags)
 		warning("qgroup data inconsistent, rescan recommended");
 }
 
-static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
+static bool key_in_range(const struct btrfs_key *key,
+			 const struct btrfs_ioctl_search_key *sk)
+{
+	if (key->objectid < sk->min_objectid ||
+	    key->objectid > sk->max_objectid)
+		return false;
+

qgroup.c static inline void print_status_flag_warning(u64 flags) · line 1184

Quoted 10 lines
qgroup.c +10 -0
+	if (key->type < sk->min_type ||
+	    key->type > sk->max_type)
+		return false;
+
+	if (key->offset < sk->min_offset ||
+	    key->offset > sk->max_offset)
+		return false;
+
+	return true;
+}

Even with the key_in_range() check here, we are still following the tree search slice behavior:

tree search will still gives us all the items in key range from (min_objectid, min_type, min_offset) to (max_objectid, max_type, max_offset).

I don't see much different between the tree search ioctl and this one.

Quoted 54 lines
qgroup.c +11 -21
+
+static int __qgroups_search(int fd, struct btrfs_ioctl_search_args *args,
+			    struct qgroup_lookup *qgroup_lookup)
 {
 	int ret;
-	struct btrfs_ioctl_search_args args;
-	struct btrfs_ioctl_search_key *sk = &args.key;
+	struct btrfs_ioctl_search_key *sk = &args->key;
+	struct btrfs_ioctl_search_key filter_key = args->key;
 	struct btrfs_ioctl_search_header *sh;
 	unsigned long off = 0;
 	unsigned int i;
@@ -1180,30 +1199,15 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 	u64 qgroupid;
 	u64 qgroupid1;
 
-	memset(&args, 0, sizeof(args));
-
-	sk->tree_id = BTRFS_QUOTA_TREE_OBJECTID;
-	sk->max_type = BTRFS_QGROUP_RELATION_KEY;
-	sk->min_type = BTRFS_QGROUP_STATUS_KEY;
-	sk->max_objectid = (u64)-1;
-	sk->max_offset = (u64)-1;
-	sk->max_transid = (u64)-1;
-	sk->nr_items = 4096;
-
 	qgroup_lookup_init(qgroup_lookup);
 
 	while (1) {
-		ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
+		ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, args);
 		if (ret < 0) {
-			if (errno == ENOENT) {
-				error("can't list qgroups: quotas not enabled");
+			if (errno == ENOENT)
 				ret = -ENOTTY;
-			} else {
-				error("can't list qgroups: %s",
-				       strerror(errno));
+			else
 				ret = -errno;
-			}
-
 			break;
 		}
 
@@ -1217,37 +1221,46 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 		 * read the root_ref item it contains
 		 */
 		for (i = 0; i < sk->nr_items; i++) {
-			sh = (struct btrfs_ioctl_search_header *)(args.buf +
+			struct btrfs_key key;
+
+			sh = (struct btrfs_ioctl_search_header *)(args->buf +

qgroup.c static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) · line 1235

Quoted 10 lines
qgroup.c +6 -1
 								  off);
 			off += sizeof(*sh);
 
-			switch (btrfs_search_header_type(sh)) {
+			key.objectid = btrfs_search_header_objectid(sh);
+			key.type = btrfs_search_header_type(sh);
+			key.offset = btrfs_search_header_offset(sh);
+
+			if (!key_in_range(&key, &filter_key))
+				goto next;

It still looks like that most other qgroup info will get calculated.

Quoted 85 lines
qgroup.c +36 -10
+
+			switch (key.type) {
 			case BTRFS_QGROUP_STATUS_KEY:
 				si = (struct btrfs_qgroup_status_item *)
-				     (args.buf + off);
+				     (args->buf + off);
 				flags = btrfs_stack_qgroup_status_flags(si);
 
 				print_status_flag_warning(flags);
 				break;
 			case BTRFS_QGROUP_INFO_KEY:
-				qgroupid = btrfs_search_header_offset(sh);
+				qgroupid = key.offset;
 				info = (struct btrfs_qgroup_info_item *)
-				       (args.buf + off);
+				       (args->buf + off);
 
 				ret = update_qgroup_info(fd, qgroup_lookup,
 							 qgroupid, info);
 				break;
 			case BTRFS_QGROUP_LIMIT_KEY:
-				qgroupid = btrfs_search_header_offset(sh);
+				qgroupid = key.offset;
 				limit = (struct btrfs_qgroup_limit_item *)
-					(args.buf + off);
+					(args->buf + off);
 
 				ret = update_qgroup_limit(fd, qgroup_lookup,
 							  qgroupid, limit);
 				break;
 			case BTRFS_QGROUP_RELATION_KEY:
-				qgroupid = btrfs_search_header_offset(sh);
-				qgroupid1 = btrfs_search_header_objectid(sh);
+				qgroupid = key.offset;
+				qgroupid1 = key.objectid;
 
 				if (qgroupid < qgroupid1)
 					break;
@@ -1262,15 +1275,16 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 			if (ret)
 				return ret;
 
+next:
 			off += btrfs_search_header_len(sh);
 
 			/*
 			 * record the mins in sk so we can make sure the
 			 * next search doesn't repeat this root
 			 */
-			sk->min_type = btrfs_search_header_type(sh);
-			sk->min_offset = btrfs_search_header_offset(sh);
-			sk->min_objectid = btrfs_search_header_objectid(sh);
+			sk->min_type = key.type;
+			sk->min_offset = key.offset;
+			sk->min_objectid = key.objectid;
 		}
 		sk->nr_items = 4096;
 		/*
@@ -1286,6 +1300,67 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 	return ret;
 }
 
+static int qgroups_search_all(int fd, struct qgroup_lookup *qgroup_lookup)
+{
+	struct btrfs_ioctl_search_args args = {
+		.key = {
+			.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
+			.max_type = BTRFS_QGROUP_RELATION_KEY,
+			.min_type = BTRFS_QGROUP_STATUS_KEY,
+			.max_objectid = (u64)-1,
+			.max_offset = (u64)-1,
+			.max_transid = (u64)-1,
+			.nr_items = 4096,
+		},
+	};
+	int ret;
+
+	ret = __qgroups_search(fd, &args, qgroup_lookup);
+	if (ret == -ENOTTY)
+		error("can't list qgroups: quotas not enabled");
+	else if (ret < 0)
+		error("can't list qgroups: %s", strerror(-ret));
+	return ret;
+}
+

qgroup.c static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) · line 1335

Quoted 10 lines
qgroup.c +10 -0
+int btrfs_qgroup_query(int fd, u64 qgroupid, struct btrfs_qgroup_stats *stats)
+{
+	struct btrfs_ioctl_search_args args = {
+		.key = {
+			.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
+			.min_type = BTRFS_QGROUP_INFO_KEY,
+			.max_type = BTRFS_QGROUP_LIMIT_KEY,
+			.max_objectid = 0,
+			.min_offset = qgroupid,
+			.max_offset = qgroupid,

Just keep in mind that such search could include unrelated qgroup info into the result, key_in_range() check won't help much due to the limit of how tree search works.

Quoted 5 lines
qgroup.c +5 -0
+			.max_transid = (u64)-1,
+			.nr_items = 4096,
+		},
+	};
+	struct qgroup_lookup qgroup_lookup;

qgroup.c static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) · line 1350

Quoted 10 lines
qgroup.c +10 -0
+	struct btrfs_qgroup *qgroup;
+	struct rb_node *n;
+	int ret;
+
+	ret = __qgroups_search(fd, &args, &qgroup_lookup);
+	if (ret < 0)
+		return ret;
+
+	ret = -ENODATA;
+	n = rb_first(&qgroup_lookup.root);

And in worst case, if we're query some qgroup which doesn't exist (maybe manually deleted), then due to limit of tree search, @qgroup_lookup could contain unrelated qgroup info.

In that case, rb_first() could gives us some unrelated qgroup.

For example, we have qgroups info for 5, 258, 259, 1/1, and we're trying to query qgroup 257 (deleted manually), then we will get the following result from tree search:

	item 3 key (0 QGROUP_INFO 0/258) itemoff 16131 itemsize 40
	item 4 key (0 QGROUP_INFO 0/259) itemoff 16131 itemsize 40
	item 5 key (0 QGROUP_INFO 1/1) itemoff 16091 itemsize 40
	item 6 key (0 QGROUP_LIMIT 0/5) itemoff 16051 itemsize 40

So in @qgroup_lookup, the first item will be qgroup 258 instead of the non-exist qgroup 257.

Either caller needs extra check or we need to do extra check in this function.

Thanks,
Qu

Quoted 49 lines
qgroup.c +14 -1
+	if (n) {
+		qgroup = rb_entry(n, struct btrfs_qgroup, rb_node);
+		stats->qgroupid = qgroup->qgroupid;
+		stats->info = qgroup->info;
+		stats->limit = qgroup->limit;
+
+		ret = 0;
+	}
+
+	__free_all_qgroups(&qgroup_lookup);
+	return ret;
+}
+
 static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup, bool verbose)
 {
 
@@ -1312,7 +1387,7 @@ int btrfs_show_qgroups(int fd,
 	struct qgroup_lookup sort_tree;
 	int ret;
 
-	ret = __qgroups_search(fd, &qgroup_lookup);
+	ret = qgroups_search_all(fd, &qgroup_lookup);
 	if (ret)
 		return ret;
 	__filter_and_sort_qgroups(&qgroup_lookup, &sort_tree,
qgroup.h +7 -0
index 5e71349c..688f92b2 100644
@@ -87,6 +87,12 @@ struct btrfs_qgroup_info {
 	u64 exclusive_compressed;
 };
 
+struct btrfs_qgroup_stats {
+	u64 qgroupid;
+	struct btrfs_qgroup_info info;
+	struct btrfs_qgroup_limit limit;
+};
+
 int btrfs_qgroup_parse_sort_string(const char *opt_arg,
 				struct btrfs_qgroup_comparer_set **comps);
 int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *,
@@ -105,4 +111,5 @@ int qgroup_inherit_add_group(struct btrfs_qgroup_inherit **inherit, char *arg);
 int qgroup_inherit_add_copy(struct btrfs_qgroup_inherit **inherit, char *arg,
 			    int type);
 
+int btrfs_qgroup_query(int fd, u64 qgroupid, struct btrfs_qgroup_stats *stats);
 #endif
#14 lore raw

Re: [PATCH 08/20] btrfs-progs: qgroups: introduce btrfs_qgroup_query

Quoted 50 lines · Qu Wenruo
Quoted 33 lines · On 2018年03月08日 10:40, [email protected] wrote:

From: Jeff Mahoney <[email protected]>

The only mechanism we have in the progs for searching qgroups is to load all of them and filter the results. This works for qgroup show but to add quota information to 'btrfs subvoluem show' it's pretty wasteful.

This patch splits out setting up the search and performing the search so we can search for a single qgroupid more easily. Since TREE_SEARCH will give results that don't strictly match the search terms, we add a filter to match only the results we care about.

---
 qgroup.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++---------------
 qgroup.h |   7 ++++
 2 files changed, 116 insertions(+), 34 deletions(-)
qgroup.c +7 -1
index 57815718..d076b1de 100644
@@ -1165,11 +1165,30 @@ static inline void print_status_flag_warning(u64 flags)
 		warning("qgroup data inconsistent, rescan recommended");
 }
 
-static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
+static bool key_in_range(const struct btrfs_key *key,
+			 const struct btrfs_ioctl_search_key *sk)
+{
+	if (key->objectid < sk->min_objectid ||
+	    key->objectid > sk->max_objectid)
+		return false;
+

qgroup.c static inline void print_status_flag_warning(u64 flags) · line 1184

Quoted 10 lines
qgroup.c +10 -0
+	if (key->type < sk->min_type ||
+	    key->type > sk->max_type)
+		return false;
+
+	if (key->offset < sk->min_offset ||
+	    key->offset > sk->max_offset)
+		return false;
+
+	return true;
+}

Even with the key_in_range() check here, we are still following the tree search slice behavior:

Quoted 5 lines

tree search will still gives us all the items in key range from (min_objectid, min_type, min_offset) to (max_objectid, max_type, max_offset).

I don't see much different between the tree search ioctl and this one.

It's fundamentally different.

The one in the kernel has a silly interface. It should be min_key and max_key since the components aren't evaluated independently. It effectively treats min_key and max_key as 136-bit values and returns everything between them, inclusive. That's the slice behavior, as you call it.

This key_in_range treats each component separately and acts as a filter on the slice returned from the kernel. If we request min/max_offset = 259, the caller will not get anything without offset = 259.

I suppose, ultimately, this could also be done using a filter on the rbtree using the existing interface but that seems even more wasteful.

-Jeff

Quoted 257 lines
Quoted 54 lines
qgroup.c +11 -21
+
+static int __qgroups_search(int fd, struct btrfs_ioctl_search_args *args,
+			    struct qgroup_lookup *qgroup_lookup)
 {
 	int ret;
-	struct btrfs_ioctl_search_args args;
-	struct btrfs_ioctl_search_key *sk = &args.key;
+	struct btrfs_ioctl_search_key *sk = &args->key;
+	struct btrfs_ioctl_search_key filter_key = args->key;
 	struct btrfs_ioctl_search_header *sh;
 	unsigned long off = 0;
 	unsigned int i;
@@ -1180,30 +1199,15 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 	u64 qgroupid;
 	u64 qgroupid1;
 
-	memset(&args, 0, sizeof(args));
-
-	sk->tree_id = BTRFS_QUOTA_TREE_OBJECTID;
-	sk->max_type = BTRFS_QGROUP_RELATION_KEY;
-	sk->min_type = BTRFS_QGROUP_STATUS_KEY;
-	sk->max_objectid = (u64)-1;
-	sk->max_offset = (u64)-1;
-	sk->max_transid = (u64)-1;
-	sk->nr_items = 4096;
-
 	qgroup_lookup_init(qgroup_lookup);
 
 	while (1) {
-		ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
+		ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, args);
 		if (ret < 0) {
-			if (errno == ENOENT) {
-				error("can't list qgroups: quotas not enabled");
+			if (errno == ENOENT)
 				ret = -ENOTTY;
-			} else {
-				error("can't list qgroups: %s",
-				       strerror(errno));
+			else
 				ret = -errno;
-			}
-
 			break;
 		}
 
@@ -1217,37 +1221,46 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 		 * read the root_ref item it contains
 		 */
 		for (i = 0; i < sk->nr_items; i++) {
-			sh = (struct btrfs_ioctl_search_header *)(args.buf +
+			struct btrfs_key key;
+
+			sh = (struct btrfs_ioctl_search_header *)(args->buf +

qgroup.c static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) · line 1235

Quoted 10 lines
qgroup.c +6 -1
 								  off);
 			off += sizeof(*sh);
 
-			switch (btrfs_search_header_type(sh)) {
+			key.objectid = btrfs_search_header_objectid(sh);
+			key.type = btrfs_search_header_type(sh);
+			key.offset = btrfs_search_header_offset(sh);
+
+			if (!key_in_range(&key, &filter_key))
+				goto next;

It still looks like that most other qgroup info will get calculated.

Quoted 85 lines
qgroup.c +36 -10
+
+			switch (key.type) {
 			case BTRFS_QGROUP_STATUS_KEY:
 				si = (struct btrfs_qgroup_status_item *)
-				     (args.buf + off);
+				     (args->buf + off);
 				flags = btrfs_stack_qgroup_status_flags(si);
 
 				print_status_flag_warning(flags);
 				break;
 			case BTRFS_QGROUP_INFO_KEY:
-				qgroupid = btrfs_search_header_offset(sh);
+				qgroupid = key.offset;
 				info = (struct btrfs_qgroup_info_item *)
-				       (args.buf + off);
+				       (args->buf + off);
 
 				ret = update_qgroup_info(fd, qgroup_lookup,
 							 qgroupid, info);
 				break;
 			case BTRFS_QGROUP_LIMIT_KEY:
-				qgroupid = btrfs_search_header_offset(sh);
+				qgroupid = key.offset;
 				limit = (struct btrfs_qgroup_limit_item *)
-					(args.buf + off);
+					(args->buf + off);
 
 				ret = update_qgroup_limit(fd, qgroup_lookup,
 							  qgroupid, limit);
 				break;
 			case BTRFS_QGROUP_RELATION_KEY:
-				qgroupid = btrfs_search_header_offset(sh);
-				qgroupid1 = btrfs_search_header_objectid(sh);
+				qgroupid = key.offset;
+				qgroupid1 = key.objectid;
 
 				if (qgroupid < qgroupid1)
 					break;
@@ -1262,15 +1275,16 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 			if (ret)
 				return ret;
 
+next:
 			off += btrfs_search_header_len(sh);
 
 			/*
 			 * record the mins in sk so we can make sure the
 			 * next search doesn't repeat this root
 			 */
-			sk->min_type = btrfs_search_header_type(sh);
-			sk->min_offset = btrfs_search_header_offset(sh);
-			sk->min_objectid = btrfs_search_header_objectid(sh);
+			sk->min_type = key.type;
+			sk->min_offset = key.offset;
+			sk->min_objectid = key.objectid;
 		}
 		sk->nr_items = 4096;
 		/*
@@ -1286,6 +1300,67 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 	return ret;
 }
 
+static int qgroups_search_all(int fd, struct qgroup_lookup *qgroup_lookup)
+{
+	struct btrfs_ioctl_search_args args = {
+		.key = {
+			.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
+			.max_type = BTRFS_QGROUP_RELATION_KEY,
+			.min_type = BTRFS_QGROUP_STATUS_KEY,
+			.max_objectid = (u64)-1,
+			.max_offset = (u64)-1,
+			.max_transid = (u64)-1,
+			.nr_items = 4096,
+		},
+	};
+	int ret;
+
+	ret = __qgroups_search(fd, &args, qgroup_lookup);
+	if (ret == -ENOTTY)
+		error("can't list qgroups: quotas not enabled");
+	else if (ret < 0)
+		error("can't list qgroups: %s", strerror(-ret));
+	return ret;
+}
+

qgroup.c static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) · line 1335

Quoted 10 lines
qgroup.c +10 -0
+int btrfs_qgroup_query(int fd, u64 qgroupid, struct btrfs_qgroup_stats *stats)
+{
+	struct btrfs_ioctl_search_args args = {
+		.key = {
+			.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
+			.min_type = BTRFS_QGROUP_INFO_KEY,
+			.max_type = BTRFS_QGROUP_LIMIT_KEY,
+			.max_objectid = 0,
+			.min_offset = qgroupid,
+			.max_offset = qgroupid,

Just keep in mind that such search could include unrelated qgroup info into the result, key_in_range() check won't help much due to the limit of how tree search works.

Quoted 5 lines
qgroup.c +5 -0
+			.max_transid = (u64)-1,
+			.nr_items = 4096,
+		},
+	};
+	struct qgroup_lookup qgroup_lookup;

qgroup.c static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) · line 1350

Quoted 10 lines
qgroup.c +10 -0
+	struct btrfs_qgroup *qgroup;
+	struct rb_node *n;
+	int ret;
+
+	ret = __qgroups_search(fd, &args, &qgroup_lookup);
+	if (ret < 0)
+		return ret;
+
+	ret = -ENODATA;
+	n = rb_first(&qgroup_lookup.root);

And in worst case, if we're query some qgroup which doesn't exist (maybe manually deleted), then due to limit of tree search, @qgroup_lookup could contain unrelated qgroup info.

In that case, rb_first() could gives us some unrelated qgroup.

For example, we have qgroups info for 5, 258, 259, 1/1, and we're trying to query qgroup 257 (deleted manually), then we will get the following result from tree search:

	item 3 key (0 QGROUP_INFO 0/258) itemoff 16131 itemsize 40
	item 4 key (0 QGROUP_INFO 0/259) itemoff 16131 itemsize 40
	item 5 key (0 QGROUP_INFO 1/1) itemoff 16091 itemsize 40
	item 6 key (0 QGROUP_LIMIT 0/5) itemoff 16051 itemsize 40

So in @qgroup_lookup, the first item will be qgroup 258 instead of the non-exist qgroup 257.

Either caller needs extra check or we need to do extra check in this function.

Thanks,
Qu

Quoted 49 lines
qgroup.c +14 -1
+	if (n) {
+		qgroup = rb_entry(n, struct btrfs_qgroup, rb_node);
+		stats->qgroupid = qgroup->qgroupid;
+		stats->info = qgroup->info;
+		stats->limit = qgroup->limit;
+
+		ret = 0;
+	}
+
+	__free_all_qgroups(&qgroup_lookup);
+	return ret;
+}
+
 static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup, bool verbose)
 {
 
@@ -1312,7 +1387,7 @@ int btrfs_show_qgroups(int fd,
 	struct qgroup_lookup sort_tree;
 	int ret;
 
-	ret = __qgroups_search(fd, &qgroup_lookup);
+	ret = qgroups_search_all(fd, &qgroup_lookup);
 	if (ret)
 		return ret;
 	__filter_and_sort_qgroups(&qgroup_lookup, &sort_tree,
qgroup.h +7 -0
index 5e71349c..688f92b2 100644
@@ -87,6 +87,12 @@ struct btrfs_qgroup_info {
 	u64 exclusive_compressed;
 };
 
+struct btrfs_qgroup_stats {
+	u64 qgroupid;
+	struct btrfs_qgroup_info info;
+	struct btrfs_qgroup_limit limit;
+};
+
 int btrfs_qgroup_parse_sort_string(const char *opt_arg,
 				struct btrfs_qgroup_comparer_set **comps);
 int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *,
@@ -105,4 +111,5 @@ int qgroup_inherit_add_group(struct btrfs_qgroup_inherit **inherit, char *arg);
 int qgroup_inherit_add_copy(struct btrfs_qgroup_inherit **inherit, char *arg,
 			    int type);
 
+int btrfs_qgroup_query(int fd, u64 qgroupid, struct btrfs_qgroup_stats *stats);
 #endif
Signature · 2 lines
Jeff Mahoney
SUSE Labs
Reviewed-by
#15 lore raw

Re: [PATCH 08/20] btrfs-progs: qgroups: introduce btrfs_qgroup_query

Quoted 65 lines · Jeff Mahoney
Quoted 50 lines · Qu Wenruo
Quoted 33 lines · On 2018年03月08日 10:40, [email protected] wrote:

From: Jeff Mahoney <[email protected]>

The only mechanism we have in the progs for searching qgroups is to load all of them and filter the results. This works for qgroup show but to add quota information to 'btrfs subvoluem show' it's pretty wasteful.

This patch splits out setting up the search and performing the search so we can search for a single qgroupid more easily. Since TREE_SEARCH will give results that don't strictly match the search terms, we add a filter to match only the results we care about.

---
 qgroup.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++---------------
 qgroup.h |   7 ++++
 2 files changed, 116 insertions(+), 34 deletions(-)
qgroup.c +7 -1
index 57815718..d076b1de 100644
@@ -1165,11 +1165,30 @@ static inline void print_status_flag_warning(u64 flags)
 		warning("qgroup data inconsistent, rescan recommended");
 }
 
-static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
+static bool key_in_range(const struct btrfs_key *key,
+			 const struct btrfs_ioctl_search_key *sk)
+{
+	if (key->objectid < sk->min_objectid ||
+	    key->objectid > sk->max_objectid)
+		return false;
+

qgroup.c static inline void print_status_flag_warning(u64 flags) · line 1184

Quoted 10 lines
qgroup.c +10 -0
+	if (key->type < sk->min_type ||
+	    key->type > sk->max_type)
+		return false;
+
+	if (key->offset < sk->min_offset ||
+	    key->offset > sk->max_offset)
+		return false;
+
+	return true;
+}

Even with the key_in_range() check here, we are still following the tree search slice behavior:

Quoted 5 lines

tree search will still gives us all the items in key range from (min_objectid, min_type, min_offset) to (max_objectid, max_type, max_offset).

I don't see much different between the tree search ioctl and this one.

It's fundamentally different.

The one in the kernel has a silly interface. It should be min_key and max_key since the components aren't evaluated independently. It effectively treats min_key and max_key as 136-bit values and returns everything between them, inclusive. That's the slice behavior, as you call it.

Quoted 3 lines

This key_in_range treats each component separately and acts as a filter on the slice returned from the kernel. If we request min/max_offset = 259, the caller will not get anything without offset = 259.

You're right.

I'm just an idiot, the separate check on objectid/type/offset breaks the slice behavior so we won't found any thing unrelated.

So the current design is completely fine, even we try to query something doesn't exist we won't have any noise.

Thanks for the filter and this really helps a lot.

Thanks,
Qu

Quoted 265 lines

I suppose, ultimately, this could also be done using a filter on the rbtree using the existing interface but that seems even more wasteful.

-Jeff

Quoted 257 lines
Quoted 54 lines
qgroup.c +11 -21
+
+static int __qgroups_search(int fd, struct btrfs_ioctl_search_args *args,
+			    struct qgroup_lookup *qgroup_lookup)
 {
 	int ret;
-	struct btrfs_ioctl_search_args args;
-	struct btrfs_ioctl_search_key *sk = &args.key;
+	struct btrfs_ioctl_search_key *sk = &args->key;
+	struct btrfs_ioctl_search_key filter_key = args->key;
 	struct btrfs_ioctl_search_header *sh;
 	unsigned long off = 0;
 	unsigned int i;
@@ -1180,30 +1199,15 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 	u64 qgroupid;
 	u64 qgroupid1;
 
-	memset(&args, 0, sizeof(args));
-
-	sk->tree_id = BTRFS_QUOTA_TREE_OBJECTID;
-	sk->max_type = BTRFS_QGROUP_RELATION_KEY;
-	sk->min_type = BTRFS_QGROUP_STATUS_KEY;
-	sk->max_objectid = (u64)-1;
-	sk->max_offset = (u64)-1;
-	sk->max_transid = (u64)-1;
-	sk->nr_items = 4096;
-
 	qgroup_lookup_init(qgroup_lookup);
 
 	while (1) {
-		ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
+		ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, args);
 		if (ret < 0) {
-			if (errno == ENOENT) {
-				error("can't list qgroups: quotas not enabled");
+			if (errno == ENOENT)
 				ret = -ENOTTY;
-			} else {
-				error("can't list qgroups: %s",
-				       strerror(errno));
+			else
 				ret = -errno;
-			}
-
 			break;
 		}
 
@@ -1217,37 +1221,46 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 		 * read the root_ref item it contains
 		 */
 		for (i = 0; i < sk->nr_items; i++) {
-			sh = (struct btrfs_ioctl_search_header *)(args.buf +
+			struct btrfs_key key;
+
+			sh = (struct btrfs_ioctl_search_header *)(args->buf +

qgroup.c static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) · line 1235

Quoted 10 lines
qgroup.c +6 -1
 								  off);
 			off += sizeof(*sh);
 
-			switch (btrfs_search_header_type(sh)) {
+			key.objectid = btrfs_search_header_objectid(sh);
+			key.type = btrfs_search_header_type(sh);
+			key.offset = btrfs_search_header_offset(sh);
+
+			if (!key_in_range(&key, &filter_key))
+				goto next;

It still looks like that most other qgroup info will get calculated.

Quoted 85 lines
qgroup.c +36 -10
+
+			switch (key.type) {
 			case BTRFS_QGROUP_STATUS_KEY:
 				si = (struct btrfs_qgroup_status_item *)
-				     (args.buf + off);
+				     (args->buf + off);
 				flags = btrfs_stack_qgroup_status_flags(si);
 
 				print_status_flag_warning(flags);
 				break;
 			case BTRFS_QGROUP_INFO_KEY:
-				qgroupid = btrfs_search_header_offset(sh);
+				qgroupid = key.offset;
 				info = (struct btrfs_qgroup_info_item *)
-				       (args.buf + off);
+				       (args->buf + off);
 
 				ret = update_qgroup_info(fd, qgroup_lookup,
 							 qgroupid, info);
 				break;
 			case BTRFS_QGROUP_LIMIT_KEY:
-				qgroupid = btrfs_search_header_offset(sh);
+				qgroupid = key.offset;
 				limit = (struct btrfs_qgroup_limit_item *)
-					(args.buf + off);
+					(args->buf + off);
 
 				ret = update_qgroup_limit(fd, qgroup_lookup,
 							  qgroupid, limit);
 				break;
 			case BTRFS_QGROUP_RELATION_KEY:
-				qgroupid = btrfs_search_header_offset(sh);
-				qgroupid1 = btrfs_search_header_objectid(sh);
+				qgroupid = key.offset;
+				qgroupid1 = key.objectid;
 
 				if (qgroupid < qgroupid1)
 					break;
@@ -1262,15 +1275,16 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 			if (ret)
 				return ret;
 
+next:
 			off += btrfs_search_header_len(sh);
 
 			/*
 			 * record the mins in sk so we can make sure the
 			 * next search doesn't repeat this root
 			 */
-			sk->min_type = btrfs_search_header_type(sh);
-			sk->min_offset = btrfs_search_header_offset(sh);
-			sk->min_objectid = btrfs_search_header_objectid(sh);
+			sk->min_type = key.type;
+			sk->min_offset = key.offset;
+			sk->min_objectid = key.objectid;
 		}
 		sk->nr_items = 4096;
 		/*
@@ -1286,6 +1300,67 @@ static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup)
 	return ret;
 }
 
+static int qgroups_search_all(int fd, struct qgroup_lookup *qgroup_lookup)
+{
+	struct btrfs_ioctl_search_args args = {
+		.key = {
+			.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
+			.max_type = BTRFS_QGROUP_RELATION_KEY,
+			.min_type = BTRFS_QGROUP_STATUS_KEY,
+			.max_objectid = (u64)-1,
+			.max_offset = (u64)-1,
+			.max_transid = (u64)-1,
+			.nr_items = 4096,
+		},
+	};
+	int ret;
+
+	ret = __qgroups_search(fd, &args, qgroup_lookup);
+	if (ret == -ENOTTY)
+		error("can't list qgroups: quotas not enabled");
+	else if (ret < 0)
+		error("can't list qgroups: %s", strerror(-ret));
+	return ret;
+}
+

qgroup.c static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) · line 1335

Quoted 10 lines
qgroup.c +10 -0
+int btrfs_qgroup_query(int fd, u64 qgroupid, struct btrfs_qgroup_stats *stats)
+{
+	struct btrfs_ioctl_search_args args = {
+		.key = {
+			.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
+			.min_type = BTRFS_QGROUP_INFO_KEY,
+			.max_type = BTRFS_QGROUP_LIMIT_KEY,
+			.max_objectid = 0,
+			.min_offset = qgroupid,
+			.max_offset = qgroupid,

Just keep in mind that such search could include unrelated qgroup info into the result, key_in_range() check won't help much due to the limit of how tree search works.

Quoted 5 lines
qgroup.c +5 -0
+			.max_transid = (u64)-1,
+			.nr_items = 4096,
+		},
+	};
+	struct qgroup_lookup qgroup_lookup;

qgroup.c static int __qgroups_search(int fd, struct qgroup_lookup *qgroup_lookup) · line 1350

Quoted 10 lines
qgroup.c +10 -0
+	struct btrfs_qgroup *qgroup;
+	struct rb_node *n;
+	int ret;
+
+	ret = __qgroups_search(fd, &args, &qgroup_lookup);
+	if (ret < 0)
+		return ret;
+
+	ret = -ENODATA;
+	n = rb_first(&qgroup_lookup.root);

And in worst case, if we're query some qgroup which doesn't exist (maybe manually deleted), then due to limit of tree search, @qgroup_lookup could contain unrelated qgroup info.

In that case, rb_first() could gives us some unrelated qgroup.

For example, we have qgroups info for 5, 258, 259, 1/1, and we're trying to query qgroup 257 (deleted manually), then we will get the following result from tree search:

	item 3 key (0 QGROUP_INFO 0/258) itemoff 16131 itemsize 40
	item 4 key (0 QGROUP_INFO 0/259) itemoff 16131 itemsize 40
	item 5 key (0 QGROUP_INFO 1/1) itemoff 16091 itemsize 40
	item 6 key (0 QGROUP_LIMIT 0/5) itemoff 16051 itemsize 40

So in @qgroup_lookup, the first item will be qgroup 258 instead of the non-exist qgroup 257.

Either caller needs extra check or we need to do extra check in this function.

Thanks,
Qu

Quoted 49 lines
qgroup.c +14 -1
+	if (n) {
+		qgroup = rb_entry(n, struct btrfs_qgroup, rb_node);
+		stats->qgroupid = qgroup->qgroupid;
+		stats->info = qgroup->info;
+		stats->limit = qgroup->limit;
+
+		ret = 0;
+	}
+
+	__free_all_qgroups(&qgroup_lookup);
+	return ret;
+}
+
 static void print_all_qgroups(struct qgroup_lookup *qgroup_lookup, bool verbose)
 {
 
@@ -1312,7 +1387,7 @@ int btrfs_show_qgroups(int fd,
 	struct qgroup_lookup sort_tree;
 	int ret;
 
-	ret = __qgroups_search(fd, &qgroup_lookup);
+	ret = qgroups_search_all(fd, &qgroup_lookup);
 	if (ret)
 		return ret;
 	__filter_and_sort_qgroups(&qgroup_lookup, &sort_tree,
qgroup.h +7 -0
index 5e71349c..688f92b2 100644
@@ -87,6 +87,12 @@ struct btrfs_qgroup_info {
 	u64 exclusive_compressed;
 };
 
+struct btrfs_qgroup_stats {
+	u64 qgroupid;
+	struct btrfs_qgroup_info info;
+	struct btrfs_qgroup_limit limit;
+};
+
 int btrfs_qgroup_parse_sort_string(const char *opt_arg,
 				struct btrfs_qgroup_comparer_set **comps);
 int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *,
@@ -105,4 +111,5 @@ int qgroup_inherit_add_group(struct btrfs_qgroup_inherit **inherit, char *arg);
 int qgroup_inherit_add_copy(struct btrfs_qgroup_inherit **inherit, char *arg,
 			    int type);
 
+int btrfs_qgroup_query(int fd, u64 qgroupid, struct btrfs_qgroup_stats *stats);
 #endif
#16 lore raw

PATCH v2 9/20 btrfs-progs: subvolume: add quota info to btrfs sub show

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

This patch reports on the first-level qgroup, if any, associated with a particular subvolume. It displays the usage and limit, subject to the usual unit parameters.

---
 cmds-subvolume.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)
cmds-subvolume.c +50 -0
index 769d2a76..96fb7b06 100644
@@ -972,6 +972,7 @@ static const char * const cmd_subvol_show_usage[] = {
 	"Show more information about the subvolume",
 	"-r|--rootid   rootid of the subvolume",
 	"-u|--uuid     uuid of the subvolume",
+	HELPINFO_UNITS_SHORT_LONG,
 	"",
 	"If no option is specified, <subvol-path> will be shown, otherwise",
 	"the rootid or uuid are resolved relative to the <mnt> path.",
@@ -993,6 +994,13 @@ static int cmd_subvol_show(int argc, char **argv)
 	int by_uuid = 0;
 	u64 rootid_arg;
 	u8 uuid_arg[BTRFS_UUID_SIZE];
+	struct btrfs_qgroup_stats stats;
+	unsigned int unit_mode;
+	const char *referenced_size;
+	const char *referenced_limit_size = "-";
+	unsigned int field_width = 0;
+
+	unit_mode = get_unit_mode_from_arg(&argc, argv, 1);
 
 	while (1) {
 		int c;
@@ -1112,6 +1120,48 @@ static int cmd_subvol_show(int argc, char **argv)
 	btrfs_list_subvols_print(fd, filter_set, NULL, BTRFS_LIST_LAYOUT_RAW,
 			1, raw_prefix);
 
+	ret = btrfs_qgroup_query(fd, get_ri.root_id, &stats);
+	if (ret && ret != -ENOTTY && ret != -ENODATA) {
+		fprintf(stderr,
+			"\nERROR: BTRFS_IOC_QUOTA_QUERY failed: %s\n",
+			strerror(-ret));
+		goto out;
+	}
+
+	printf("\tQuota Usage:\t\t");
+	fflush(stdout);
+	if (ret) {
+		if (ret == -ENOTTY)
+			printf("quotas not enabled\n");
+		else
+			printf("quotas not available\n");
+		goto out;
+	}
+
+	referenced_size = pretty_size_mode(stats.info.referenced, unit_mode);
+	if (stats.limit.max_referenced)
+		referenced_limit_size = pretty_size_mode(
+						stats.limit.max_referenced,
+						unit_mode);
+	field_width = max(strlen(referenced_size),
+			  strlen(referenced_limit_size));
+
+	printf("%-*s referenced, %s exclusive\n ", field_width,
+	       referenced_size,
+	       pretty_size_mode(stats.info.exclusive, unit_mode));
+
+	printf("\tQuota Limits:\t\t");
+	if (stats.limit.max_referenced || stats.limit.max_exclusive) {
+		const char *excl = "-";
+
+		if (stats.limit.max_exclusive)
+			excl = pretty_size_mode(stats.limit.max_exclusive,
+						unit_mode);
+		printf("%-*s referenced, %s exclusive\n", field_width,
+		       referenced_limit_size, excl);
+	} else
+		printf("None\n");
+
 out:
 	btrfs_cleanup_root_info(&get_ri);
 	free(filter_set);
Signature · 1 line
2.12.3
#17 lore raw

PATCH v2 10/20 btrfs-progs: help: convert ints used as bools to bool

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

We use an int for 'full', 'all', and 'err' when we really mean a boolean.

---
 btrfs.c | 14 +++++++-------
 help.c  | 25 +++++++++++++------------
 help.h  |  4 ++--
 3 files changed, 22 insertions(+), 21 deletions(-)
btrfs.c +7 -7
index 2d39f2ce..fec1a135 100644
@@ -109,7 +109,7 @@ static void handle_help_options_next_level(const struct cmd_struct *cmd,
 			argv++;
 			help_command_group(cmd->next, argc, argv);
 		} else {
-			usage_command(cmd, 1, 0);
+			usage_command(cmd, true, false);
 		}
 
 		exit(0);
@@ -125,7 +125,7 @@ int handle_command_group(const struct cmd_group *grp, int argc,
 	argc--;
 	argv++;
 	if (argc < 1) {
-		usage_command_group(grp, 0, 0);
+		usage_command_group(grp, false, false);
 		exit(1);
 	}
 
@@ -212,20 +212,20 @@ static int handle_global_options(int argc, char **argv)
 
 void handle_special_globals(int shift, int argc, char **argv)
 {
-	int has_help = 0;
-	int has_full = 0;
+	bool has_help = false;
+	bool has_full = false;
 	int i;
 
 	for (i = 0; i < shift; i++) {
 		if (strcmp(argv[i], "--help") == 0)
-			has_help = 1;
+			has_help = true;
 		else if (strcmp(argv[i], "--full") == 0)
-			has_full = 1;
+			has_full = true;
 	}
 
 	if (has_help) {
 		if (has_full)
-			usage_command_group(&btrfs_cmd_group, 1, 0);
+			usage_command_group(&btrfs_cmd_group, true, false);
 		else
 			cmd_help(argc, argv);
 		exit(0);
help.c +13 -12
index 311a4320..ef7986b4 100644
@@ -196,8 +196,8 @@ static int do_usage_one_command(const char * const *usagestr,
 }
 
 static int usage_command_internal(const char * const *usagestr,
-				  const char *token, int full, int lst,
-				  int alias, FILE *outf)
+				  const char *token, bool full, bool lst,
+				  bool alias, FILE *outf)
 {
 	unsigned int flags = 0;
 	int ret;
@@ -223,17 +223,17 @@ static int usage_command_internal(const char * const *usagestr,
 }
 
 static void usage_command_usagestr(const char * const *usagestr,
-				   const char *token, int full, int err)
+				   const char *token, bool full, bool err)
 {
 	FILE *outf = err ? stderr : stdout;
 	int ret;
 
-	ret = usage_command_internal(usagestr, token, full, 0, 0, outf);
+	ret = usage_command_internal(usagestr, token, full, false, false, outf);
 	if (!ret)
 		fputc('\n', outf);
 }
 
-void usage_command(const struct cmd_struct *cmd, int full, int err)
+void usage_command(const struct cmd_struct *cmd, bool full, bool err)
 {
 	usage_command_usagestr(cmd->usagestr, cmd->token, full, err);
 }
@@ -241,11 +241,11 @@ void usage_command(const struct cmd_struct *cmd, int full, int err)
 __attribute__((noreturn))
 void usage(const char * const *usagestr)
 {
-	usage_command_usagestr(usagestr, NULL, 1, 1);
+	usage_command_usagestr(usagestr, NULL, true, true);
 	exit(1);
 }
 
-static void usage_command_group_internal(const struct cmd_group *grp, int full,
+static void usage_command_group_internal(const struct cmd_group *grp, bool full,
 					 FILE *outf)
 {
 	const struct cmd_struct *cmd = grp->commands;
@@ -265,7 +265,8 @@ static void usage_command_group_internal(const struct cmd_group *grp, int full,
 			}
 
 			usage_command_internal(cmd->usagestr, cmd->token, full,
-					       1, cmd->flags & CMD_ALIAS, outf);
+					       true, cmd->flags & CMD_ALIAS,
+					       outf);
 			if (cmd->flags & CMD_ALIAS)
 				putchar('\n');
 			continue;
@@ -327,7 +328,7 @@ void usage_command_group_short(const struct cmd_group *grp)
 	fprintf(stderr, "All command groups have their manual page named 'btrfs-<group>'.\n");
 }
 
-void usage_command_group(const struct cmd_group *grp, int full, int err)
+void usage_command_group(const struct cmd_group *grp, bool full, bool err)
 {
 	const char * const *usagestr = grp->usagestr;
 	FILE *outf = err ? stderr : stdout;
@@ -350,7 +351,7 @@ __attribute__((noreturn))
 void help_unknown_token(const char *arg, const struct cmd_group *grp)
 {
 	fprintf(stderr, "%s: unknown token '%s'\n", get_argv0_buf(), arg);
-	usage_command_group(grp, 0, 1);
+	usage_command_group(grp, false, true);
 	exit(1);
 }
 
@@ -372,13 +373,13 @@ void help_ambiguous_token(const char *arg, const struct cmd_group *grp)
 
 void help_command_group(const struct cmd_group *grp, int argc, char **argv)
 {
-	int full = 0;
+	bool full = false;
 
 	if (argc > 1) {
 		if (!strcmp(argv[1], "--full"))
 			full = 1;
 	}
 
-	usage_command_group(grp, full, 0);
+	usage_command_group(grp, full, false);
 }
 
help.h +2 -2
index efeded30..a69ea6b2 100644
@@ -57,8 +57,8 @@ struct cmd_group;
 
 __attribute__((noreturn))
 void usage(const char * const *usagestr);
-void usage_command(const struct cmd_struct *cmd, int full, int err);
-void usage_command_group(const struct cmd_group *grp, int all, int err);
+void usage_command(const struct cmd_struct *cmd, bool full, bool err);
+void usage_command_group(const struct cmd_group *grp, bool all, bool err);
 void usage_command_group_short(const struct cmd_group *grp);
 
 __attribute__((noreturn))
Signature · 1 line
2.12.3
Reviewed-by on v2 10/20
#18 lore raw

Re: [PATCH 10/20] btrfs-progs: help: convert ints used as bools to bool

Quoted 5 lines · On 2018年03月08日 10:40, [email protected] wrote:

From: Jeff Mahoney <[email protected]>

We use an int for 'full', 'all', and 'err' when we really mean a boolean.

Thanks,
Qu

Quoted 164 lines
---
 btrfs.c | 14 +++++++-------
 help.c  | 25 +++++++++++++------------
 help.h  |  4 ++--
 3 files changed, 22 insertions(+), 21 deletions(-)
btrfs.c +7 -7
index 2d39f2ce..fec1a135 100644
@@ -109,7 +109,7 @@ static void handle_help_options_next_level(const struct cmd_struct *cmd,
 			argv++;
 			help_command_group(cmd->next, argc, argv);
 		} else {
-			usage_command(cmd, 1, 0);
+			usage_command(cmd, true, false);
 		}
 
 		exit(0);
@@ -125,7 +125,7 @@ int handle_command_group(const struct cmd_group *grp, int argc,
 	argc--;
 	argv++;
 	if (argc < 1) {
-		usage_command_group(grp, 0, 0);
+		usage_command_group(grp, false, false);
 		exit(1);
 	}
 
@@ -212,20 +212,20 @@ static int handle_global_options(int argc, char **argv)
 
 void handle_special_globals(int shift, int argc, char **argv)
 {
-	int has_help = 0;
-	int has_full = 0;
+	bool has_help = false;
+	bool has_full = false;
 	int i;
 
 	for (i = 0; i < shift; i++) {
 		if (strcmp(argv[i], "--help") == 0)
-			has_help = 1;
+			has_help = true;
 		else if (strcmp(argv[i], "--full") == 0)
-			has_full = 1;
+			has_full = true;
 	}
 
 	if (has_help) {
 		if (has_full)
-			usage_command_group(&btrfs_cmd_group, 1, 0);
+			usage_command_group(&btrfs_cmd_group, true, false);
 		else
 			cmd_help(argc, argv);
 		exit(0);
help.c +13 -12
index 311a4320..ef7986b4 100644
@@ -196,8 +196,8 @@ static int do_usage_one_command(const char * const *usagestr,
 }
 
 static int usage_command_internal(const char * const *usagestr,
-				  const char *token, int full, int lst,
-				  int alias, FILE *outf)
+				  const char *token, bool full, bool lst,
+				  bool alias, FILE *outf)
 {
 	unsigned int flags = 0;
 	int ret;
@@ -223,17 +223,17 @@ static int usage_command_internal(const char * const *usagestr,
 }
 
 static void usage_command_usagestr(const char * const *usagestr,
-				   const char *token, int full, int err)
+				   const char *token, bool full, bool err)
 {
 	FILE *outf = err ? stderr : stdout;
 	int ret;
 
-	ret = usage_command_internal(usagestr, token, full, 0, 0, outf);
+	ret = usage_command_internal(usagestr, token, full, false, false, outf);
 	if (!ret)
 		fputc('\n', outf);
 }
 
-void usage_command(const struct cmd_struct *cmd, int full, int err)
+void usage_command(const struct cmd_struct *cmd, bool full, bool err)
 {
 	usage_command_usagestr(cmd->usagestr, cmd->token, full, err);
 }
@@ -241,11 +241,11 @@ void usage_command(const struct cmd_struct *cmd, int full, int err)
 __attribute__((noreturn))
 void usage(const char * const *usagestr)
 {
-	usage_command_usagestr(usagestr, NULL, 1, 1);
+	usage_command_usagestr(usagestr, NULL, true, true);
 	exit(1);
 }
 
-static void usage_command_group_internal(const struct cmd_group *grp, int full,
+static void usage_command_group_internal(const struct cmd_group *grp, bool full,
 					 FILE *outf)
 {
 	const struct cmd_struct *cmd = grp->commands;
@@ -265,7 +265,8 @@ static void usage_command_group_internal(const struct cmd_group *grp, int full,
 			}
 
 			usage_command_internal(cmd->usagestr, cmd->token, full,
-					       1, cmd->flags & CMD_ALIAS, outf);
+					       true, cmd->flags & CMD_ALIAS,
+					       outf);
 			if (cmd->flags & CMD_ALIAS)
 				putchar('\n');
 			continue;
@@ -327,7 +328,7 @@ void usage_command_group_short(const struct cmd_group *grp)
 	fprintf(stderr, "All command groups have their manual page named 'btrfs-<group>'.\n");
 }
 
-void usage_command_group(const struct cmd_group *grp, int full, int err)
+void usage_command_group(const struct cmd_group *grp, bool full, bool err)
 {
 	const char * const *usagestr = grp->usagestr;
 	FILE *outf = err ? stderr : stdout;
@@ -350,7 +351,7 @@ __attribute__((noreturn))
 void help_unknown_token(const char *arg, const struct cmd_group *grp)
 {
 	fprintf(stderr, "%s: unknown token '%s'\n", get_argv0_buf(), arg);
-	usage_command_group(grp, 0, 1);
+	usage_command_group(grp, false, true);
 	exit(1);
 }
 
@@ -372,13 +373,13 @@ void help_ambiguous_token(const char *arg, const struct cmd_group *grp)
 
 void help_command_group(const struct cmd_group *grp, int argc, char **argv)
 {
-	int full = 0;
+	bool full = false;
 
 	if (argc > 1) {
 		if (!strcmp(argv[1], "--full"))
 			full = 1;
 	}
 
-	usage_command_group(grp, full, 0);
+	usage_command_group(grp, full, false);
 }
 
help.h +2 -2
index efeded30..a69ea6b2 100644
@@ -57,8 +57,8 @@ struct cmd_group;
 
 __attribute__((noreturn))
 void usage(const char * const *usagestr);
-void usage_command(const struct cmd_struct *cmd, int full, int err);
-void usage_command_group(const struct cmd_group *grp, int all, int err);
+void usage_command(const struct cmd_struct *cmd, bool full, bool err);
+void usage_command_group(const struct cmd_group *grp, bool all, bool err);
 void usage_command_group_short(const struct cmd_group *grp);
 
 __attribute__((noreturn))
#19 lore raw

PATCH v2 11/20 btrfs-progs: reorder placement of help declarations for send/receive

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

The usage definitions for send and receive follow the command definitions, which use them. This works because we declare them in commands.h. When we move to using cmd_struct as the entry point, these declarations will be removed, breaking the commands. Since that would be an otherwise unrelated change, this patch reorders them separately.

---
 cmds-receive.c | 62 ++++++++++++++++++++++++++--------------------------
 cmds-send.c    | 69 +++++++++++++++++++++++++++++-----------------------------
 2 files changed, 66 insertions(+), 65 deletions(-)
cmds-receive.c +31 -31
index 68123a31..b3709f36 100644
@@ -1248,6 +1248,37 @@ out:
 	return ret;
 }
 
+const char * const cmd_receive_usage[] = {
+	"btrfs receive [options] <mount>\n"
+	"btrfs receive --dump [options]",
+	"Receive subvolumes from a stream",
+	"Receives one or more subvolumes that were previously",
+	"sent with btrfs send. The received subvolumes are stored",
+	"into MOUNT.",
+	"The receive will fail in case the receiving subvolume",
+	"already exists. It will also fail in case a previously",
+	"received subvolume has been changed after it was received.",
+	"After receiving a subvolume, it is immediately set to",
+	"read-only.",
+	"",
+	"-v               increase verbosity about performed actions",
+	"-f FILE          read the stream from FILE instead of stdin",
+	"-e               terminate after receiving an <end cmd> marker in the stream.",
+	"                 Without this option the receiver side terminates only in case",
+	"                 of an error on end of file.",
+	"-C|--chroot      confine the process to <mount> using chroot",
+	"-E|--max-errors NERR",
+	"                 terminate as soon as NERR errors occur while",
+	"                 stream processing commands from the stream.",
+	"                 Default value is 1. A value of 0 means no limit.",
+	"-m ROOTMOUNT     the root mount point of the destination filesystem.",
+	"                 If /proc is not accessible, use this to tell us where",
+	"                 this file system is mounted.",
+	"--dump           dump stream metadata, one line per operation,",
+	"                 does not require the MOUNT parameter",
+	NULL
+};
+
 int cmd_receive(int argc, char **argv)
 {
 	char *tomnt = NULL;
@@ -1357,34 +1388,3 @@ out:
 
 	return !!ret;
 }
-
-const char * const cmd_receive_usage[] = {
-	"btrfs receive [options] <mount>\n"
-	"btrfs receive --dump [options]",
-	"Receive subvolumes from a stream",
-	"Receives one or more subvolumes that were previously",
-	"sent with btrfs send. The received subvolumes are stored",
-	"into MOUNT.",
-	"The receive will fail in case the receiving subvolume",
-	"already exists. It will also fail in case a previously",
-	"received subvolume has been changed after it was received.",
-	"After receiving a subvolume, it is immediately set to",
-	"read-only.",
-	"",
-	"-v               increase verbosity about performed actions",
-	"-f FILE          read the stream from FILE instead of stdin",
-	"-e               terminate after receiving an <end cmd> marker in the stream.",
-	"                 Without this option the receiver side terminates only in case",
-	"                 of an error on end of file.",
-	"-C|--chroot      confine the process to <mount> using chroot",
-	"-E|--max-errors NERR",
-	"                 terminate as soon as NERR errors occur while",
-	"                 stream processing commands from the stream.",
-	"                 Default value is 1. A value of 0 means no limit.",
-	"-m ROOTMOUNT     the root mount point of the destination filesystem.",
-	"                 If /proc is not accessible, use this to tell us where",
-	"                 this file system is mounted.",
-	"--dump           dump stream metadata, one line per operation,",
-	"                 does not require the MOUNT parameter",
-	NULL
-};
cmds-send.c +35 -34

78 lines not on this page · raw message

Signature · 1 line
2.12.3
#20 lore raw

PATCH v2 12/20 btrfs-progs: filesystem balance: split out special handling

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

In preparation to use cmd_struct as the command entry point, we need to split out the 'filesystem balance' handling to not call cmd_balance directly. The reason is that the flags that indicate a command is hidden are a part of cmd_struct and so we can use a cmd_struct as a direct alias in another command group and ALSO have it be hidden without declaring another cmd_struct.

This change has no immediate impact since cmd_balance will still use its usage information directly from cmds-balance.c. It will take effect once we start passing cmd_structs around for usage information.

---
 cmds-filesystem.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)
cmds-filesystem.c +15 -2
index 467aff11..62112705 100644
@@ -1184,6 +1184,18 @@ static int cmd_filesystem_label(int argc, char **argv)
 	}
 }
 
+static const char * const cmd_filesystem_balance_usage[] = {
+	"btrfs filesystem balance [args...] (alias of \"btrfs balance\")",
+	"Please see \"btrfs balance --help\" for more information.",
+	NULL
+};
+
+/* Compatible old "btrfs filesystem balance" command */
+static int cmd_filesystem_balance(int argc, char **argv)
+{
+	return cmd_balance(argc, argv);
+}
+
 static const char filesystem_cmd_group_info[] =
 "overall filesystem tasks and information";
 
@@ -1197,8 +1209,9 @@ const struct cmd_group filesystem_cmd_group = {
 			0 },
 		{ "defragment", cmd_filesystem_defrag,
 			cmd_filesystem_defrag_usage, NULL, 0 },
-		{ "balance", cmd_balance, NULL, &balance_cmd_group,
-			CMD_HIDDEN },
+		{ "balance", cmd_filesystem_balance,
+		   cmd_filesystem_balance_usage, &balance_cmd_group,
+		   CMD_HIDDEN },
 		{ "resize", cmd_filesystem_resize, cmd_filesystem_resize_usage,
 			NULL, 0 },
 		{ "label", cmd_filesystem_label, cmd_filesystem_label_usage,
Signature · 1 line
2.12.3
#21 lore raw

PATCH v2 13/20 btrfs-progs: use cmd_struct as command entry point

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

Rather than having global command usage and callbacks used to create cmd_structs in the command array, establish the cmd_struct structures separately and use those. The next commit in the series passes the cmd_struct to the command callbacks such that we can access flags and determine which of several potential command we were called as.

This establishes several macros to more easily define the commands within each command's source.

---
 btrfs-calc-size.c         |   5 +-
 btrfs-debug-tree.c        |   5 +-
 btrfs-show-super.c        |   6 +--
 btrfs.c                   |  48 ++++++++++--------
 check/main.c              |   5 +-
 cmds-balance.c            |  27 ++++++----
 cmds-device.c             |  31 ++++++-----
 cmds-fi-du.c              |   5 +-
 cmds-fi-usage.c           |   5 +-
 cmds-filesystem.c         |  52 ++++++++++---------
 cmds-inspect-dump-super.c |   5 +-
 cmds-inspect-dump-tree.c  |   5 +-
 cmds-inspect-tree-stats.c |   5 +-
 cmds-inspect.c            |  36 +++++++------
 cmds-property.c           |  19 +++----
 cmds-qgroup.c             |  31 +++++------
 cmds-quota.c              |  17 ++++---
 cmds-receive.c            |   5 +-
 cmds-replace.c            |  19 +++----
 cmds-rescue.c             |  22 ++++----
 cmds-restore.c            |   5 +-
 cmds-scrub.c              |  20 +++++---
 cmds-send.c               |   6 +--
 cmds-subvolume.c          |  38 ++++++++------
 commands.h                | 127 +++++++++++++++++++++++++++-------------------
 help.c                    |  21 +++++---
 26 files changed, 326 insertions(+), 244 deletions(-)
btrfs-calc-size.c +3 -2
index d2d68ab2..908e830f 100644
@@ -23,15 +23,16 @@
 
 int main(int argc, char **argv)
 {
+	const struct cmd_struct *cmd = &cmd_struct_inspect_tree_stats;
 	int ret;
 
 	warning(
 "\nthe tool has been deprecated, please use 'btrfs inspect-internal tree-stats' instead\n");
 
 	if (argc > 1 && !strcmp(argv[1], "--help"))
-		usage(cmd_inspect_tree_stats_usage);
+		usage(cmd->usagestr);
 
-	ret = cmd_inspect_tree_stats(argc, argv);
+	ret = cmd_execute(cmd, argc, argv);
 
 	btrfs_close_all_devices();
 
btrfs-debug-tree.c +3 -2
index 7bee018f..7f254519 100644
@@ -24,16 +24,17 @@
 
 int main(int argc, char **argv)
 {
+	const struct cmd_struct *cmd = &cmd_struct_inspect_dump_tree;
 	int ret;
 
 	set_argv0(argv);
 
 	if (argc > 1 && !strcmp(argv[1], "--help"))
-		usage(cmd_inspect_dump_tree_usage);
+		usage(cmd->usagestr);
 
 	radix_tree_init();
 
-	ret = cmd_inspect_dump_tree(argc, argv);
+	ret = cmd_execute(cmd, argc, argv);
 
 	btrfs_close_all_devices();
 
btrfs-show-super.c +3 -3
index 4273e42d..ee717c33 100644
@@ -22,7 +22,7 @@
 
 int main(int argc, char **argv)
 {
-
+	const struct cmd_struct *cmd = &cmd_struct_inspect_dump_super;
 	int ret;
 
 	set_argv0(argv);
@@ -31,9 +31,9 @@ int main(int argc, char **argv)
 "\nthe tool has been deprecated, please use 'btrfs inspect-internal dump-super' instead\n");
 
 	if (argc > 1 && !strcmp(argv[1], "--help"))
-		usage(cmd_inspect_dump_super_usage);
+		usage(cmd->usagestr);
 
-	ret = cmd_inspect_dump_super(argc, argv);
+	ret = cmd_execute(cmd, argc, argv);
 
 	return ret;
 }
btrfs.c +26 -22

86 lines not on this page · raw message

check/main.c +3 -2
index 97baae58..4b8f7678 100644
@@ -9408,7 +9408,7 @@ close_out:
 	return ret;
 }
 
-const char * const cmd_check_usage[] = {
+static const char * const cmd_check_usage[] = {
 	"btrfs check [options] <device>",
 	"Check structural integrity of a filesystem (unmounted).",
 	"Check structural integrity of an unmounted filesystem. Verify internal",
@@ -9440,7 +9440,7 @@ const char * const cmd_check_usage[] = {
 	NULL
 };
 
-int cmd_check(int argc, char **argv)
+static int cmd_check(int argc, char **argv)
 {
 	struct cache_tree root_cache;
 	struct btrfs_root *root;
@@ -9930,3 +9930,4 @@ err_out:
 
 	return err;
 }
+DEFINE_SIMPLE_COMMAND(check, "check");
cmds-balance.c +18 -9
index 0c91bdf1..7a60be61 100644
@@ -672,6 +672,7 @@ static int cmd_balance_start(int argc, char **argv)
 
 	return do_balance(argv[optind], &args, start_flags);
 }
+static DEFINE_SIMPLE_COMMAND(balance_start, "start");
 
 static const char * const cmd_balance_pause_usage[] = {
 	"btrfs balance pause <path>",
@@ -710,6 +711,7 @@ static int cmd_balance_pause(int argc, char **argv)
 	close_file_or_dir(fd, dirstream);
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(balance_pause, "pause");
 
 static const char * const cmd_balance_cancel_usage[] = {
 	"btrfs balance cancel <path>",
@@ -748,6 +750,7 @@ static int cmd_balance_cancel(int argc, char **argv)
 	close_file_or_dir(fd, dirstream);
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(balance_cancel, "cancel");
 
 static const char * const cmd_balance_resume_usage[] = {
 	"btrfs balance resume <path>",
@@ -807,6 +810,7 @@ static int cmd_balance_resume(int argc, char **argv)
 	close_file_or_dir(fd, dirstream);
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(balance_resume, "resume");
 
 static const char * const cmd_balance_status_usage[] = {
 	"btrfs balance status [-v] <path>",
@@ -898,6 +902,7 @@ out:
 	close_file_or_dir(fd, dirstream);
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(balance_status, "status");
 
 static int cmd_balance_full(int argc, char **argv)
 {
@@ -908,23 +913,25 @@ static int cmd_balance_full(int argc, char **argv)
 
 	return do_balance(argv[1], &args, BALANCE_START_NOWARN);
 }
+static DEFINE_COMMAND(balance_full, "--full-balance", cmd_balance_full,
+		      NULL, NULL, CMD_HIDDEN);
 
 static const char balance_cmd_group_info[] =
 "balance data across devices, or change block groups using filters";
 
-const struct cmd_group balance_cmd_group = {
+static const struct cmd_group balance_cmd_group = {
 	balance_cmd_group_usage, balance_cmd_group_info, {
-		{ "start", cmd_balance_start, cmd_balance_start_usage, NULL, 0 },
-		{ "pause", cmd_balance_pause, cmd_balance_pause_usage, NULL, 0 },
-		{ "cancel", cmd_balance_cancel, cmd_balance_cancel_usage, NULL, 0 },
-		{ "resume", cmd_balance_resume, cmd_balance_resume_usage, NULL, 0 },
-		{ "status", cmd_balance_status, cmd_balance_status_usage, NULL, 0 },
-		{ "--full-balance", cmd_balance_full, NULL, NULL, 1 },
-		NULL_CMD_STRUCT
+		&cmd_struct_balance_start,
+		&cmd_struct_balance_pause,
+		&cmd_struct_balance_cancel,
+		&cmd_struct_balance_resume,
+		&cmd_struct_balance_status,
+		&cmd_struct_balance_full,
+		NULL
 	}
 };
 
-int cmd_balance(int argc, char **argv)
+static int cmd_balance(int argc, char **argv)
 {
 	if (argc == 2 && strcmp("start", argv[1]) != 0) {
 		/* old 'btrfs filesystem balance <path>' syntax */
@@ -938,3 +945,5 @@ int cmd_balance(int argc, char **argv)
 
 	return handle_command_group(&balance_cmd_group, argc, argv);
 }
+
+DEFINE_GROUP_COMMAND(balance, "balance");
cmds-device.c +19 -12
index a49c9d9d..96764d6c 100644
@@ -140,6 +140,7 @@ error_out:
 	close_file_or_dir(fdmnt, dirstream);
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(device_add, "add");
 
 static int _cmd_device_remove(int argc, char **argv,
 		const char * const *usagestr)
@@ -239,6 +240,7 @@ static int cmd_device_remove(int argc, char **argv)
 {
 	return _cmd_device_remove(argc, argv, cmd_device_remove_usage);
 }
+static DEFINE_SIMPLE_COMMAND(device_remove, "remove");
 
 static const char * const cmd_device_delete_usage[] = {
 	"btrfs device delete <device>|<devid> [<device>|<devid>...] <path>",
@@ -252,6 +254,8 @@ static int cmd_device_delete(int argc, char **argv)
 {
 	return _cmd_device_remove(argc, argv, cmd_device_delete_usage);
 }
+static DEFINE_COMMAND(device_delete, "delete", cmd_device_delete,
+		      cmd_device_delete_usage, NULL, CMD_ALIAS);
 
 static const char * const cmd_device_scan_usage[] = {
 	"btrfs device scan [(-d|--all-devices)|<device> [<device>...]]",
@@ -325,6 +329,7 @@ static int cmd_device_scan(int argc, char **argv)
 out:
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(device_scan, "scan");
 
 static const char * const cmd_device_ready_usage[] = {
 	"btrfs device ready <device>",
@@ -378,6 +383,7 @@ out:
 	close(fd);
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(device_ready, "ready");
 
 static const char * const cmd_device_stats_usage[] = {
 	"btrfs device stats [options] <path>|<device>",
@@ -518,6 +524,7 @@ out:
 
 	return err;
 }
+static DEFINE_SIMPLE_COMMAND(device_stats, "stats");
 
 static const char * const cmd_device_usage_usage[] = {
 	"btrfs device usage [options] <path> [<path>..]",
@@ -590,26 +597,26 @@ static int cmd_device_usage(int argc, char **argv)
 
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(device_usage, "usage");
 
 static const char device_cmd_group_info[] =
 "manage and query devices in the filesystem";
 
-const struct cmd_group device_cmd_group = {
+static const struct cmd_group device_cmd_group = {
 	device_cmd_group_usage, device_cmd_group_info, {
-		{ "add", cmd_device_add, cmd_device_add_usage, NULL, 0 },
-		{ "delete", cmd_device_delete, cmd_device_delete_usage, NULL,
-			CMD_ALIAS },
-		{ "remove", cmd_device_remove, cmd_device_remove_usage, NULL, 0 },
-		{ "scan", cmd_device_scan, cmd_device_scan_usage, NULL, 0 },
-		{ "ready", cmd_device_ready, cmd_device_ready_usage, NULL, 0 },
-		{ "stats", cmd_device_stats, cmd_device_stats_usage, NULL, 0 },
-		{ "usage", cmd_device_usage,
-			cmd_device_usage_usage, NULL, 0 },
-		NULL_CMD_STRUCT
+		&cmd_struct_device_add,
+		&cmd_struct_device_delete,
+		&cmd_struct_device_remove,
+		&cmd_struct_device_scan,
+		&cmd_struct_device_ready,
+		&cmd_struct_device_stats,
+		&cmd_struct_device_usage,
+		NULL
 	}
 };
 
-int cmd_device(int argc, char **argv)
+static int cmd_device(int argc, char **argv)
 {
 	return handle_command_group(&device_cmd_group, argc, argv);
 }
+DEFINE_GROUP_COMMAND_TOKEN(device);
cmds-fi-du.c +3 -2
index 8a44665c..cb2f09c7 100644
@@ -549,7 +549,7 @@ out:
 	return ret;
 }
 
-const char * const cmd_filesystem_du_usage[] = {
+static const char * const cmd_filesystem_du_usage[] = {
 	"btrfs filesystem du [options] <path> [<path>..]",
 	"Summarize disk usage of each file.",
 	"-s|--summarize     display only a total for each argument",
@@ -557,7 +557,7 @@ const char * const cmd_filesystem_du_usage[] = {
 	NULL
 };
 
-int cmd_filesystem_du(int argc, char **argv)
+static int cmd_filesystem_du(int argc, char **argv)
 {
 	int ret = 0, err = 0;
 	int i;
@@ -611,3 +611,4 @@ int cmd_filesystem_du(int argc, char **argv)
 
 	return err;
 }
+DEFINE_SIMPLE_COMMAND(filesystem_du, "du");
cmds-fi-usage.c +3 -2
index 9a1c76ab..af882400 100644
@@ -957,7 +957,7 @@ out:
 	return ret;
 }
 
-const char * const cmd_filesystem_usage_usage[] = {
+static const char * const cmd_filesystem_usage_usage[] = {
 	"btrfs filesystem usage [options] <path> [<path>..]",
 	"Show detailed information about internal filesystem usage .",
 	HELPINFO_UNITS_SHORT_LONG,
@@ -965,7 +965,7 @@ const char * const cmd_filesystem_usage_usage[] = {
 	NULL
 };
 
-int cmd_filesystem_usage(int argc, char **argv)
+static int cmd_filesystem_usage(int argc, char **argv)
 {
 	int ret = 0;
 	unsigned unit_mode;
@@ -1035,6 +1035,7 @@ cleanup:
 out:
 	return !!ret;
 }
+DEFINE_SIMPLE_COMMAND(filesystem_usage, "usage");
 
 void print_device_chunks(struct device_info *devinfo,
 		struct chunk_info *chunks_info_ptr,
cmds-filesystem.c +29 -23

105 lines not on this page · raw message

cmds-inspect-dump-super.c +3 -2
index 150c2e5a..34542d71 100644
@@ -486,7 +486,7 @@ static int load_and_dump_sb(char *filename, int fd, u64 sb_bytenr, int full,
 	return 0;
 }
 
-const char * const cmd_inspect_dump_super_usage[] = {
+static const char * const cmd_inspect_dump_super_usage[] = {
 	"btrfs inspect-internal dump-super [options] device [device...]",
 	"Dump superblock from a device in a textual form",
 	"-f|--full             print full superblock information, backup roots etc.",
@@ -504,7 +504,7 @@ const char * const cmd_inspect_dump_super_usage[] = {
 	NULL
 };
 
-int cmd_inspect_dump_super(int argc, char **argv)
+static int cmd_inspect_dump_super(int argc, char **argv)
 {
 	int all = 0;
 	int full = 0;
@@ -612,3 +612,4 @@ int cmd_inspect_dump_super(int argc, char **argv)
 out:
 	return ret;
 }
+DEFINE_SIMPLE_COMMAND(inspect_dump_super, "dump-super");
cmds-inspect-dump-tree.c +3 -2
index df44bb63..6417eab3 100644
@@ -183,7 +183,7 @@ static u64 treeid_from_string(const char *str, const char **end)
 	return id;
 }
 
-const char * const cmd_inspect_dump_tree_usage[] = {
+static const char * const cmd_inspect_dump_tree_usage[] = {
 	"btrfs inspect-internal dump-tree [options] device",
 	"Dump tree structures from a given device",
 	"Dump tree structures from a given device in textual form, expand keys to human",
@@ -201,7 +201,7 @@ const char * const cmd_inspect_dump_tree_usage[] = {
 	NULL
 };
 
-int cmd_inspect_dump_tree(int argc, char **argv)
+static int cmd_inspect_dump_tree(int argc, char **argv)
 {
 	struct btrfs_root *root;
 	struct btrfs_fs_info *info;
@@ -585,3 +585,4 @@ close_root:
 out:
 	return !!ret;
 }
+DEFINE_SIMPLE_COMMAND(inspect_dump_tree, "dump-tree");
cmds-inspect-tree-stats.c +3 -2
index eced0db9..14d79ccc 100644
@@ -420,14 +420,14 @@ out:
 	return ret;
 }
 
-const char * const cmd_inspect_tree_stats_usage[] = {
+static const char * const cmd_inspect_tree_stats_usage[] = {
 	"btrfs inspect-internal tree-stats [options] <device>",
 	"Print various stats for trees",
 	"-b		raw numbers in bytes",
 	NULL
 };
 
-int cmd_inspect_tree_stats(int argc, char **argv)
+static int cmd_inspect_tree_stats(int argc, char **argv)
 {
 	struct btrfs_key key;
 	struct btrfs_root *root;
@@ -494,3 +494,4 @@ out:
 	close_ctree(root);
 	return ret;
 }
+DEFINE_SIMPLE_COMMAND(inspect_tree_stats, "tree-stats");
cmds-inspect.c +17 -19
index afd7fe48..12f200b3 100644
@@ -121,6 +121,7 @@ static int cmd_inspect_inode_resolve(int argc, char **argv)
 	return !!ret;
 
 }
+static DEFINE_SIMPLE_COMMAND(inspect_inode_resolve, "inode-resolve");
 
 static const char * const cmd_inspect_logical_resolve_usage[] = {
 	"btrfs inspect-internal logical-resolve [-Pv] [-s bufsize] <logical> <path>",
@@ -257,6 +258,7 @@ out:
 	free(inodes);
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(inspect_logical_resolve, "logical-resolve");
 
 static const char * const cmd_inspect_subvolid_resolve_usage[] = {
 	"btrfs inspect-internal subvolid-resolve <subvolid> <path>",
@@ -299,6 +301,7 @@ out:
 	close_file_or_dir(fd, dirstream);
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(inspect_subvolid_resolve, "subvolid-resolve");
 
 static const char* const cmd_inspect_rootid_usage[] = {
 	"btrfs inspect-internal rootid <path>",
@@ -336,6 +339,7 @@ out:
 
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(inspect_rootid, "rootid");
 
 static const char* const cmd_inspect_min_dev_size_usage[] = {
 	"btrfs inspect-internal min-dev-size [options] <path>",
@@ -625,33 +629,27 @@ static int cmd_inspect_min_dev_size(int argc, char **argv)
 out:
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(inspect_min_dev_size, "min-dev-size");
 
 static const char inspect_cmd_group_info[] =
 "query various internal information";
 
-const struct cmd_group inspect_cmd_group = {
+static const struct cmd_group inspect_cmd_group = {
 	inspect_cmd_group_usage, inspect_cmd_group_info, {
-		{ "inode-resolve", cmd_inspect_inode_resolve,
-			cmd_inspect_inode_resolve_usage, NULL, 0 },
-		{ "logical-resolve", cmd_inspect_logical_resolve,
-			cmd_inspect_logical_resolve_usage, NULL, 0 },
-		{ "subvolid-resolve", cmd_inspect_subvolid_resolve,
-			cmd_inspect_subvolid_resolve_usage, NULL, 0 },
-		{ "rootid", cmd_inspect_rootid, cmd_inspect_rootid_usage, NULL,
-			0 },
-		{ "min-dev-size", cmd_inspect_min_dev_size,
-			cmd_inspect_min_dev_size_usage, NULL, 0 },
-		{ "dump-tree", cmd_inspect_dump_tree,
-				cmd_inspect_dump_tree_usage, NULL, 0 },
-		{ "dump-super", cmd_inspect_dump_super,
-				cmd_inspect_dump_super_usage, NULL, 0 },
-		{ "tree-stats", cmd_inspect_tree_stats,
-				cmd_inspect_tree_stats_usage, NULL, 0 },
-		NULL_CMD_STRUCT
+		&cmd_struct_inspect_inode_resolve,
+		&cmd_struct_inspect_logical_resolve,
+		&cmd_struct_inspect_subvolid_resolve,
+		&cmd_struct_inspect_rootid,
+		&cmd_struct_inspect_min_dev_size,
+		&cmd_struct_inspect_dump_tree,
+		&cmd_struct_inspect_dump_super,
+		&cmd_struct_inspect_tree_stats,
+		NULL
 	}
 };
 
-int cmd_inspect(int argc, char **argv)
+static int cmd_inspect(int argc, char **argv)
 {
 	return handle_command_group(&inspect_cmd_group, argc, argv);
 }
+DEFINE_GROUP_COMMAND(inspect, "inspect");
cmds-property.c +10 -9
index 03bafa05..dce1f2a9 100644
@@ -358,6 +358,7 @@ static int cmd_property_get(int argc, char **argv)
 
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(property_get, "get");
 
 static const char * const cmd_property_set_usage[] = {
 	"btrfs property set [-t <type>] <object> <name> <value>",
@@ -382,6 +383,7 @@ static int cmd_property_set(int argc, char **argv)
 
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(property_set, "set");
 
 static const char * const cmd_property_list_usage[] = {
 	"btrfs property list [-t <type>] <object>",
@@ -404,23 +406,22 @@ static int cmd_property_list(int argc, char **argv)
 
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(property_list, "list");
 
 static const char property_cmd_group_info[] =
 "modify properties of filesystem objects";
 
-const struct cmd_group property_cmd_group = {
+static const struct cmd_group property_cmd_group = {
 	property_cmd_group_usage, property_cmd_group_info, {
-		{ "get", cmd_property_get,
-			cmd_property_get_usage, NULL, 0 },
-		{ "set", cmd_property_set,
-			cmd_property_set_usage, NULL, 0 },
-		{ "list", cmd_property_list,
-			cmd_property_list_usage, NULL, 0 },
-		NULL_CMD_STRUCT
+		&cmd_struct_property_get,
+		&cmd_struct_property_set,
+		&cmd_struct_property_list,
+		NULL
 	}
 };
 
-int cmd_property(int argc, char **argv)
+static int cmd_property(int argc, char **argv)
 {
 	return handle_command_group(&property_cmd_group, argc, argv);
 }
+DEFINE_GROUP_COMMAND_TOKEN(property);
cmds-qgroup.c +16 -15
index d704aeaf..6945d160 100644
@@ -219,6 +219,7 @@ static int cmd_qgroup_assign(int argc, char **argv)
 {
 	return _cmd_qgroup_assign(1, argc, argv, cmd_qgroup_assign_usage);
 }
+static DEFINE_SIMPLE_COMMAND(qgroup_assign, "assign");
 
 static const char * const cmd_qgroup_remove_usage[] = {
 	"btrfs qgroup remove <src> <dst> <path>",
@@ -230,6 +231,7 @@ static int cmd_qgroup_remove(int argc, char **argv)
 {
 	return _cmd_qgroup_assign(0, argc, argv, cmd_qgroup_remove_usage);
 }
+static DEFINE_SIMPLE_COMMAND(qgroup_remove, "remove");
 
 static const char * const cmd_qgroup_create_usage[] = {
 	"btrfs qgroup create <qgroupid> <path>",
@@ -249,6 +251,7 @@ static int cmd_qgroup_create(int argc, char **argv)
 		usage(cmd_qgroup_create_usage);
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(qgroup_create, "create");
 
 static const char * const cmd_qgroup_destroy_usage[] = {
 	"btrfs qgroup destroy <qgroupid> <path>",
@@ -268,6 +271,7 @@ static int cmd_qgroup_destroy(int argc, char **argv)
 		usage(cmd_qgroup_destroy_usage);
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(qgroup_destroy, "destroy");
 
 static const char * const cmd_qgroup_show_usage[] = {
 	"btrfs qgroup show [options] <path>",
@@ -414,6 +418,7 @@ static int cmd_qgroup_show(int argc, char **argv)
 out:
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(qgroup_show, "show");
 
 static const char * const cmd_qgroup_limit_usage[] = {
 	"btrfs qgroup limit [options] <size>|none [<qgroupid>] <path>",
@@ -506,29 +511,25 @@ static int cmd_qgroup_limit(int argc, char **argv)
 	}
 	return 0;
 }
+static DEFINE_SIMPLE_COMMAND(qgroup_limit, "limit");
 
 static const char qgroup_cmd_group_info[] =
 "manage quota groups";
 
-const struct cmd_group qgroup_cmd_group = {
+static const struct cmd_group qgroup_cmd_group = {
 	qgroup_cmd_group_usage, qgroup_cmd_group_info, {
-		{ "assign", cmd_qgroup_assign, cmd_qgroup_assign_usage,
-		   NULL, 0 },
-		{ "remove", cmd_qgroup_remove, cmd_qgroup_remove_usage,
-		   NULL, 0 },
-		{ "create", cmd_qgroup_create, cmd_qgroup_create_usage,
-		   NULL, 0 },
-		{ "destroy", cmd_qgroup_destroy, cmd_qgroup_destroy_usage,
-		   NULL, 0 },
-		{ "show", cmd_qgroup_show, cmd_qgroup_show_usage,
-		   NULL, 0 },
-		{ "limit", cmd_qgroup_limit, cmd_qgroup_limit_usage,
-		   NULL, 0 },
-		NULL_CMD_STRUCT
+		&cmd_struct_qgroup_assign,
+		&cmd_struct_qgroup_remove,
+		&cmd_struct_qgroup_create,
+		&cmd_struct_qgroup_destroy,
+		&cmd_struct_qgroup_show,
+		&cmd_struct_qgroup_limit,
+		NULL
 	}
 };
 
-int cmd_qgroup(int argc, char **argv)
+static int cmd_qgroup(int argc, char **argv)
 {
 	return handle_command_group(&qgroup_cmd_group, argc, argv);
 }
+DEFINE_GROUP_COMMAND_TOKEN(qgroup);
cmds-quota.c +10 -7
index 7f933495..5cd5607f 100644
@@ -79,6 +79,7 @@ static int cmd_quota_enable(int argc, char **argv)
 		usage(cmd_quota_enable_usage);
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(quota_enable, "enable");
 
 static const char * const cmd_quota_disable_usage[] = {
 	"btrfs quota disable <path>",
@@ -98,6 +99,7 @@ static int cmd_quota_disable(int argc, char **argv)
 		usage(cmd_quota_disable_usage);
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(quota_disable, "disable");
 
 static const char * const cmd_quota_rescan_usage[] = {
 	"btrfs quota rescan [-sw] <path>",
@@ -197,21 +199,22 @@ static int cmd_quota_rescan(int argc, char **argv)
 	close_file_or_dir(fd, dirstream);
 	return 0;
 }
+static DEFINE_SIMPLE_COMMAND(quota_rescan, "rescan");
 
 static const char quota_cmd_group_info[] =
 "manage filesystem quota settings";
 
-const struct cmd_group quota_cmd_group = {
+static const struct cmd_group quota_cmd_group = {
 	quota_cmd_group_usage, quota_cmd_group_info, {
-		{ "enable", cmd_quota_enable, cmd_quota_enable_usage, NULL, 0 },
-		{ "disable", cmd_quota_disable, cmd_quota_disable_usage,
-		   NULL, 0 },
-		{ "rescan", cmd_quota_rescan, cmd_quota_rescan_usage, NULL, 0 },
-		NULL_CMD_STRUCT
+		&cmd_struct_quota_enable,
+		&cmd_struct_quota_disable,
+		&cmd_struct_quota_rescan,
+		NULL
 	}
 };
 
-int cmd_quota(int argc, char **argv)
+static int cmd_quota(int argc, char **argv)
 {
 	return handle_command_group(&quota_cmd_group, argc, argv);
 }
+DEFINE_GROUP_COMMAND_TOKEN(quota);
cmds-receive.c +3 -2
index b3709f36..d88b8793 100644
@@ -1248,7 +1248,7 @@ out:
 	return ret;
 }
 
-const char * const cmd_receive_usage[] = {
+static const char * const cmd_receive_usage[] = {
 	"btrfs receive [options] <mount>\n"
 	"btrfs receive --dump [options]",
 	"Receive subvolumes from a stream",
@@ -1279,7 +1279,7 @@ const char * const cmd_receive_usage[] = {
 	NULL
 };
 
-int cmd_receive(int argc, char **argv)
+static int cmd_receive(int argc, char **argv)
 {
 	char *tomnt = NULL;
 	char fromfile[PATH_MAX];
@@ -1388,3 +1388,4 @@ out:
 
 	return !!ret;
 }
+DEFINE_SIMPLE_COMMAND(receive, "receive");
cmds-replace.c +10 -9
index 032a44fc..a7379c71 100644
@@ -313,6 +313,7 @@ leave_with_error:
 		close(fddstdev);
 	return 1;
 }
+static DEFINE_SIMPLE_COMMAND(replace_start, "start");
 
 static const char *const cmd_replace_status_usage[] = {
 	"btrfs replace status [-1] <mount_point>",
@@ -356,6 +357,7 @@ static int cmd_replace_status(int argc, char **argv)
 	close_file_or_dir(fd, dirstream);
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(replace_status, "status");
 
 static int print_replace_status(int fd, const char *path, int once)
 {
@@ -538,23 +540,22 @@ static int cmd_replace_cancel(int argc, char **argv)
 	}
 	return 0;
 }
+static DEFINE_SIMPLE_COMMAND(replace_cancel, "cancel");
 
 static const char replace_cmd_group_info[] =
 "replace a device in the filesystem";
 
-const struct cmd_group replace_cmd_group = {
+static const struct cmd_group replace_cmd_group = {
 	replace_cmd_group_usage, replace_cmd_group_info, {
-		{ "start", cmd_replace_start, cmd_replace_start_usage, NULL,
-		  0 },
-		{ "status", cmd_replace_status, cmd_replace_status_usage, NULL,
-		  0 },
-		{ "cancel", cmd_replace_cancel, cmd_replace_cancel_usage, NULL,
-		  0 },
-		NULL_CMD_STRUCT
+		&cmd_struct_replace_start,
+		&cmd_struct_replace_status,
+		&cmd_struct_replace_cancel,
+		NULL
 	}
 };
 
-int cmd_replace(int argc, char **argv)
+static int cmd_replace(int argc, char **argv)
 {
 	return handle_command_group(&replace_cmd_group, argc, argv);
 }
+DEFINE_GROUP_COMMAND_TOKEN(replace);
cmds-rescue.c +12 -10
index c61145bc..e3611f2f 100644
@@ -94,6 +94,7 @@ static int cmd_rescue_chunk_recover(int argc, char *argv[])
 	}
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(rescue_chunk_recover, "chunk-recover");
 
 static const char * const cmd_rescue_super_recover_usage[] = {
 	"btrfs rescue super-recover [options] <device>",
@@ -149,6 +150,7 @@ static int cmd_rescue_super_recover(int argc, char **argv)
 	ret = btrfs_recover_superblocks(dname, verbose, yes);
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(rescue_super_recover, "super-recover");
 
 static const char * const cmd_rescue_zero_log_usage[] = {
 	"btrfs rescue zero-log <device>",
@@ -202,6 +204,7 @@ static int cmd_rescue_zero_log(int argc, char **argv)
 out:
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(rescue_zero_log, "zero-log");
 
 static const char * const cmd_rescue_fix_device_size_usage[] = {
 	"btrfs rescue fix-device-size <device>",
@@ -247,24 +250,23 @@ static int cmd_rescue_fix_device_size(int argc, char **argv)
 out:
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(rescue_fix_device_size, "fix-device-size");
 
 static const char rescue_cmd_group_info[] =
 "toolbox for specific rescue operations";
 
-const struct cmd_group rescue_cmd_group = {
+static const struct cmd_group rescue_cmd_group = {
 	rescue_cmd_group_usage, rescue_cmd_group_info, {
-		{ "chunk-recover", cmd_rescue_chunk_recover,
-			cmd_rescue_chunk_recover_usage, NULL, 0},
-		{ "super-recover", cmd_rescue_super_recover,
-			cmd_rescue_super_recover_usage, NULL, 0},
-		{ "zero-log", cmd_rescue_zero_log, cmd_rescue_zero_log_usage, NULL, 0},
-		{ "fix-device-size", cmd_rescue_fix_device_size,
-			cmd_rescue_fix_device_size_usage, NULL, 0},
-		NULL_CMD_STRUCT
+		&cmd_struct_rescue_chunk_recover,
+		&cmd_struct_rescue_super_recover,
+		&cmd_struct_rescue_zero_log,
+		&cmd_struct_rescue_fix_device_size,
+		NULL
 	}
 };
 
-int cmd_rescue(int argc, char **argv)
+static int cmd_rescue(int argc, char **argv)
 {
 	return handle_command_group(&rescue_cmd_group, argc, argv);
 }
+DEFINE_GROUP_COMMAND_TOKEN(rescue);
cmds-restore.c +3 -2
index ade35f0f..05fd1c80 100644
@@ -1389,7 +1389,7 @@ out:
 	return ret;
 }
 
-const char * const cmd_restore_usage[] = {
+static const char * const cmd_restore_usage[] = {
 	"btrfs restore [options] <device> <path> | -l <device>",
 	"Try to restore files from a damaged filesystem (unmounted)",
 	"",
@@ -1415,7 +1415,7 @@ const char * const cmd_restore_usage[] = {
 	NULL
 };
 
-int cmd_restore(int argc, char **argv)
+static int cmd_restore(int argc, char **argv)
 {
 	struct btrfs_root *root;
 	struct btrfs_key key;
@@ -1621,3 +1621,4 @@ out:
 	close_ctree(root);
 	return !!ret;
 }
+DEFINE_SIMPLE_COMMAND(restore, "restore");
cmds-scrub.c +13 -7
index dabe7d9a..b0f447c7 100644
@@ -1580,6 +1580,7 @@ static int cmd_scrub_start(int argc, char **argv)
 {
 	return scrub_start(argc, argv, 0);
 }
+static DEFINE_SIMPLE_COMMAND(scrub_start, "start");
 
 static const char * const cmd_scrub_cancel_usage[] = {
 	"btrfs scrub cancel <path>|<device>",
@@ -1626,6 +1627,7 @@ out:
 	close_file_or_dir(fdmnt, dirstream);
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(scrub_cancel, "cancel");
 
 static const char * const cmd_scrub_resume_usage[] = {
 	"btrfs scrub resume [-BdqrR] [-c ioprio_class -n ioprio_classdata] <path>|<device>",
@@ -1645,6 +1647,7 @@ static int cmd_scrub_resume(int argc, char **argv)
 {
 	return scrub_start(argc, argv, 1);
 }
+static DEFINE_SIMPLE_COMMAND(scrub_resume, "resume");
 
 static const char * const cmd_scrub_status_usage[] = {
 	"btrfs scrub status [-dR] <path>|<device>",
@@ -1786,21 +1789,24 @@ out:
 
 	return !!err;
 }
+static DEFINE_SIMPLE_COMMAND(scrub_status, "status");
 
 static const char scrub_cmd_group_info[] =
 "verify checksums of data and metadata";
 
-const struct cmd_group scrub_cmd_group = {
+static const struct cmd_group scrub_cmd_group = {
 	scrub_cmd_group_usage, scrub_cmd_group_info, {
-		{ "start", cmd_scrub_start, cmd_scrub_start_usage, NULL, 0 },
-		{ "cancel", cmd_scrub_cancel, cmd_scrub_cancel_usage, NULL, 0 },
-		{ "resume", cmd_scrub_resume, cmd_scrub_resume_usage, NULL, 0 },
-		{ "status", cmd_scrub_status, cmd_scrub_status_usage, NULL, 0 },
-		NULL_CMD_STRUCT
+		&cmd_struct_scrub_start,
+		&cmd_struct_scrub_cancel,
+		&cmd_struct_scrub_resume,
+		&cmd_struct_scrub_status,
+		NULL
 	}
 };
 
-int cmd_scrub(int argc, char **argv)
+static int cmd_scrub(int argc, char **argv)
 {
 	return handle_command_group(&scrub_cmd_group, argc, argv);
 }
+
+DEFINE_GROUP_COMMAND_TOKEN(scrub);
cmds-send.c +3 -3
index 8365e9c9..f1e5124d 100644
@@ -489,8 +489,7 @@ static void free_send_info(struct btrfs_send *sctx)
 	subvol_uuid_search_finit(&sctx->sus);
 }
 
-
-const char * const cmd_send_usage[] = {
+static const char * const cmd_send_usage[] = {
 	"btrfs send [-ve] [-p <parent>] [-c <clone-src>] [-f <outfile>] <subvol> [<subvol>...]",
 	"Send the subvolume(s) to stdout.",
 	"Sends the subvolume(s) specified by <subvol> to stdout.",
@@ -524,7 +523,7 @@ const char * const cmd_send_usage[] = {
 	NULL
 };
 
-int cmd_send(int argc, char **argv)
+static int cmd_send(int argc, char **argv)
 {
 	char *subvol = NULL;
 	int ret;
@@ -809,3 +808,4 @@ out:
 	free_send_info(&send);
 	return !!ret;
 }
+DEFINE_SIMPLE_COMMAND(send, "send");
cmds-subvolume.c +22 -16
index 96fb7b06..6fc4b2e7 100644
@@ -223,6 +223,7 @@ out:
 
 	return retval;
 }
+static DEFINE_SIMPLE_COMMAND(subvol_create, "create");
 
 static int wait_for_commit(int fd)
 {
@@ -429,6 +430,7 @@ keep_fd:
 
 	return ret;
 }
+static DEFINE_SIMPLE_COMMAND(subvol_delete, "delete");
 
 /*
  * Naming of options:
@@ -632,6 +634,7 @@ out:
 		usage(cmd_subvol_list_usage);
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(subvol_list, "list");
 
 static const char * const cmd_subvol_snapshot_usage[] = {
 	"btrfs subvolume snapshot [-r] [-i <qgroupid>] <source> <dest>|[<dest>/]<name>",
@@ -788,6 +791,7 @@ out:
 
 	return retval;
 }
+static DEFINE_SIMPLE_COMMAND(subvol_snapshot, "snapshot");
 
 static const char * const cmd_subvol_get_default_usage[] = {
 	"btrfs subvolume get-default <path>",
@@ -852,6 +856,7 @@ out:
 	close_file_or_dir(fd, dirstream);
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(subvol_get_default, "get-default");
 
 static const char * const cmd_subvol_set_default_usage[] = {
 	"btrfs subvolume set-default <subvolume>\n"
@@ -918,6 +923,7 @@ static int cmd_subvol_set_default(int argc, char **argv)
 	}
 	return 0;
 }
+static DEFINE_SIMPLE_COMMAND(subvol_set_default, "set-default");
 
 static const char * const cmd_subvol_find_new_usage[] = {
 	"btrfs subvolume find-new <path> <lastgen>",
@@ -966,6 +972,7 @@ static int cmd_subvol_find_new(int argc, char **argv)
 	close_file_or_dir(fd, dirstream);
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(subvol_find_new, "find-new");
 
 static const char * const cmd_subvol_show_usage[] = {
 	"btrfs subvolume show [options] <subvol-path>|<mnt>",
@@ -1170,6 +1177,7 @@ out:
 	free(fullpath);
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(subvol_show, "show");
 
 static const char * const cmd_subvol_sync_usage[] = {
 	"btrfs subvolume sync <path> [<subvol-id>...]",
@@ -1420,30 +1428,28 @@ out:
 
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(subvol_sync, "sync");
 
 static const char subvolume_cmd_group_info[] =
 "manage subvolumes: create, delete, list, etc";
 
-const struct cmd_group subvolume_cmd_group = {
+static const struct cmd_group subvolume_cmd_group = {
 	subvolume_cmd_group_usage, subvolume_cmd_group_info, {
-		{ "create", cmd_subvol_create, cmd_subvol_create_usage, NULL, 0 },
-		{ "delete", cmd_subvol_delete, cmd_subvol_delete_usage, NULL, 0 },
-		{ "list", cmd_subvol_list, cmd_subvol_list_usage, NULL, 0 },
-		{ "snapshot", cmd_subvol_snapshot, cmd_subvol_snapshot_usage,
-			NULL, 0 },
-		{ "get-default", cmd_subvol_get_default,
-			cmd_subvol_get_default_usage, NULL, 0 },
-		{ "set-default", cmd_subvol_set_default,
-			cmd_subvol_set_default_usage, NULL, 0 },
-		{ "find-new", cmd_subvol_find_new, cmd_subvol_find_new_usage,
-			NULL, 0 },
-		{ "show", cmd_subvol_show, cmd_subvol_show_usage, NULL, 0 },
-		{ "sync", cmd_subvol_sync, cmd_subvol_sync_usage, NULL, 0 },
-		NULL_CMD_STRUCT
+		&cmd_struct_subvol_create,
+		&cmd_struct_subvol_delete,
+		&cmd_struct_subvol_list,
+		&cmd_struct_subvol_snapshot,
+		&cmd_struct_subvol_get_default,
+		&cmd_struct_subvol_set_default,
+		&cmd_struct_subvol_find_new,
+		&cmd_struct_subvol_show,
+		&cmd_struct_subvol_sync,
+		NULL
 	}
 };
 
-int cmd_subvolume(int argc, char **argv)
+static int cmd_subvolume(int argc, char **argv)
 {
 	return handle_command_group(&subvolume_cmd_group, argc, argv);
 }
+DEFINE_GROUP_COMMAND_TOKEN(subvolume);
commands.h +75 -52

144 lines not on this page · raw message

help.c +13 -8
index ef7986b4..b7f06aae 100644
@@ -248,14 +248,15 @@ void usage(const char * const *usagestr)
 static void usage_command_group_internal(const struct cmd_group *grp, bool full,
 					 FILE *outf)
 {
-	const struct cmd_struct *cmd = grp->commands;
+	int i;
 	int do_sep = 0;
 
-	for (; cmd->token; cmd++) {
+	for (i = 0; grp->commands[i]; i++) {
+		const struct cmd_struct *cmd = grp->commands[i];
 		if (cmd->flags & CMD_HIDDEN)
 			continue;
 
-		if (full && cmd != grp->commands)
+		if (full && i)
 			fputc('\n', outf);
 
 		if (!cmd->next) {
@@ -274,7 +275,7 @@ static void usage_command_group_internal(const struct cmd_group *grp, bool full,
 
 		/* this is an entry point to a nested command group */
 
-		if (!full && cmd != grp->commands)
+		if (!full && i)
 			fputc('\n', outf);
 
 		usage_command_group_internal(cmd->next, full, outf);
@@ -289,6 +290,7 @@ void usage_command_group_short(const struct cmd_group *grp)
 	const char * const *usagestr = grp->usagestr;
 	FILE *outf = stdout;
 	const struct cmd_struct *cmd;
+	int i;
 
 	if (usagestr && *usagestr) {
 		fprintf(outf, "usage: %s\n", *usagestr++);
@@ -299,7 +301,8 @@ void usage_command_group_short(const struct cmd_group *grp)
 	fputc('\n', outf);
 
 	fprintf(outf, "Command groups:\n");
-	for (cmd = grp->commands; cmd->token; cmd++) {
+	for (i = 0; grp->commands[i]; i++) {
+		cmd = grp->commands[i];
 		if (cmd->flags & CMD_HIDDEN)
 			continue;
 
@@ -310,7 +313,8 @@ void usage_command_group_short(const struct cmd_group *grp)
 	}
 
 	fprintf(outf, "\nCommands:\n");
-	for (cmd = grp->commands; cmd->token; cmd++) {
+	for (i = 0; grp->commands[i]; i++) {
+		cmd = grp->commands[i];
 		if (cmd->flags & CMD_HIDDEN)
 			continue;
 
@@ -358,12 +362,13 @@ void help_unknown_token(const char *arg, const struct cmd_group *grp)
 __attribute__((noreturn))
 void help_ambiguous_token(const char *arg, const struct cmd_group *grp)
 {
-	const struct cmd_struct *cmd = grp->commands;
+	int i;
 
 	fprintf(stderr, "%s: ambiguous token '%s'\n", get_argv0_buf(), arg);
 	fprintf(stderr, "\nDid you mean one of these ?\n");
 
-	for (; cmd->token; cmd++) {
+	for (i = 0; grp->commands[i]; i++) {
+		const struct cmd_struct *cmd = grp->commands[i];
 		if (!prefixcmp(cmd->token, arg))
 			fprintf(stderr, "\t%s\n", cmd->token);
 	}
Signature · 1 line
2.12.3
#22 lore raw

Re: [PATCH 13/20] btrfs-progs: use cmd_struct as command entry point

Quoted 42 lines · On 3/7/18 9:40 PM, [email protected] wrote:

From: Jeff Mahoney <[email protected]>

cmds-inspect.c +10 -18
index afd7fe48..12f200b3 100644
@@ -625,33 +629,27 @@ static int cmd_inspect_min_dev_size(int argc, char **argv)
 out:
 	return !!ret;
 }
+static DEFINE_SIMPLE_COMMAND(inspect_min_dev_size, "min-dev-size");
 
 static const char inspect_cmd_group_info[] =
 "query various internal information";
 
-const struct cmd_group inspect_cmd_group = {
+static const struct cmd_group inspect_cmd_group = {
 	inspect_cmd_group_usage, inspect_cmd_group_info, {
-		{ "inode-resolve", cmd_inspect_inode_resolve,
-			cmd_inspect_inode_resolve_usage, NULL, 0 },
-		{ "logical-resolve", cmd_inspect_logical_resolve,
-			cmd_inspect_logical_resolve_usage, NULL, 0 },
-		{ "subvolid-resolve", cmd_inspect_subvolid_resolve,
-			cmd_inspect_subvolid_resolve_usage, NULL, 0 },
-		{ "rootid", cmd_inspect_rootid, cmd_inspect_rootid_usage, NULL,
-			0 },
-		{ "min-dev-size", cmd_inspect_min_dev_size,
-			cmd_inspect_min_dev_size_usage, NULL, 0 },
-		{ "dump-tree", cmd_inspect_dump_tree,
-				cmd_inspect_dump_tree_usage, NULL, 0 },
-		{ "dump-super", cmd_inspect_dump_super,
-				cmd_inspect_dump_super_usage, NULL, 0 },
-		{ "tree-stats", cmd_inspect_tree_stats,
-				cmd_inspect_tree_stats_usage, NULL, 0 },
-		NULL_CMD_STRUCT
+		&cmd_struct_inspect_inode_resolve,
+		&cmd_struct_inspect_logical_resolve,
+		&cmd_struct_inspect_subvolid_resolve,
+		&cmd_struct_inspect_rootid,
+		&cmd_struct_inspect_min_dev_size,
+		&cmd_struct_inspect_dump_tree,
+		&cmd_struct_inspect_dump_super,
+		&cmd_struct_inspect_tree_stats,

cmds-inspect.c static int cmd_inspect_min_dev_size(int argc, char **argv) · line 655

Quoted 10 lines
cmds-inspect.c +3 -1
+		NULL
 	}
 };
 
-int cmd_inspect(int argc, char **argv)
+static int cmd_inspect(int argc, char **argv)
 {
 	return handle_command_group(&inspect_cmd_group, argc, argv);
 }
+DEFINE_GROUP_COMMAND(inspect, "inspect");

"inspect-internal"

-Jeff

Signature · 2 lines
Jeff Mahoney
SUSE Labs
#23 lore raw

Re: [PATCH 13/20] btrfs-progs: use cmd_struct as command entry point

In reply to [email protected]

cmds-filesystem.c next: · line 1081

Quoted 9 lines · On 3/7/18 9:40 PM, [email protected] wrote:
cmds-filesystem.c +1 -0
index 62112705..ec038f2f 100644
@@ -1075,6 +1078,7 @@ next:
 
 	return !!defrag_global_errors;
 }
+static DEFINE_SIMPLE_COMMAND(filesystem_defrag, "defrag");

"defragment"

-Jeff

Signature · 2 lines
Jeff Mahoney
SUSE Labs
#24 lore raw

PATCH v2 14/20 btrfs-progs: pass cmd_struct to command callback function

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

This patch passes the cmd_struct to the command callback function. This has several purposes: It allows the command callback to identify which command was used to call it. It also gives us direct access to the usage associated with that command.

---
 btrfs.c                   |  8 ++++----
 check/main.c              |  2 +-
 cmds-balance.c            | 19 ++++++++++++-------
 cmds-device.c             | 35 +++++++++++++++++++----------------
 cmds-fi-du.c              |  3 ++-
 cmds-fi-usage.c           |  3 ++-
 cmds-filesystem.c         | 24 ++++++++++++++++--------
 cmds-inspect-dump-super.c |  3 ++-
 cmds-inspect-dump-tree.c  |  3 ++-
 cmds-inspect-tree-stats.c |  3 ++-
 cmds-inspect.c            | 17 +++++++++++------
 cmds-property.c           | 12 ++++++++----
 cmds-qgroup.c             | 18 +++++++++++-------
 cmds-quota.c              |  9 +++++----
 cmds-receive.c            |  2 +-
 cmds-replace.c            | 11 +++++++----
 cmds-rescue.c             | 14 +++++++++-----
 cmds-restore.c            |  2 +-
 cmds-scrub.c              | 23 +++++++++++------------
 cmds-send.c               |  2 +-
 cmds-subvolume.c          | 27 +++++++++++++++++----------
 commands.h                |  4 ++--
 22 files changed, 146 insertions(+), 98 deletions(-)
btrfs.c +4 -4
index 1e68b0c0..49128182 100644
@@ -148,7 +148,7 @@ static const char * const cmd_help_usage[] = {
 	NULL
 };
 
-static int cmd_help(int argc, char **argv)
+static int cmd_help(const struct cmd_struct *unused, int argc, char **argv)
 {
 	help_command_group(&btrfs_cmd_group, argc, argv);
 	return 0;
@@ -162,7 +162,7 @@ static const char * const cmd_version_usage[] = {
 	NULL
 };
 
-static int cmd_version(int argc, char **argv)
+static int cmd_version(const struct cmd_struct *unused, int argc, char **argv)
 {
 	printf("%s\n", PACKAGE_STRING);
 	return 0;
@@ -231,13 +231,13 @@ void handle_special_globals(int shift, int argc, char **argv)
 		if (has_full)
 			usage_command_group(&btrfs_cmd_group, true, false);
 		else
-			cmd_help(argc, argv);
+			cmd_execute(&cmd_struct_help, argc, argv);
 		exit(0);
 	}
 
 	for (i = 0; i < shift; i++)
 		if (strcmp(argv[i], "--version") == 0) {
-			cmd_version(argc, argv);
+			cmd_execute(&cmd_struct_version, argc, argv);
 			exit(0);
 		}
 }
check/main.c +1 -1
index 4b8f7678..bd31fb9f 100644
@@ -9440,7 +9440,7 @@ static const char * const cmd_check_usage[] = {
 	NULL
 };
 
-static int cmd_check(int argc, char **argv)
+static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	struct cache_tree root_cache;
 	struct btrfs_root *root;
cmds-balance.c +12 -7
index 7a60be61..1bd7b3ce 100644
@@ -515,7 +515,8 @@ static const char * const cmd_balance_start_usage[] = {
 	NULL
 };
 
-static int cmd_balance_start(int argc, char **argv)
+static int cmd_balance_start(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
 	struct btrfs_ioctl_balance_args args;
 	struct btrfs_balance_args *ptrs[] = { &args.data, &args.sys,
@@ -680,7 +681,8 @@ static const char * const cmd_balance_pause_usage[] = {
 	NULL
 };
 
-static int cmd_balance_pause(int argc, char **argv)
+static int cmd_balance_pause(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
 	const char *path;
 	int fd;
@@ -719,7 +721,8 @@ static const char * const cmd_balance_cancel_usage[] = {
 	NULL
 };
 
-static int cmd_balance_cancel(int argc, char **argv)
+static int cmd_balance_cancel(const struct cmd_struct *cmd,
+			      int argc, char **argv)
 {
 	const char *path;
 	int fd;
@@ -758,7 +761,8 @@ static const char * const cmd_balance_resume_usage[] = {
 	NULL
 };
 
-static int cmd_balance_resume(int argc, char **argv)
+static int cmd_balance_resume(const struct cmd_struct *cmd,
+			      int argc, char **argv)
 {
 	struct btrfs_ioctl_balance_args args;
 	const char *path;
@@ -826,7 +830,8 @@ static const char * const cmd_balance_status_usage[] = {
  *   1 : Successful to know status of a pending balance
  *   0 : When there is no pending balance or completed
  */
-static int cmd_balance_status(int argc, char **argv)
+static int cmd_balance_status(const struct cmd_struct *cmd,
+			      int argc, char **argv)
 {
 	struct btrfs_ioctl_balance_args args;
 	const char *path;
@@ -904,7 +909,7 @@ out:
 }
 static DEFINE_SIMPLE_COMMAND(balance_status, "status");
 
-static int cmd_balance_full(int argc, char **argv)
+static int cmd_balance_full(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	struct btrfs_ioctl_balance_args args;
 
@@ -931,7 +936,7 @@ static const struct cmd_group balance_cmd_group = {
 	}
 };
 
-static int cmd_balance(int argc, char **argv)
+static int cmd_balance(const struct cmd_struct *unused, int argc, char **argv)
 {
 	if (argc == 2 && strcmp("start", argv[1]) != 0) {
 		/* old 'btrfs filesystem balance <path>' syntax */
cmds-device.c +19 -16
index 96764d6c..feb53f68 100644
@@ -48,7 +48,8 @@ static const char * const cmd_device_add_usage[] = {
 	NULL
 };
 
-static int cmd_device_add(int argc, char **argv)
+static int cmd_device_add(const struct cmd_struct *cmd,
+			  int argc, char **argv)
 {
 	char	*mntpnt;
 	int i, fdmnt, ret = 0;
@@ -142,17 +143,17 @@ error_out:
 }
 static DEFINE_SIMPLE_COMMAND(device_add, "add");
 
-static int _cmd_device_remove(int argc, char **argv,
-		const char * const *usagestr)
+static int _cmd_device_remove(const struct cmd_struct *cmd,
+			      int argc, char **argv)
 {
 	char	*mntpnt;
 	int i, fdmnt, ret = 0;
 	DIR	*dirstream = NULL;
 
-	clean_args_no_options(argc, argv, usagestr);
+	clean_args_no_options(argc, argv, cmd->usagestr);
 
 	if (check_argc_min(argc - optind, 2))
-		usage(usagestr);
+		usage(cmd->usagestr);
 
 	mntpnt = argv[argc - 1];
 
@@ -236,9 +237,10 @@ static const char * const cmd_device_remove_usage[] = {
 	NULL
 };
 
-static int cmd_device_remove(int argc, char **argv)
+static int cmd_device_remove(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
-	return _cmd_device_remove(argc, argv, cmd_device_remove_usage);
+	return _cmd_device_remove(cmd, argc, argv);
 }
 static DEFINE_SIMPLE_COMMAND(device_remove, "remove");
 
@@ -250,9 +252,10 @@ static const char * const cmd_device_delete_usage[] = {
 	NULL
 };
 
-static int cmd_device_delete(int argc, char **argv)
+static int cmd_device_delete(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
-	return _cmd_device_remove(argc, argv, cmd_device_delete_usage);
+	return _cmd_device_remove(cmd, argc, argv);
 }
 static DEFINE_COMMAND(device_delete, "delete", cmd_device_delete,
 		      cmd_device_delete_usage, NULL, CMD_ALIAS);
@@ -264,7 +267,7 @@ static const char * const cmd_device_scan_usage[] = {
 	NULL
 };
 
-static int cmd_device_scan(int argc, char **argv)
+static int cmd_device_scan(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	int i;
 	int devstart;
@@ -337,14 +340,14 @@ static const char * const cmd_device_ready_usage[] = {
 	NULL
 };
 
-static int cmd_device_ready(int argc, char **argv)
+static int cmd_device_ready(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	struct	btrfs_ioctl_vol_args args;
 	int	fd;
 	int	ret;
 	char	*path;
 
-	clean_args_no_options(argc, argv, cmd_device_ready_usage);
+	clean_args_no_options(argc, argv, cmd->usagestr);
 
 	if (check_argc_exact(argc - optind, 1))
 		usage(cmd_device_ready_usage);
@@ -396,7 +399,7 @@ static const char * const cmd_device_stats_usage[] = {
 	NULL
 };
 
-static int cmd_device_stats(int argc, char **argv)
+static int cmd_device_stats(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	char *dev_path;
 	struct btrfs_ioctl_fs_info_args fi_args;
@@ -562,7 +565,7 @@ out:
 	return ret;
 }
 
-static int cmd_device_usage(int argc, char **argv)
+static int cmd_device_usage(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	unsigned unit_mode;
 	int ret = 0;
@@ -570,7 +573,7 @@ static int cmd_device_usage(int argc, char **argv)
 
 	unit_mode = get_unit_mode_from_arg(&argc, argv, 1);
 
-	clean_args_no_options(argc, argv, cmd_device_usage_usage);
+	clean_args_no_options(argc, argv, cmd->usagestr);
 
 	if (check_argc_min(argc - optind, 1))
 		usage(cmd_device_usage_usage);
@@ -615,7 +618,7 @@ static const struct cmd_group device_cmd_group = {
 	}
 };
 
-static int cmd_device(int argc, char **argv)
+static int cmd_device(const struct cmd_struct *unused, int argc, char **argv)
 {
 	return handle_command_group(&device_cmd_group, argc, argv);
 }
cmds-fi-du.c +2 -1
index cb2f09c7..a86f4ad6 100644
@@ -557,7 +557,8 @@ static const char * const cmd_filesystem_du_usage[] = {
 	NULL
 };
 
-static int cmd_filesystem_du(int argc, char **argv)
+static int cmd_filesystem_du(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
 	int ret = 0, err = 0;
 	int i;
cmds-fi-usage.c +2 -1
index af882400..36684762 100644
@@ -965,7 +965,8 @@ static const char * const cmd_filesystem_usage_usage[] = {
 	NULL
 };
 
-static int cmd_filesystem_usage(int argc, char **argv)
+static int cmd_filesystem_usage(const struct cmd_struct *cmd,
+				int argc, char **argv)
 {
 	int ret = 0;
 	unsigned unit_mode;
cmds-filesystem.c +16 -8
index ec038f2f..c2ee8595 100644
@@ -115,7 +115,8 @@ static void print_df(struct btrfs_ioctl_space_args *sargs, unsigned unit_mode)
 	}
 }
 
-static int cmd_filesystem_df(int argc, char **argv)
+static int cmd_filesystem_df(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
 	struct btrfs_ioctl_space_args *sargs = NULL;
 	int ret;
@@ -666,7 +667,8 @@ static const char * const cmd_filesystem_show_usage[] = {
 	NULL
 };
 
-static int cmd_filesystem_show(int argc, char **argv)
+static int cmd_filesystem_show(const struct cmd_struct *cmd,
+			       int argc, char **argv)
 {
 	LIST_HEAD(all_uuids);
 	struct btrfs_fs_devices *fs_devices;
@@ -813,7 +815,8 @@ static const char * const cmd_filesystem_sync_usage[] = {
 	NULL
 };
 
-static int cmd_filesystem_sync(int argc, char **argv)
+static int cmd_filesystem_sync(const struct cmd_struct *cmd,
+			       int argc, char **argv)
 {
 	int 	fd, res;
 	char	*path;
@@ -910,7 +913,8 @@ error:
 	return 0;
 }
 
-static int cmd_filesystem_defrag(int argc, char **argv)
+static int cmd_filesystem_defrag(const struct cmd_struct *cmd,
+				 int argc, char **argv)
 {
 	int fd;
 	int flush = 0;
@@ -1089,7 +1093,8 @@ static const char * const cmd_filesystem_resize_usage[] = {
 	NULL
 };
 
-static int cmd_filesystem_resize(int argc, char **argv)
+static int cmd_filesystem_resize(const struct cmd_struct *cmd,
+				 int argc, char **argv)
 {
 	struct btrfs_ioctl_vol_args	args;
 	int	fd, res, len, e;
@@ -1167,7 +1172,8 @@ static const char * const cmd_filesystem_label_usage[] = {
 	NULL
 };
 
-static int cmd_filesystem_label(int argc, char **argv)
+static int cmd_filesystem_label(const struct cmd_struct *cmd,
+				int argc, char **argv)
 {
 	clean_args_no_options(argc, argv, cmd_filesystem_label_usage);
 
@@ -1196,7 +1202,8 @@ static const char * const cmd_filesystem_balance_usage[] = {
 	NULL
 };
 
-static int cmd_filesystem_balance(int argc, char **argv)
+static int cmd_filesystem_balance(const struct cmd_struct *unused,
+				  int argc, char **argv)
 {
 	return cmd_execute(&cmd_struct_balance, argc, argv);
 }
@@ -1228,7 +1235,8 @@ static const struct cmd_group filesystem_cmd_group = {
 	}
 };
 
-static int cmd_filesystem(int argc, char **argv)
+static int cmd_filesystem(const struct cmd_struct *unused,
+			  int argc, char **argv)
 {
 	return handle_command_group(&filesystem_cmd_group, argc, argv);
 }
cmds-inspect-dump-super.c +2 -1
index 34542d71..ca503a2e 100644
@@ -504,7 +504,8 @@ static const char * const cmd_inspect_dump_super_usage[] = {
 	NULL
 };
 
-static int cmd_inspect_dump_super(int argc, char **argv)
+static int cmd_inspect_dump_super(const struct cmd_struct *cmd,
+				  int argc, char **argv)
 {
 	int all = 0;
 	int full = 0;
cmds-inspect-dump-tree.c +2 -1
index 6417eab3..5cc39a88 100644
@@ -201,7 +201,8 @@ static const char * const cmd_inspect_dump_tree_usage[] = {
 	NULL
 };
 
-static int cmd_inspect_dump_tree(int argc, char **argv)
+static int cmd_inspect_dump_tree(const struct cmd_struct *cmd,
+				 int argc, char **argv)
 {
 	struct btrfs_root *root;
 	struct btrfs_fs_info *info;
cmds-inspect-tree-stats.c +2 -1
index 14d79ccc..64ca3d0b 100644
@@ -427,7 +427,8 @@ static const char * const cmd_inspect_tree_stats_usage[] = {
 	NULL
 };
 
-static int cmd_inspect_tree_stats(int argc, char **argv)
+static int cmd_inspect_tree_stats(const struct cmd_struct *cmd,
+				  int argc, char **argv)
 {
 	struct btrfs_key key;
 	struct btrfs_root *root;
cmds-inspect.c +11 -6
index 12f200b3..1bdc8bd9 100644
@@ -87,7 +87,8 @@ static const char * const cmd_inspect_inode_resolve_usage[] = {
 	NULL
 };
 
-static int cmd_inspect_inode_resolve(int argc, char **argv)
+static int cmd_inspect_inode_resolve(const struct cmd_struct *cmd,
+				     int argc, char **argv)
 {
 	int fd;
 	int verbose = 0;
@@ -134,7 +135,8 @@ static const char * const cmd_inspect_logical_resolve_usage[] = {
 	NULL
 };
 
-static int cmd_inspect_logical_resolve(int argc, char **argv)
+static int cmd_inspect_logical_resolve(const struct cmd_struct *cmd,
+				       int argc, char **argv)
 {
 	int ret;
 	int fd;
@@ -266,7 +268,8 @@ static const char * const cmd_inspect_subvolid_resolve_usage[] = {
 	NULL
 };
 
-static int cmd_inspect_subvolid_resolve(int argc, char **argv)
+static int cmd_inspect_subvolid_resolve(const struct cmd_struct *cmd,
+					int argc, char **argv)
 {
 	int ret;
 	int fd = -1;
@@ -309,7 +312,8 @@ static const char* const cmd_inspect_rootid_usage[] = {
 	NULL
 };
 
-static int cmd_inspect_rootid(int argc, char **argv)
+static int cmd_inspect_rootid(const struct cmd_struct *cmd,
+			      int argc, char **argv)
 {
 	int ret;
 	int fd = -1;
@@ -588,7 +592,8 @@ out:
 	return ret;
 }
 
-static int cmd_inspect_min_dev_size(int argc, char **argv)
+static int cmd_inspect_min_dev_size(const struct cmd_struct *cmd,
+				    int argc, char **argv)
 {
 	int ret;
 	int fd = -1;
@@ -648,7 +653,7 @@ static const struct cmd_group inspect_cmd_group = {
 	}
 };
 
-static int cmd_inspect(int argc, char **argv)
+static int cmd_inspect(const struct cmd_struct *unused, int argc, char **argv)
 {
 	return handle_command_group(&inspect_cmd_group, argc, argv);
 }
cmds-property.c +8 -4
index dce1f2a9..5684443c 100644
@@ -341,7 +341,8 @@ static const char * const cmd_property_get_usage[] = {
 	NULL
 };
 
-static int cmd_property_get(int argc, char **argv)
+static int cmd_property_get(const struct cmd_struct *cmd,
+			    int argc, char **argv)
 {
 	int ret;
 	char *object = NULL;
@@ -368,7 +369,8 @@ static const char * const cmd_property_set_usage[] = {
 	NULL
 };
 
-static int cmd_property_set(int argc, char **argv)
+static int cmd_property_set(const struct cmd_struct *cmd,
+			    int argc, char **argv)
 {
 	int ret;
 	char *object = NULL;
@@ -393,7 +395,8 @@ static const char * const cmd_property_list_usage[] = {
 	NULL
 };
 
-static int cmd_property_list(int argc, char **argv)
+static int cmd_property_list(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
 	int ret;
 	char *object = NULL;
@@ -420,7 +423,8 @@ static const struct cmd_group property_cmd_group = {
 	}
 };
 
-static int cmd_property(int argc, char **argv)
+static int cmd_property(const struct cmd_struct *unused,
+			int argc, char **argv)
 {
 	return handle_command_group(&property_cmd_group, argc, argv);
 }
cmds-qgroup.c +11 -7
index 6945d160..2972baee 100644
@@ -215,7 +215,8 @@ static const char * const cmd_qgroup_assign_usage[] = {
 	NULL
 };
 
-static int cmd_qgroup_assign(int argc, char **argv)
+static int cmd_qgroup_assign(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
 	return _cmd_qgroup_assign(1, argc, argv, cmd_qgroup_assign_usage);
 }
@@ -227,7 +228,8 @@ static const char * const cmd_qgroup_remove_usage[] = {
 	NULL
 };
 
-static int cmd_qgroup_remove(int argc, char **argv)
+static int cmd_qgroup_remove(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
 	return _cmd_qgroup_assign(0, argc, argv, cmd_qgroup_remove_usage);
 }
@@ -239,7 +241,8 @@ static const char * const cmd_qgroup_create_usage[] = {
 	NULL
 };
 
-static int cmd_qgroup_create(int argc, char **argv)
+static int cmd_qgroup_create(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
 	int ret;
 
@@ -259,7 +262,8 @@ static const char * const cmd_qgroup_destroy_usage[] = {
 	NULL
 };
 
-static int cmd_qgroup_destroy(int argc, char **argv)
+static int cmd_qgroup_destroy(const struct cmd_struct *cmd,
+			      int argc, char **argv)
 {
 	int ret;
 
@@ -296,7 +300,7 @@ static const char * const cmd_qgroup_show_usage[] = {
 	NULL
 };
 
-static int cmd_qgroup_show(int argc, char **argv)
+static int cmd_qgroup_show(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	char *path;
 	int ret = 0;
@@ -430,7 +434,7 @@ static const char * const cmd_qgroup_limit_usage[] = {
 	NULL
 };
 
-static int cmd_qgroup_limit(int argc, char **argv)
+static int cmd_qgroup_limit(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	int ret = 0;
 	int fd;
@@ -528,7 +532,7 @@ static const struct cmd_group qgroup_cmd_group = {
 	}
 };
 
-static int cmd_qgroup(int argc, char **argv)
+static int cmd_qgroup(const struct cmd_struct *unused, int argc, char **argv)
 {
 	return handle_command_group(&qgroup_cmd_group, argc, argv);
 }
cmds-quota.c +5 -4
index 5cd5607f..a6e7a6f6 100644
@@ -67,7 +67,7 @@ static const char * const cmd_quota_enable_usage[] = {
 	NULL
 };
 
-static int cmd_quota_enable(int argc, char **argv)
+static int cmd_quota_enable(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	int ret;
 
@@ -87,7 +87,8 @@ static const char * const cmd_quota_disable_usage[] = {
 	NULL
 };
 
-static int cmd_quota_disable(int argc, char **argv)
+static int cmd_quota_disable(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
 	int ret;
 
@@ -110,7 +111,7 @@ static const char * const cmd_quota_rescan_usage[] = {
 	NULL
 };
 
-static int cmd_quota_rescan(int argc, char **argv)
+static int cmd_quota_rescan(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	int ret = 0;
 	int fd;
@@ -213,7 +214,7 @@ static const struct cmd_group quota_cmd_group = {
 	}
 };
 
-static int cmd_quota(int argc, char **argv)
+static int cmd_quota(const struct cmd_struct *unused, int argc, char **argv)
 {
 	return handle_command_group(&quota_cmd_group, argc, argv);
 }
cmds-receive.c +1 -1
index d88b8793..93c1838d 100644
@@ -1279,7 +1279,7 @@ static const char * const cmd_receive_usage[] = {
 	NULL
 };
 
-static int cmd_receive(int argc, char **argv)
+static int cmd_receive(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	char *tomnt = NULL;
 	char fromfile[PATH_MAX];
cmds-replace.c +7 -4
index a7379c71..f1e76bdf 100644
@@ -114,7 +114,8 @@ static const char *const cmd_replace_start_usage[] = {
 	NULL
 };
 
-static int cmd_replace_start(int argc, char **argv)
+static int cmd_replace_start(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
 	struct btrfs_ioctl_dev_replace_args start_args = {0};
 	struct btrfs_ioctl_dev_replace_args status_args = {0};
@@ -325,7 +326,8 @@ static const char *const cmd_replace_status_usage[] = {
 	NULL
 };
 
-static int cmd_replace_status(int argc, char **argv)
+static int cmd_replace_status(const struct cmd_struct *cmd,
+			      int argc, char **argv)
 {
 	int fd;
 	int c;
@@ -494,7 +496,8 @@ static const char *const cmd_replace_cancel_usage[] = {
 	NULL
 };
 
-static int cmd_replace_cancel(int argc, char **argv)
+static int cmd_replace_cancel(const struct cmd_struct *cmd,
+			      int argc, char **argv)
 {
 	struct btrfs_ioctl_dev_replace_args args = {0};
 	int ret;
@@ -554,7 +557,7 @@ static const struct cmd_group replace_cmd_group = {
 	}
 };
 
-static int cmd_replace(int argc, char **argv)
+static int cmd_replace(const struct cmd_struct *unused, int argc, char **argv)
 {
 	return handle_command_group(&replace_cmd_group, argc, argv);
 }
cmds-rescue.c +9 -5
index e3611f2f..f5a618e1 100644
@@ -45,7 +45,8 @@ static const char * const cmd_rescue_chunk_recover_usage[] = {
 	NULL
 };
 
-static int cmd_rescue_chunk_recover(int argc, char *argv[])
+static int cmd_rescue_chunk_recover(const struct cmd_struct *cmd,
+				    int argc, char *argv[])
 {
 	int ret = 0;
 	char *file;
@@ -113,7 +114,8 @@ static const char * const cmd_rescue_super_recover_usage[] = {
  *   3 : Fail to Recover bad supeblocks
  *   4 : Abort to recover bad superblocks
  */
-static int cmd_rescue_super_recover(int argc, char **argv)
+static int cmd_rescue_super_recover(const struct cmd_struct *cmd,
+				    int argc, char **argv)
 {
 	int ret;
 	int verbose = 0;
@@ -159,7 +161,8 @@ static const char * const cmd_rescue_zero_log_usage[] = {
 	NULL
 };
 
-static int cmd_rescue_zero_log(int argc, char **argv)
+static int cmd_rescue_zero_log(const struct cmd_struct *cmd,
+			       int argc, char **argv)
 {
 	struct btrfs_root *root;
 	struct btrfs_trans_handle *trans;
@@ -213,7 +216,8 @@ static const char * const cmd_rescue_fix_device_size_usage[] = {
 	NULL
 };
 
-static int cmd_rescue_fix_device_size(int argc, char **argv)
+static int cmd_rescue_fix_device_size(const struct cmd_struct *cmd,
+				      int argc, char **argv)
 {
 	struct btrfs_fs_info *fs_info;
 	char *devname;
@@ -265,7 +269,7 @@ static const struct cmd_group rescue_cmd_group = {
 	}
 };
 
-static int cmd_rescue(int argc, char **argv)
+static int cmd_rescue(const struct cmd_struct *unused, int argc, char **argv)
 {
 	return handle_command_group(&rescue_cmd_group, argc, argv);
 }
cmds-restore.c +1 -1
index 05fd1c80..e850ec97 100644
@@ -1415,7 +1415,7 @@ static const char * const cmd_restore_usage[] = {
 	NULL
 };
 
-static int cmd_restore(int argc, char **argv)
+static int cmd_restore(const struct cmd_struct *unused, int argc, char **argv)
 {
 	struct btrfs_root *root;
 	struct btrfs_key key;
cmds-scrub.c +11 -12
index b0f447c7..a762f035 100644
@@ -1097,7 +1097,8 @@ static int is_scrub_running_in_kernel(int fd,
 static const char * const cmd_scrub_start_usage[];
 static const char * const cmd_scrub_resume_usage[];
 
-static int scrub_start(int argc, char **argv, int resume)
+static int scrub_start(const struct cmd_struct *cmd, int argc, char **argv,
+		       bool resume)
 {
 	int fdmnt;
 	int prg_fd = -1;
@@ -1176,16 +1177,14 @@ static int scrub_start(int argc, char **argv, int resume)
 			break;
 		case '?':
 		default:
-			usage(resume ? cmd_scrub_resume_usage :
-						cmd_scrub_start_usage);
+			usage(cmd->usagestr);
 		}
 	}
 
 	/* try to catch most error cases before forking */
 
 	if (check_argc_exact(argc - optind, 1)) {
-		usage(resume ? cmd_scrub_resume_usage :
-					cmd_scrub_start_usage);
+		usage(cmd->usagestr);
 	}
 
 	spc.progress = NULL;
@@ -1576,9 +1575,9 @@ static const char * const cmd_scrub_start_usage[] = {
 	NULL
 };
 
-static int cmd_scrub_start(int argc, char **argv)
+static int cmd_scrub_start(const struct cmd_struct *cmd, int argc, char **argv)
 {
-	return scrub_start(argc, argv, 0);
+	return scrub_start(cmd, argc, argv, false);
 }
 static DEFINE_SIMPLE_COMMAND(scrub_start, "start");
 
@@ -1588,7 +1587,7 @@ static const char * const cmd_scrub_cancel_usage[] = {
 	NULL
 };
 
-static int cmd_scrub_cancel(int argc, char **argv)
+static int cmd_scrub_cancel(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	char *path;
 	int ret;
@@ -1643,9 +1642,9 @@ static const char * const cmd_scrub_resume_usage[] = {
 	NULL
 };
 
-static int cmd_scrub_resume(int argc, char **argv)
+static int cmd_scrub_resume(const struct cmd_struct *cmd, int argc, char **argv)
 {
-	return scrub_start(argc, argv, 1);
+	return scrub_start(cmd, argc, argv, true);
 }
 static DEFINE_SIMPLE_COMMAND(scrub_resume, "resume");
 
@@ -1658,7 +1657,7 @@ static const char * const cmd_scrub_status_usage[] = {
 	NULL
 };
 
-static int cmd_scrub_status(int argc, char **argv)
+static int cmd_scrub_status(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	char *path;
 	struct btrfs_ioctl_fs_info_args fi_args;
@@ -1804,7 +1803,7 @@ static const struct cmd_group scrub_cmd_group = {
 	}
 };
 
-static int cmd_scrub(int argc, char **argv)
+static int cmd_scrub(const struct cmd_struct *unused, int argc, char **argv)
 {
 	return handle_command_group(&scrub_cmd_group, argc, argv);
 }
cmds-send.c +1 -1
index f1e5124d..bd501576 100644
@@ -523,7 +523,7 @@ static const char * const cmd_send_usage[] = {
 	NULL
 };
 
-static int cmd_send(int argc, char **argv)
+static int cmd_send(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	char *subvol = NULL;
 	int ret;
cmds-subvolume.c +17 -10
index 6fc4b2e7..13303db8 100644
@@ -116,7 +116,8 @@ static const char * const cmd_subvol_create_usage[] = {
 	NULL
 };
 
-static int cmd_subvol_create(int argc, char **argv)
+static int cmd_subvol_create(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
 	int	retval, res, len;
 	int	fddst = -1;
@@ -251,7 +252,8 @@ static const char * const cmd_subvol_delete_usage[] = {
 	NULL
 };
 
-static int cmd_subvol_delete(int argc, char **argv)
+static int cmd_subvol_delete(const struct cmd_struct *cmd,
+			     int argc, char **argv)
 {
 	int res, ret = 0;
 	int cnt;
@@ -477,7 +479,7 @@ static const char * const cmd_subvol_list_usage[] = {
 	NULL,
 };
 
-static int cmd_subvol_list(int argc, char **argv)
+static int cmd_subvol_list(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	struct btrfs_list_filter_set *filter_set;
 	struct btrfs_list_comparer_set *comparer_set;
@@ -649,7 +651,8 @@ static const char * const cmd_subvol_snapshot_usage[] = {
 	NULL
 };
 
-static int cmd_subvol_snapshot(int argc, char **argv)
+static int cmd_subvol_snapshot(const struct cmd_struct *cmd,
+			       int argc, char **argv)
 {
 	char	*subvol, *dst;
 	int	res, retval;
@@ -799,7 +802,8 @@ static const char * const cmd_subvol_get_default_usage[] = {
 	NULL
 };
 
-static int cmd_subvol_get_default(int argc, char **argv)
+static int cmd_subvol_get_default(const struct cmd_struct *cmd,
+				  int argc, char **argv)
 {
 	int fd = -1;
 	int ret;
@@ -867,7 +871,8 @@ static const char * const cmd_subvol_set_default_usage[] = {
 	NULL
 };
 
-static int cmd_subvol_set_default(int argc, char **argv)
+static int cmd_subvol_set_default(const struct cmd_struct *cmd,
+				  int argc, char **argv)
 {
 	int	ret=0, fd;
 	u64	objectid;
@@ -931,7 +936,8 @@ static const char * const cmd_subvol_find_new_usage[] = {
 	NULL
 };
 
-static int cmd_subvol_find_new(int argc, char **argv)
+static int cmd_subvol_find_new(const struct cmd_struct *cmd,
+			       int argc, char **argv)
 {
 	int fd;
 	int ret;
@@ -986,7 +992,7 @@ static const char * const cmd_subvol_show_usage[] = {
 	NULL
 };
 
-static int cmd_subvol_show(int argc, char **argv)
+static int cmd_subvol_show(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	struct root_info get_ri;
 	struct btrfs_list_filter_set *filter_set = NULL;
@@ -1337,7 +1343,7 @@ static int enumerate_dead_subvols(int fd, u64 **ids)
 	return idx;
 }
 
-static int cmd_subvol_sync(int argc, char **argv)
+static int cmd_subvol_sync(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	int fd = -1;
 	int i;
@@ -1448,7 +1454,8 @@ static const struct cmd_group subvolume_cmd_group = {
 	}
 };
 
-static int cmd_subvolume(int argc, char **argv)
+static int cmd_subvolume(const struct cmd_struct *unused,
+			 int argc, char **argv)
 {
 	return handle_command_group(&subvolume_cmd_group, argc, argv);
 }
commands.h +2 -2
index 9a65204b..4c5469ac 100644
@@ -24,7 +24,7 @@ enum {
 
 struct cmd_struct {
 	const char *token;
-	int (*fn)(int, char **);
+	int (*fn)(const struct cmd_struct *cmd, int argc, char **argv);
 
 	/*
 	 * Usage strings
@@ -110,7 +110,7 @@ struct cmd_group {
 static inline int cmd_execute(const struct cmd_struct *cmd,
 			      int argc, char **argv)
 {
-	return cmd->fn(argc, argv);
+	return cmd->fn(cmd, argc, argv);
 }
 
 int handle_command_group(const struct cmd_group *grp, int argc,
Signature · 1 line
2.12.3
#25 lore raw

PATCH v2 15/20 btrfs-progs: pass cmd_struct to clean_args_no_options{,_relaxed}

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

Now that we have a cmd_struct everywhere, we can pass it to clean_args_no_options and have it resolve the usage string from it there. This is necessary for it to pass the cmd_struct to usage() in the next patch.

---
 cmds-balance.c    |  6 +++---
 cmds-device.c     |  9 +++++----
 cmds-filesystem.c |  8 ++++----
 cmds-inspect.c    |  4 ++--
 cmds-qgroup.c     | 16 ++++++++--------
 cmds-quota.c      |  4 ++--
 cmds-rescue.c     |  4 ++--
 cmds-scrub.c      | 15 ++++++++-------
 cmds-subvolume.c  |  6 +++---
 help.c            |  9 +++++----
 help.h            |  7 ++++---
 11 files changed, 46 insertions(+), 42 deletions(-)
cmds-balance.c +3 -3
index 1bd7b3ce..488fffcc 100644
@@ -689,7 +689,7 @@ static int cmd_balance_pause(const struct cmd_struct *cmd,
 	int ret;
 	DIR *dirstream = NULL;
 
-	clean_args_no_options(argc, argv, cmd_balance_pause_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
 		usage(cmd_balance_pause_usage);
@@ -729,7 +729,7 @@ static int cmd_balance_cancel(const struct cmd_struct *cmd,
 	int ret;
 	DIR *dirstream = NULL;
 
-	clean_args_no_options(argc, argv, cmd_balance_cancel_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
 		usage(cmd_balance_cancel_usage);
@@ -770,7 +770,7 @@ static int cmd_balance_resume(const struct cmd_struct *cmd,
 	int fd;
 	int ret;
 
-	clean_args_no_options(argc, argv, cmd_balance_resume_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
 		usage(cmd_balance_resume_usage);
cmds-device.c +5 -4
index feb53f68..5be748f7 100644
@@ -149,11 +149,12 @@ static int _cmd_device_remove(const struct cmd_struct *cmd,
 	char	*mntpnt;
 	int i, fdmnt, ret = 0;
 	DIR	*dirstream = NULL;
+	const char * const *usagestr = cmd->usagestr;
 
-	clean_args_no_options(argc, argv, cmd->usagestr);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_min(argc - optind, 2))
-		usage(cmd->usagestr);
+		usage(usagestr);
 
 	mntpnt = argv[argc - 1];
 
@@ -347,7 +348,7 @@ static int cmd_device_ready(const struct cmd_struct *cmd, int argc, char **argv)
 	int	ret;
 	char	*path;
 
-	clean_args_no_options(argc, argv, cmd->usagestr);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
 		usage(cmd_device_ready_usage);
@@ -573,7 +574,7 @@ static int cmd_device_usage(const struct cmd_struct *cmd, int argc, char **argv)
 
 	unit_mode = get_unit_mode_from_arg(&argc, argv, 1);
 
-	clean_args_no_options(argc, argv, cmd->usagestr);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_min(argc - optind, 1))
 		usage(cmd_device_usage_usage);
cmds-filesystem.c +4 -4
index c2ee8595..b793532b 100644
@@ -127,7 +127,7 @@ static int cmd_filesystem_df(const struct cmd_struct *cmd,
 
 	unit_mode = get_unit_mode_from_arg(&argc, argv, 1);
 
-	clean_args_no_options(argc, argv, cmd_filesystem_df_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
 		usage(cmd_filesystem_df_usage);
@@ -822,7 +822,7 @@ static int cmd_filesystem_sync(const struct cmd_struct *cmd,
 	char	*path;
 	DIR	*dirstream = NULL;
 
-	clean_args_no_options(argc, argv, cmd_filesystem_sync_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
 		usage(cmd_filesystem_sync_usage);
@@ -1102,7 +1102,7 @@ static int cmd_filesystem_resize(const struct cmd_struct *cmd,
 	DIR	*dirstream = NULL;
 	struct stat st;
 
-	clean_args_no_options_relaxed(argc, argv, cmd_filesystem_resize_usage);
+	clean_args_no_options_relaxed(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 2))
 		usage(cmd_filesystem_resize_usage);
@@ -1175,7 +1175,7 @@ static const char * const cmd_filesystem_label_usage[] = {
 static int cmd_filesystem_label(const struct cmd_struct *cmd,
 				int argc, char **argv)
 {
-	clean_args_no_options(argc, argv, cmd_filesystem_label_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_min(argc - optind, 1) ||
 			check_argc_max(argc - optind, 2))
cmds-inspect.c +2 -2
index 1bdc8bd9..ece8c8d4 100644
@@ -277,7 +277,7 @@ static int cmd_inspect_subvolid_resolve(const struct cmd_struct *cmd,
 	char path[PATH_MAX];
 	DIR *dirstream = NULL;
 
-	clean_args_no_options(argc, argv, cmd_inspect_subvolid_resolve_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 2))
 		usage(cmd_inspect_subvolid_resolve_usage);
@@ -320,7 +320,7 @@ static int cmd_inspect_rootid(const struct cmd_struct *cmd,
 	u64 rootid;
 	DIR *dirstream = NULL;
 
-	clean_args_no_options(argc, argv, cmd_inspect_rootid_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
 		usage(cmd_inspect_rootid_usage);
cmds-qgroup.c +8 -8
index 2972baee..6e59c559 100644
@@ -33,8 +33,8 @@ static const char * const qgroup_cmd_group_usage[] = {
 	NULL
 };
 
-static int _cmd_qgroup_assign(int assign, int argc, char **argv,
-		const char * const *usage_str)
+static int _cmd_qgroup_assign(const struct cmd_struct *cmd, int assign,
+			      int argc, char **argv)
 {
 	int ret = 0;
 	int fd;
@@ -70,11 +70,11 @@ static int _cmd_qgroup_assign(int assign, int argc, char **argv,
 			}
 		}
 	} else {
-		clean_args_no_options(argc, argv, usage_str);
+		clean_args_no_options(cmd, argc, argv);
 	}
 
 	if (check_argc_exact(argc - optind, 3))
-		usage(usage_str);
+		usage(cmd->usagestr);
 
 	memset(&args, 0, sizeof(args));
 	args.assign = assign;
@@ -218,7 +218,7 @@ static const char * const cmd_qgroup_assign_usage[] = {
 static int cmd_qgroup_assign(const struct cmd_struct *cmd,
 			     int argc, char **argv)
 {
-	return _cmd_qgroup_assign(1, argc, argv, cmd_qgroup_assign_usage);
+	return _cmd_qgroup_assign(cmd, 1, argc, argv);
 }
 static DEFINE_SIMPLE_COMMAND(qgroup_assign, "assign");
 
@@ -231,7 +231,7 @@ static const char * const cmd_qgroup_remove_usage[] = {
 static int cmd_qgroup_remove(const struct cmd_struct *cmd,
 			     int argc, char **argv)
 {
-	return _cmd_qgroup_assign(0, argc, argv, cmd_qgroup_remove_usage);
+	return _cmd_qgroup_assign(cmd, 0, argc, argv);
 }
 static DEFINE_SIMPLE_COMMAND(qgroup_remove, "remove");
 
@@ -246,7 +246,7 @@ static int cmd_qgroup_create(const struct cmd_struct *cmd,
 {
 	int ret;
 
-	clean_args_no_options(argc, argv, cmd_qgroup_create_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	ret = _cmd_qgroup_create(1, argc, argv);
 
@@ -267,7 +267,7 @@ static int cmd_qgroup_destroy(const struct cmd_struct *cmd,
 {
 	int ret;
 
-	clean_args_no_options(argc, argv, cmd_qgroup_destroy_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	ret = _cmd_qgroup_create(0, argc, argv);
 
cmds-quota.c +2 -2
index a6e7a6f6..23757f9a 100644
@@ -71,7 +71,7 @@ static int cmd_quota_enable(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	int ret;
 
-	clean_args_no_options(argc, argv, cmd_quota_enable_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	ret = quota_ctl(BTRFS_QUOTA_CTL_ENABLE, argc, argv);
 
@@ -92,7 +92,7 @@ static int cmd_quota_disable(const struct cmd_struct *cmd,
 {
 	int ret;
 
-	clean_args_no_options(argc, argv, cmd_quota_disable_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	ret = quota_ctl(BTRFS_QUOTA_CTL_DISABLE, argc, argv);
 
cmds-rescue.c +2 -2
index f5a618e1..975ff05a 100644
@@ -170,7 +170,7 @@ static int cmd_rescue_zero_log(const struct cmd_struct *cmd,
 	char *devname;
 	int ret;
 
-	clean_args_no_options(argc, argv, cmd_rescue_zero_log_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc, 2))
 		usage(cmd_rescue_zero_log_usage);
@@ -223,7 +223,7 @@ static int cmd_rescue_fix_device_size(const struct cmd_struct *cmd,
 	char *devname;
 	int ret;
 
-	clean_args_no_options(argc, argv, cmd_rescue_fix_device_size_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc, 2))
 		usage(cmd_rescue_fix_device_size_usage);
cmds-scrub.c +8 -7
index a762f035..9917a2f4 100644
@@ -1097,8 +1097,7 @@ static int is_scrub_running_in_kernel(int fd,
 static const char * const cmd_scrub_start_usage[];
 static const char * const cmd_scrub_resume_usage[];
 
-static int scrub_start(const struct cmd_struct *cmd, int argc, char **argv,
-		       bool resume)
+static int scrub_start(int argc, char **argv, bool resume)
 {
 	int fdmnt;
 	int prg_fd = -1;
@@ -1177,14 +1176,16 @@ static int scrub_start(const struct cmd_struct *cmd, int argc, char **argv,
 			break;
 		case '?':
 		default:
-			usage(cmd->usagestr);
+			usage(resume ? cmd_scrub_resume_usage :
+						cmd_scrub_start_usage);
 		}
 	}
 
 	/* try to catch most error cases before forking */
 
 	if (check_argc_exact(argc - optind, 1)) {
-		usage(cmd->usagestr);
+		usage(resume ? cmd_scrub_resume_usage :
+					cmd_scrub_start_usage);
 	}
 
 	spc.progress = NULL;
@@ -1577,7 +1578,7 @@ static const char * const cmd_scrub_start_usage[] = {
 
 static int cmd_scrub_start(const struct cmd_struct *cmd, int argc, char **argv)
 {
-	return scrub_start(cmd, argc, argv, false);
+	return scrub_start(argc, argv, false);
 }
 static DEFINE_SIMPLE_COMMAND(scrub_start, "start");
 
@@ -1594,7 +1595,7 @@ static int cmd_scrub_cancel(const struct cmd_struct *cmd, int argc, char **argv)
 	int fdmnt = -1;
 	DIR *dirstream = NULL;
 
-	clean_args_no_options(argc, argv, cmd_scrub_cancel_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
 		usage(cmd_scrub_cancel_usage);
@@ -1644,7 +1645,7 @@ static const char * const cmd_scrub_resume_usage[] = {
 
 static int cmd_scrub_resume(const struct cmd_struct *cmd, int argc, char **argv)
 {
-	return scrub_start(cmd, argc, argv, true);
+	return scrub_start(argc, argv, true);
 }
 static DEFINE_SIMPLE_COMMAND(scrub_resume, "resume");
 
cmds-subvolume.c +3 -3
index 13303db8..c577cc23 100644
@@ -812,7 +812,7 @@ static int cmd_subvol_get_default(const struct cmd_struct *cmd,
 	u64 default_id;
 	DIR *dirstream = NULL;
 
-	clean_args_no_options(argc, argv, cmd_subvol_get_default_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
 		usage(cmd_subvol_get_default_usage);
@@ -880,7 +880,7 @@ static int cmd_subvol_set_default(const struct cmd_struct *cmd,
 	char	*subvolid;
 	DIR	*dirstream = NULL;
 
-	clean_args_no_options(argc, argv, cmd_subvol_set_default_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_min(argc - optind, 1) ||
 			check_argc_max(argc - optind, 2))
@@ -945,7 +945,7 @@ static int cmd_subvol_find_new(const struct cmd_struct *cmd,
 	u64 last_gen;
 	DIR *dirstream = NULL;
 
-	clean_args_no_options(argc, argv, cmd_subvol_find_new_usage);
+	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 2))
 		usage(cmd_subvol_find_new_usage);
help.c +5 -4
index b7f06aae..23d6ea8f 100644
@@ -86,7 +86,7 @@ int check_argc_max(int nargs, int expected)
  * Unknown short and long options are reported, optionally the @usage is printed
  * before exit.
  */
-void clean_args_no_options(int argc, char *argv[], const char * const *usagestr)
+void clean_args_no_options(const struct cmd_struct *cmd, int argc, char *argv[])
 {
 	static const struct option long_options[] = {
 		{NULL, 0, NULL, 0}
@@ -100,8 +100,8 @@ void clean_args_no_options(int argc, char *argv[], const char * const *usagestr)
 
 		switch (c) {
 		default:
-			if (usagestr)
-				usage(usagestr);
+			if (cmd->usagestr)
+				usage(cmd->usagestr);
 		}
 	}
 }
@@ -115,7 +115,8 @@ void clean_args_no_options(int argc, char *argv[], const char * const *usagestr)
  * - "-- option1 option2 ..."
  * - "option1 option2 ..."
  */
-void clean_args_no_options_relaxed(int argc, char *argv[], const char * const *usagestr)
+void clean_args_no_options_relaxed(const struct cmd_struct *cmd,
+				   int argc, char *argv[])
 {
 	if (argc <= 1)
 		return;
help.h +4 -3
index a69ea6b2..e642f58d 100644
@@ -71,9 +71,10 @@ void help_command_group(const struct cmd_group *grp, int argc, char **argv);
 int check_argc_exact(int nargs, int expected);
 int check_argc_min(int nargs, int expected);
 int check_argc_max(int nargs, int expected);
-void clean_args_no_options(int argc, char *argv[], const char * const *usage);
-void clean_args_no_options_relaxed(int argc, char *argv[],
-		const char * const *usagestr);
+void clean_args_no_options(const struct cmd_struct *cmd,
+			   int argc, char *argv[]);
+void clean_args_no_options_relaxed(const struct cmd_struct *cmd,
+				   int argc, char *argv[]);
 
 void fixup_argv0(char **argv, const char *token);
 void set_argv0(char **argv);
Signature · 1 line
2.12.3
#26 lore raw

PATCH v2 16/20 btrfs-progs: pass cmd_struct to usage()

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

Now that every call site has a cmd_struct, we can just pass the cmd_struct to usage to print the usager information. This allows us to interpret the format flags we'll add later in this series to inform the user of which output formats any given command supports.

---
 btrfs-calc-size.c         |  2 +-
 btrfs-debug-tree.c        |  2 +-
 btrfs-show-super.c        |  2 +-
 check/main.c              |  4 ++--
 cmds-balance.c            | 14 +++++++-------
 cmds-device.c             | 19 +++++++++----------
 cmds-fi-du.c              |  4 ++--
 cmds-fi-usage.c           |  4 ++--
 cmds-filesystem.c         | 18 +++++++++---------
 cmds-inspect-dump-super.c |  4 ++--
 cmds-inspect-dump-tree.c  |  4 ++--
 cmds-inspect-tree-stats.c |  4 ++--
 cmds-inspect.c            | 16 ++++++++--------
 cmds-property.c           | 22 +++++++++-------------
 cmds-qgroup.c             | 18 +++++++++---------
 cmds-quota.c              |  8 ++++----
 cmds-receive.c            |  4 ++--
 cmds-replace.c            | 12 ++++++------
 cmds-rescue.c             | 12 ++++++------
 cmds-restore.c            |  8 ++++----
 cmds-scrub.c              | 25 ++++++++++---------------
 cmds-send.c               |  2 +-
 cmds-subvolume.c          | 30 +++++++++++++++---------------
 help.c                    |  6 +++---
 help.h                    |  2 +-
 25 files changed, 118 insertions(+), 128 deletions(-)
btrfs-calc-size.c +1 -1
index 908e830f..4c8fcc19 100644
@@ -30,7 +30,7 @@ int main(int argc, char **argv)
 "\nthe tool has been deprecated, please use 'btrfs inspect-internal tree-stats' instead\n");
 
 	if (argc > 1 && !strcmp(argv[1], "--help"))
-		usage(cmd->usagestr);
+		usage(cmd);
 
 	ret = cmd_execute(cmd, argc, argv);
 
btrfs-debug-tree.c +1 -1
index 7f254519..49a2e949 100644
@@ -30,7 +30,7 @@ int main(int argc, char **argv)
 	set_argv0(argv);
 
 	if (argc > 1 && !strcmp(argv[1], "--help"))
-		usage(cmd->usagestr);
+		usage(cmd);
 
 	radix_tree_init();
 
btrfs-show-super.c +1 -1
index ee717c33..b4a5b693 100644
@@ -31,7 +31,7 @@ int main(int argc, char **argv)
 "\nthe tool has been deprecated, please use 'btrfs inspect-internal dump-super' instead\n");
 
 	if (argc > 1 && !strcmp(argv[1], "--help"))
-		usage(cmd->usagestr);
+		usage(cmd);
 
 	ret = cmd_execute(cmd, argc, argv);
 
check/main.c +2 -2
index bd31fb9f..0bb8633a 100644
@@ -9530,7 +9530,7 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
 				break;
 			case '?':
 			case 'h':
-				usage(cmd_check_usage);
+				usage(cmd);
 			case GETOPT_VAL_REPAIR:
 				printf("enabling repair mode\n");
 				repair = 1;
@@ -9581,7 +9581,7 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
 	}
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_check_usage);
+		usage(cmd);
 
 	if (ctx.progress_enabled) {
 		ctx.tp = TASK_NOTHING;
cmds-balance.c +7 -7
index 488fffcc..c639459f 100644
@@ -585,12 +585,12 @@ static int cmd_balance_start(const struct cmd_struct *cmd,
 			background = 1;
 			break;
 		default:
-			usage(cmd_balance_start_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_balance_start_usage);
+		usage(cmd);
 
 	/*
 	 * allow -s only under --force, otherwise do with system chunks
@@ -692,7 +692,7 @@ static int cmd_balance_pause(const struct cmd_struct *cmd,
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_balance_pause_usage);
+		usage(cmd);
 
 	path = argv[optind];
 
@@ -732,7 +732,7 @@ static int cmd_balance_cancel(const struct cmd_struct *cmd,
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_balance_cancel_usage);
+		usage(cmd);
 
 	path = argv[optind];
 
@@ -773,7 +773,7 @@ static int cmd_balance_resume(const struct cmd_struct *cmd,
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_balance_resume_usage);
+		usage(cmd);
 
 	path = argv[optind];
 
@@ -856,12 +856,12 @@ static int cmd_balance_status(const struct cmd_struct *cmd,
 			verbose = 1;
 			break;
 		default:
-			usage(cmd_balance_status_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_balance_status_usage);
+		usage(cmd);
 
 	path = argv[optind];
 
cmds-device.c +9 -10
index 5be748f7..6c74ca8e 100644
@@ -77,12 +77,12 @@ static int cmd_device_add(const struct cmd_struct *cmd,
 			force = 1;
 			break;
 		default:
-			usage(cmd_device_add_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_min(argc - optind, 2))
-		usage(cmd_device_add_usage);
+		usage(cmd);
 
 	last_dev = argc - 1;
 	mntpnt = argv[last_dev];
@@ -149,12 +149,11 @@ static int _cmd_device_remove(const struct cmd_struct *cmd,
 	char	*mntpnt;
 	int i, fdmnt, ret = 0;
 	DIR	*dirstream = NULL;
-	const char * const *usagestr = cmd->usagestr;
 
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_min(argc - optind, 2))
-		usage(usagestr);
+		usage(cmd);
 
 	mntpnt = argv[argc - 1];
 
@@ -290,13 +289,13 @@ static int cmd_device_scan(const struct cmd_struct *cmd, int argc, char **argv)
 			all = 1;
 			break;
 		default:
-			usage(cmd_device_scan_usage);
+			usage(cmd);
 		}
 	}
 	devstart = optind;
 
 	if (all && check_argc_max(argc - optind, 1))
-		usage(cmd_device_scan_usage);
+		usage(cmd);
 
 	if (all || argc - optind == 0) {
 		printf("Scanning for Btrfs filesystems\n");
@@ -351,7 +350,7 @@ static int cmd_device_ready(const struct cmd_struct *cmd, int argc, char **argv)
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_device_ready_usage);
+		usage(cmd);
 
 	fd = open("/dev/btrfs-control", O_RDWR);
 	if (fd < 0) {
@@ -434,12 +433,12 @@ static int cmd_device_stats(const struct cmd_struct *cmd, int argc, char **argv)
 			break;
 		case '?':
 		default:
-			usage(cmd_device_stats_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_device_stats_usage);
+		usage(cmd);
 
 	dev_path = argv[optind];
 
@@ -577,7 +576,7 @@ static int cmd_device_usage(const struct cmd_struct *cmd, int argc, char **argv)
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_min(argc - optind, 1))
-		usage(cmd_device_usage_usage);
+		usage(cmd);
 
 	for (i = optind; i < argc; i++) {
 		int fd;
cmds-fi-du.c +2 -2
index a86f4ad6..ebcb0c15 100644
@@ -580,12 +580,12 @@ static int cmd_filesystem_du(const struct cmd_struct *cmd,
 			summarize = 1;
 			break;
 		default:
-			usage(cmd_filesystem_du_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_min(argc - optind, 1))
-		usage(cmd_filesystem_du_usage);
+		usage(cmd);
 
 	kernel_version = get_running_kernel_version();
 
cmds-fi-usage.c +2 -2
index 36684762..6da96411 100644
@@ -988,12 +988,12 @@ static int cmd_filesystem_usage(const struct cmd_struct *cmd,
 			tabular = 1;
 			break;
 		default:
-			usage(cmd_filesystem_usage_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_min(argc - optind, 1))
-		usage(cmd_filesystem_usage_usage);
+		usage(cmd);
 
 	for (i = optind; i < argc; i++) {
 		int fd;
cmds-filesystem.c +9 -9
index b793532b..8ddb7ea5 100644
@@ -130,7 +130,7 @@ static int cmd_filesystem_df(const struct cmd_struct *cmd,
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_filesystem_df_usage);
+		usage(cmd);
 
 	path = argv[optind];
 
@@ -705,17 +705,17 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
 			where = BTRFS_SCAN_MOUNTED;
 			break;
 		default:
-			usage(cmd_filesystem_show_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_max(argc, optind + 1))
-		usage(cmd_filesystem_show_usage);
+		usage(cmd);
 
 	if (argc > optind) {
 		search = argv[optind];
 		if (*search == 0)
-			usage(cmd_filesystem_show_usage);
+			usage(cmd);
 		type = check_arg_type(search);
 
 		/*
@@ -825,7 +825,7 @@ static int cmd_filesystem_sync(const struct cmd_struct *cmd,
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_filesystem_sync_usage);
+		usage(cmd);
 
 	path = argv[optind];
 
@@ -974,12 +974,12 @@ static int cmd_filesystem_defrag(const struct cmd_struct *cmd,
 			recursive = 1;
 			break;
 		default:
-			usage(cmd_filesystem_defrag_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_min(argc - optind, 1))
-		usage(cmd_filesystem_defrag_usage);
+		usage(cmd);
 
 	memset(&defrag_global_range, 0, sizeof(defrag_global_range));
 	defrag_global_range.start = start;
@@ -1105,7 +1105,7 @@ static int cmd_filesystem_resize(const struct cmd_struct *cmd,
 	clean_args_no_options_relaxed(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 2))
-		usage(cmd_filesystem_resize_usage);
+		usage(cmd);
 
 	amount = argv[optind];
 	path = argv[optind + 1];
@@ -1179,7 +1179,7 @@ static int cmd_filesystem_label(const struct cmd_struct *cmd,
 
 	if (check_argc_min(argc - optind, 1) ||
 			check_argc_max(argc - optind, 2))
-		usage(cmd_filesystem_label_usage);
+		usage(cmd);
 
 	if (argc - optind > 1) {
 		return set_label(argv[optind], argv[optind + 1]);
cmds-inspect-dump-super.c +2 -2
index ca503a2e..6341d2ac 100644
@@ -573,12 +573,12 @@ static int cmd_inspect_dump_super(const struct cmd_struct *cmd,
 			all = 0;
 			break;
 		default:
-			usage(cmd_inspect_dump_super_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_min(argc - optind, 1))
-		usage(cmd_inspect_dump_super_usage);
+		usage(cmd);
 
 	for (i = optind; i < argc; i++) {
 		filename = argv[i];
cmds-inspect-dump-tree.c +2 -2
index 5cc39a88..22bc9cb9 100644
@@ -288,12 +288,12 @@ static int cmd_inspect_dump_tree(const struct cmd_struct *cmd,
 			break;
 			}
 		default:
-			usage(cmd_inspect_dump_tree_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_inspect_dump_tree_usage);
+		usage(cmd);
 
 	ret = check_arg_type(argv[optind]);
 	if (ret != BTRFS_ARG_BLKDEV && ret != BTRFS_ARG_REG) {
cmds-inspect-tree-stats.c +2 -2
index 64ca3d0b..e5e68562 100644
@@ -444,12 +444,12 @@ static int cmd_inspect_tree_stats(const struct cmd_struct *cmd,
 			no_pretty = 1;
 			break;
 		default:
-			usage(cmd_inspect_tree_stats_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 1)) {
-		usage(cmd_inspect_tree_stats_usage);
+		usage(cmd);
 	}
 
 	ret = check_mounted(argv[optind]);
cmds-inspect.c +8 -8
index ece8c8d4..bc86e999 100644
@@ -105,12 +105,12 @@ static int cmd_inspect_inode_resolve(const struct cmd_struct *cmd,
 			verbose = 1;
 			break;
 		default:
-			usage(cmd_inspect_inode_resolve_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 2))
-		usage(cmd_inspect_inode_resolve_usage);
+		usage(cmd);
 
 	fd = btrfs_open_dir(argv[optind + 1], &dirstream, 1);
 	if (fd < 0)
@@ -167,12 +167,12 @@ static int cmd_inspect_logical_resolve(const struct cmd_struct *cmd,
 			size = arg_strtou64(optarg);
 			break;
 		default:
-			usage(cmd_inspect_logical_resolve_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 2))
-		usage(cmd_inspect_logical_resolve_usage);
+		usage(cmd);
 
 	size = min(size, (u64)SZ_64K);
 	inodes = malloc(size);
@@ -280,7 +280,7 @@ static int cmd_inspect_subvolid_resolve(const struct cmd_struct *cmd,
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 2))
-		usage(cmd_inspect_subvolid_resolve_usage);
+		usage(cmd);
 
 	fd = btrfs_open_dir(argv[optind + 1], &dirstream, 1);
 	if (fd < 0) {
@@ -323,7 +323,7 @@ static int cmd_inspect_rootid(const struct cmd_struct *cmd,
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_inspect_rootid_usage);
+		usage(cmd);
 
 	fd = btrfs_open_file_or_dir(argv[optind], &dirstream, 1);
 	if (fd < 0) {
@@ -617,11 +617,11 @@ static int cmd_inspect_min_dev_size(const struct cmd_struct *cmd,
 			devid = arg_strtou64(optarg);
 			break;
 		default:
-			usage(cmd_inspect_min_dev_size_usage);
+			usage(cmd);
 		}
 	}
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_inspect_min_dev_size_usage);
+		usage(cmd);
 
 	fd = btrfs_open_dir(argv[optind], &dirstream, 1);
 	if (fd < 0) {
cmds-property.c +9 -13
index 5684443c..4aa2f18f 100644
@@ -256,8 +256,7 @@ out:
 
 }
 
-static void parse_args(int argc, char **argv,
-		       const char * const *usage_str,
+static void parse_args(const struct cmd_struct *cmd, int argc, char **argv,
 		       int *types, char **object,
 		       char **name, char **value, int min_nonopt_args)
 {
@@ -276,7 +275,7 @@ static void parse_args(int argc, char **argv,
 			type_str = optarg;
 			break;
 		default:
-			usage(usage_str);
+			usage(cmd);
 		}
 	}
 
@@ -287,7 +286,7 @@ static void parse_args(int argc, char **argv,
 
 	if (check_argc_min(argc - optind, min_nonopt_args) ||
 	    check_argc_max(argc - optind, max_nonopt_args))
-		usage(usage_str);
+		usage(cmd);
 
 	*types = 0;
 	if (type_str) {
@@ -304,7 +303,7 @@ static void parse_args(int argc, char **argv,
 			*types = prop_object_dev;
 		} else {
 			error("invalid object type: %s", type_str);
-			usage(usage_str);
+			usage(cmd);
 		}
 	}
 
@@ -319,11 +318,11 @@ static void parse_args(int argc, char **argv,
 		if (ret < 0) {
 			error("failed to detect object type: %s",
 				strerror(-ret));
-			usage(usage_str);
+			usage(cmd);
 		}
 		if (!*types) {
 			error("object is not a btrfs object: %s", *object);
-			usage(usage_str);
+			usage(cmd);
 		}
 	}
 }
@@ -349,8 +348,7 @@ static int cmd_property_get(const struct cmd_struct *cmd,
 	char *name = NULL;
 	int types = 0;
 
-	parse_args(argc, argv, cmd_property_get_usage, &types, &object, &name,
-		   NULL, 1);
+	parse_args(cmd, argc, argv, &types, &object, &name, NULL, 1);
 
 	if (name)
 		ret = setget_prop(types, object, name, NULL);
@@ -378,8 +376,7 @@ static int cmd_property_set(const struct cmd_struct *cmd,
 	char *value = NULL;
 	int types = 0;
 
-	parse_args(argc, argv, cmd_property_set_usage, &types,
-		   &object, &name, &value, 3);
+	parse_args(cmd, argc, argv, &types, &object, &name, &value, 3);
 
 	ret = setget_prop(types, object, name, value);
 
@@ -402,8 +399,7 @@ static int cmd_property_list(const struct cmd_struct *cmd,
 	char *object = NULL;
 	int types = 0;
 
-	parse_args(argc, argv, cmd_property_list_usage,
-		   &types, &object, NULL, NULL, 1);
+	parse_args(cmd, argc, argv, &types, &object, NULL, NULL, 1);
 
 	ret = dump_props(types, object, 1);
 
cmds-qgroup.c +9 -9
index 6e59c559..986f272c 100644
@@ -74,7 +74,7 @@ static int _cmd_qgroup_assign(const struct cmd_struct *cmd, int assign,
 	}
 
 	if (check_argc_exact(argc - optind, 3))
-		usage(cmd->usagestr);
+		usage(cmd);
 
 	memset(&args, 0, sizeof(args));
 	args.assign = assign;
@@ -251,7 +251,7 @@ static int cmd_qgroup_create(const struct cmd_struct *cmd,
 	ret = _cmd_qgroup_create(1, argc, argv);
 
 	if (ret < 0)
-		usage(cmd_qgroup_create_usage);
+		usage(cmd);
 	return ret;
 }
 static DEFINE_SIMPLE_COMMAND(qgroup_create, "create");
@@ -272,7 +272,7 @@ static int cmd_qgroup_destroy(const struct cmd_struct *cmd,
 	ret = _cmd_qgroup_create(0, argc, argv);
 
 	if (ret < 0)
-		usage(cmd_qgroup_destroy_usage);
+		usage(cmd);
 	return ret;
 }
 static DEFINE_SIMPLE_COMMAND(qgroup_destroy, "destroy");
@@ -366,7 +366,7 @@ static int cmd_qgroup_show(const struct cmd_struct *cmd, int argc, char **argv)
 			ret = btrfs_qgroup_parse_sort_string(optarg,
 							     &comparer_set);
 			if (ret)
-				usage(cmd_qgroup_show_usage);
+				usage(cmd);
 			break;
 		case GETOPT_VAL_SYNC:
 			sync = 1;
@@ -375,13 +375,13 @@ static int cmd_qgroup_show(const struct cmd_struct *cmd, int argc, char **argv)
 			verbose = true;
 			break;
 		default:
-			usage(cmd_qgroup_show_usage);
+			usage(cmd);
 		}
 	}
 	btrfs_qgroup_setup_units(unit_mode);
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_qgroup_show_usage);
+		usage(cmd);
 
 	path = argv[optind];
 	fd = btrfs_open_dir(path, &dirstream, 1);
@@ -457,12 +457,12 @@ static int cmd_qgroup_limit(const struct cmd_struct *cmd, int argc, char **argv)
 			exclusive = 1;
 			break;
 		default:
-			usage(cmd_qgroup_limit_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_min(argc - optind, 2))
-		usage(cmd_qgroup_limit_usage);
+		usage(cmd);
 
 	if (!parse_limit(argv[optind], &size)) {
 		error("invalid size argument: %s", argv[optind]);
@@ -501,7 +501,7 @@ static int cmd_qgroup_limit(const struct cmd_struct *cmd, int argc, char **argv)
 		args.qgroupid = parse_qgroupid(argv[optind + 1]);
 		path = argv[optind + 2];
 	} else
-		usage(cmd_qgroup_limit_usage);
+		usage(cmd);
 
 	fd = btrfs_open_dir(path, &dirstream, 1);
 	if (fd < 0)
cmds-quota.c +4 -4
index 23757f9a..c634c4e9 100644
@@ -76,7 +76,7 @@ static int cmd_quota_enable(const struct cmd_struct *cmd, int argc, char **argv)
 	ret = quota_ctl(BTRFS_QUOTA_CTL_ENABLE, argc, argv);
 
 	if (ret < 0)
-		usage(cmd_quota_enable_usage);
+		usage(cmd);
 	return ret;
 }
 static DEFINE_SIMPLE_COMMAND(quota_enable, "enable");
@@ -97,7 +97,7 @@ static int cmd_quota_disable(const struct cmd_struct *cmd,
 	ret = quota_ctl(BTRFS_QUOTA_CTL_DISABLE, argc, argv);
 
 	if (ret < 0)
-		usage(cmd_quota_disable_usage);
+		usage(cmd);
 	return ret;
 }
 static DEFINE_SIMPLE_COMMAND(quota_disable, "disable");
@@ -140,7 +140,7 @@ static int cmd_quota_rescan(const struct cmd_struct *cmd, int argc, char **argv)
 			wait_for_completion = 1;
 			break;
 		default:
-			usage(cmd_quota_rescan_usage);
+			usage(cmd);
 		}
 	}
 
@@ -150,7 +150,7 @@ static int cmd_quota_rescan(const struct cmd_struct *cmd, int argc, char **argv)
 	}
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_quota_rescan_usage);
+		usage(cmd);
 
 	memset(&args, 0, sizeof(args));
 
cmds-receive.c +2 -2
index 93c1838d..5429c607 100644
@@ -1352,9 +1352,9 @@ static int cmd_receive(const struct cmd_struct *cmd, int argc, char **argv)
 	}
 
 	if (dump && check_argc_exact(argc - optind, 0))
-		usage(cmd_receive_usage);
+		usage(cmd);
 	if (!dump && check_argc_exact(argc - optind, 1))
-		usage(cmd_receive_usage);
+		usage(cmd);
 
 	tomnt = argv[optind];
 
cmds-replace.c +6 -6
index f1e76bdf..2057d69e 100644
@@ -148,7 +148,7 @@ static int cmd_replace_start(const struct cmd_struct *cmd,
 			break;
 		case '?':
 		default:
-			usage(cmd_replace_start_usage);
+			usage(cmd);
 		}
 	}
 
@@ -157,7 +157,7 @@ static int cmd_replace_start(const struct cmd_struct *cmd,
 		 BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID :
 		 BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS;
 	if (check_argc_exact(argc - optind, 3))
-		usage(cmd_replace_start_usage);
+		usage(cmd);
 	path = argv[optind + 2];
 
 	fdmnt = open_path_or_dev_mnt(path, &dirstream, 1);
@@ -343,12 +343,12 @@ static int cmd_replace_status(const struct cmd_struct *cmd,
 			break;
 		case '?':
 		default:
-			usage(cmd_replace_status_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_replace_status_usage);
+		usage(cmd);
 
 	path = argv[optind];
 	fd = btrfs_open_dir(path, &dirstream, 1);
@@ -510,12 +510,12 @@ static int cmd_replace_cancel(const struct cmd_struct *cmd,
 		switch (c) {
 		case '?':
 		default:
-			usage(cmd_replace_cancel_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_replace_cancel_usage);
+		usage(cmd);
 
 	path = argv[optind];
 	fd = btrfs_open_dir(path, &dirstream, 1);
cmds-rescue.c +6 -6
index 975ff05a..f96d8010 100644
@@ -66,12 +66,12 @@ static int cmd_rescue_chunk_recover(const struct cmd_struct *cmd,
 			break;
 		case 'h':
 		default:
-			usage(cmd_rescue_chunk_recover_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_rescue_chunk_recover_usage);
+		usage(cmd);
 
 	file = argv[optind];
 
@@ -134,11 +134,11 @@ static int cmd_rescue_super_recover(const struct cmd_struct *cmd,
 			yes = 1;
 			break;
 		default:
-			usage(cmd_rescue_super_recover_usage);
+			usage(cmd);
 		}
 	}
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_rescue_super_recover_usage);
+		usage(cmd);
 
 	dname = argv[optind];
 	ret = check_mounted(dname);
@@ -173,7 +173,7 @@ static int cmd_rescue_zero_log(const struct cmd_struct *cmd,
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc, 2))
-		usage(cmd_rescue_zero_log_usage);
+		usage(cmd);
 
 	devname = argv[optind];
 	ret = check_mounted(devname);
@@ -226,7 +226,7 @@ static int cmd_rescue_fix_device_size(const struct cmd_struct *cmd,
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc, 2))
-		usage(cmd_rescue_fix_device_size_usage);
+		usage(cmd);
 
 	devname = argv[optind];
 	ret = check_mounted(devname);
cmds-restore.c +4 -4
index e850ec97..87cfb582 100644
@@ -1415,7 +1415,7 @@ static const char * const cmd_restore_usage[] = {
 	NULL
 };
 
-static int cmd_restore(const struct cmd_struct *unused, int argc, char **argv)
+static int cmd_restore(const struct cmd_struct *cmd, int argc, char **argv)
 {
 	struct btrfs_root *root;
 	struct btrfs_key key;
@@ -1518,14 +1518,14 @@ static int cmd_restore(const struct cmd_struct *unused, int argc, char **argv)
 				get_xattrs = 1;
 				break;
 			default:
-				usage(cmd_restore_usage);
+				usage(cmd);
 		}
 	}
 
 	if (!list_roots && check_argc_min(argc - optind, 2))
-		usage(cmd_restore_usage);
+		usage(cmd);
 	else if (list_roots && check_argc_min(argc - optind, 1))
-		usage(cmd_restore_usage);
+		usage(cmd);
 
 	if (fs_location && root_objectid) {
 		fprintf(stderr, "don't use -f and -r at the same time.\n");
cmds-scrub.c +10 -15
index 9917a2f4..872c996b 100644
@@ -1094,10 +1094,8 @@ static int is_scrub_running_in_kernel(int fd,
 	return 0;
 }
 
-static const char * const cmd_scrub_start_usage[];
-static const char * const cmd_scrub_resume_usage[];
-
-static int scrub_start(int argc, char **argv, bool resume)
+static int scrub_start(const struct cmd_struct *cmd, int argc, char **argv,
+		       bool resume)
 {
 	int fdmnt;
 	int prg_fd = -1;
@@ -1176,17 +1174,14 @@ static int scrub_start(int argc, char **argv, bool resume)
 			break;
 		case '?':
 		default:
-			usage(resume ? cmd_scrub_resume_usage :
-						cmd_scrub_start_usage);
+			usage(cmd);
 		}
 	}
 
 	/* try to catch most error cases before forking */
 
-	if (check_argc_exact(argc - optind, 1)) {
-		usage(resume ? cmd_scrub_resume_usage :
-					cmd_scrub_start_usage);
-	}
+	if (check_argc_exact(argc - optind, 1))
+		usage(cmd);
 
 	spc.progress = NULL;
 	if (do_quiet && do_print)
@@ -1578,7 +1573,7 @@ static const char * const cmd_scrub_start_usage[] = {
 
 static int cmd_scrub_start(const struct cmd_struct *cmd, int argc, char **argv)
 {
-	return scrub_start(argc, argv, false);
+	return scrub_start(cmd, argc, argv, false);
 }
 static DEFINE_SIMPLE_COMMAND(scrub_start, "start");
 
@@ -1598,7 +1593,7 @@ static int cmd_scrub_cancel(const struct cmd_struct *cmd, int argc, char **argv)
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_scrub_cancel_usage);
+		usage(cmd);
 
 	path = argv[optind];
 
@@ -1645,7 +1640,7 @@ static const char * const cmd_scrub_resume_usage[] = {
 
 static int cmd_scrub_resume(const struct cmd_struct *cmd, int argc, char **argv)
 {
-	return scrub_start(argc, argv, true);
+	return scrub_start(cmd, argc, argv, true);
 }
 static DEFINE_SIMPLE_COMMAND(scrub_resume, "resume");
 
@@ -1691,12 +1686,12 @@ static int cmd_scrub_status(const struct cmd_struct *cmd, int argc, char **argv)
 			break;
 		case '?':
 		default:
-			usage(cmd_scrub_status_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_scrub_status_usage);
+		usage(cmd);
 
 	path = argv[optind];
 
cmds-send.c +1 -1
index bd501576..e2d87785 100644
@@ -643,7 +643,7 @@ static int cmd_send(const struct cmd_struct *cmd, int argc, char **argv)
 	}
 
 	if (check_argc_min(argc - optind, 1))
-		usage(cmd_send_usage);
+		usage(cmd);
 
 	if (outname[0]) {
 		int tmpfd;
cmds-subvolume.c +15 -15
index c577cc23..dc529315 100644
@@ -150,12 +150,12 @@ static int cmd_subvol_create(const struct cmd_struct *cmd,
 			}
 			break;
 		default:
-			usage(cmd_subvol_create_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_subvol_create_usage);
+		usage(cmd);
 
 	dst = argv[optind];
 
@@ -295,12 +295,12 @@ static int cmd_subvol_delete(const struct cmd_struct *cmd,
 			verbose++;
 			break;
 		default:
-			usage(cmd_subvol_delete_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_min(argc - optind, 1))
-		usage(cmd_subvol_delete_usage);
+		usage(cmd);
 
 	if (verbose > 0) {
 		printf("Transaction commit: %s\n",
@@ -633,7 +633,7 @@ out:
 	if (comparer_set)
 		free(comparer_set);
 	if (uerr)
-		usage(cmd_subvol_list_usage);
+		usage(cmd);
 	return !!ret;
 }
 static DEFINE_SIMPLE_COMMAND(subvol_list, "list");
@@ -698,12 +698,12 @@ static int cmd_subvol_snapshot(const struct cmd_struct *cmd,
 			}
 			break;
 		default:
-			usage(cmd_subvol_snapshot_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 2))
-		usage(cmd_subvol_snapshot_usage);
+		usage(cmd);
 
 	subvol = argv[optind];
 	dst = argv[optind + 1];
@@ -815,7 +815,7 @@ static int cmd_subvol_get_default(const struct cmd_struct *cmd,
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_subvol_get_default_usage);
+		usage(cmd);
 
 	subvol = argv[1];
 	fd = btrfs_open_dir(subvol, &dirstream, 1);
@@ -884,7 +884,7 @@ static int cmd_subvol_set_default(const struct cmd_struct *cmd,
 
 	if (check_argc_min(argc - optind, 1) ||
 			check_argc_max(argc - optind, 2))
-		usage(cmd_subvol_set_default_usage);
+		usage(cmd);
 
 	if (argc - optind == 1) {
 		/* path to the subvolume is specified */
@@ -948,7 +948,7 @@ static int cmd_subvol_find_new(const struct cmd_struct *cmd,
 	clean_args_no_options(cmd, argc, argv);
 
 	if (check_argc_exact(argc - optind, 2))
-		usage(cmd_subvol_find_new_usage);
+		usage(cmd);
 
 	subvol = argv[optind];
 	last_gen = arg_strtou64(argv[optind + 1]);
@@ -1037,17 +1037,17 @@ static int cmd_subvol_show(const struct cmd_struct *cmd, int argc, char **argv)
 			by_uuid = 1;
 			break;
 		default:
-			usage(cmd_subvol_show_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_exact(argc - optind, 1))
-		usage(cmd_subvol_show_usage);
+		usage(cmd);
 
 	if (by_rootid && by_uuid) {
 		error(
 		"options --rootid and --uuid cannot be used at the same time");
-		usage(cmd_subvol_show_usage);
+		usage(cmd);
 	}
 
 	memset(&get_ri, 0, sizeof(get_ri));
@@ -1369,12 +1369,12 @@ static int cmd_subvol_sync(const struct cmd_struct *cmd, int argc, char **argv)
 			}
 			break;
 		default:
-			usage(cmd_subvol_sync_usage);
+			usage(cmd);
 		}
 	}
 
 	if (check_argc_min(argc - optind, 1))
-		usage(cmd_subvol_sync_usage);
+		usage(cmd);
 
 	fd = btrfs_open_dir(argv[optind], &dirstream, 1);
 	if (fd < 0) {
help.c +3 -3
index 23d6ea8f..6ee93161 100644
@@ -101,7 +101,7 @@ void clean_args_no_options(const struct cmd_struct *cmd, int argc, char *argv[])
 		switch (c) {
 		default:
 			if (cmd->usagestr)
-				usage(cmd->usagestr);
+				usage(cmd);
 		}
 	}
 }
@@ -240,9 +240,9 @@ void usage_command(const struct cmd_struct *cmd, bool full, bool err)
 }
 
 __attribute__((noreturn))
-void usage(const char * const *usagestr)
+void usage(const struct cmd_struct *cmd)
 {
-	usage_command_usagestr(usagestr, NULL, true, true);
+	usage_command_usagestr(cmd->usagestr, NULL, true, true);
 	exit(1);
 }
 
help.h +1 -1
index e642f58d..7468cf8b 100644
@@ -56,7 +56,7 @@ struct cmd_struct;
 struct cmd_group;
 
 __attribute__((noreturn))
-void usage(const char * const *usagestr);
+void usage(const struct cmd_struct *cmd);
 void usage_command(const struct cmd_struct *cmd, bool full, bool err);
 void usage_command_group(const struct cmd_group *grp, bool all, bool err);
 void usage_command_group_short(const struct cmd_group *grp);
Signature · 1 line
2.12.3
#27 lore raw

PATCH v2 17/20 btrfs-progs: add support for output formats

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

This adds a global --format option to request extended output formats from each command. Most of it is plumbing a new cmd_context structure that's established at the beginning of argument parsing into the command callbacks. That structure currently only contains the output mode enum.

We currently only support text mode. Command help reports what output formats are available for each command. Global help reports what valid formats are.

If an invalid format is requested, an error is reported and we global usage is dumped that lists the valid formats.

Each command sets a bitmask that describes which formats it is capable of outputting. If a globally valid format is requested of a command that doesn't support it, an error is reported and command usage dumped.

Commands don't need to specify that they support text output. All commands are required to output text.

---
 btrfs-debug-tree.c        |   3 +-
 btrfs.c                   | 110 ++++++++++++++++++++++++++++++++++++++--------
 check/main.c              |   3 +-
 cmds-balance.c            |  16 +++++--
 cmds-device.c             |  31 +++++++++----
 cmds-fi-du.c              |   1 +
 cmds-fi-usage.c           |   1 +
 cmds-filesystem.c         |  14 ++++--
 cmds-inspect-dump-super.c |   1 +
 cmds-inspect-dump-tree.c  |   1 +
 cmds-inspect-tree-stats.c |   1 +
 cmds-inspect.c            |  10 ++++-
 cmds-property.c           |   6 ++-
 cmds-qgroup.c             |  17 +++++--
 cmds-quota.c              |  14 ++++--
 cmds-receive.c            |   3 +-
 cmds-replace.c            |   8 +++-
 cmds-rescue.c             |   9 +++-
 cmds-restore.c            |   3 +-
 cmds-scrub.c              |  21 ++++++---
 cmds-send.c               |   3 +-
 cmds-subvolume.c          |  24 +++++++---
 commands.h                |  32 +++++++++++---
 help.c                    |  51 ++++++++++++++++-----
 help.h                    |   2 +
 25 files changed, 301 insertions(+), 84 deletions(-)
btrfs-debug-tree.c +2 -1
index 49a2e949..8cd05d53 100644
@@ -26,6 +26,7 @@ int main(int argc, char **argv)
 {
 	const struct cmd_struct *cmd = &cmd_struct_inspect_dump_tree;
 	int ret;
+	struct cmd_context cmdcxt = {};
 
 	set_argv0(argv);
 
@@ -34,7 +35,7 @@ int main(int argc, char **argv)
 
 	radix_tree_init();
 
-	ret = cmd_execute(cmd, argc, argv);
+	ret = cmd_execute(cmd, &cmdcxt, argc, argv);
 
 	btrfs_close_all_devices();
 
btrfs.c +91 -19

218 lines not on this page · raw message

check/main.c +2 -1
index 0bb8633a..6c74ca8f 100644
@@ -9440,7 +9440,8 @@ static const char * const cmd_check_usage[] = {
 	NULL
 };
 
-static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_check(const struct cmd_struct *cmd,
+		     const struct cmd_context *cmdcxt, int argc, char **argv)
 {
 	struct cache_tree root_cache;
 	struct btrfs_root *root;
cmds-balance.c +12 -4
index c639459f..c17b9ee3 100644
@@ -516,6 +516,7 @@ static const char * const cmd_balance_start_usage[] = {
 };
 
 static int cmd_balance_start(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
 	struct btrfs_ioctl_balance_args args;
@@ -682,6 +683,7 @@ static const char * const cmd_balance_pause_usage[] = {
 };
 
 static int cmd_balance_pause(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
 	const char *path;
@@ -722,6 +724,7 @@ static const char * const cmd_balance_cancel_usage[] = {
 };
 
 static int cmd_balance_cancel(const struct cmd_struct *cmd,
+			      const struct cmd_context *cmdcxt,
 			      int argc, char **argv)
 {
 	const char *path;
@@ -762,6 +765,7 @@ static const char * const cmd_balance_resume_usage[] = {
 };
 
 static int cmd_balance_resume(const struct cmd_struct *cmd,
+			      const struct cmd_context *cmdcxt,
 			      int argc, char **argv)
 {
 	struct btrfs_ioctl_balance_args args;
@@ -831,6 +835,7 @@ static const char * const cmd_balance_status_usage[] = {
  *   0 : When there is no pending balance or completed
  */
 static int cmd_balance_status(const struct cmd_struct *cmd,
+			      const struct cmd_context *cmdcxt,
 			      int argc, char **argv)
 {
 	struct btrfs_ioctl_balance_args args;
@@ -909,7 +914,9 @@ out:
 }
 static DEFINE_SIMPLE_COMMAND(balance_status, "status");
 
-static int cmd_balance_full(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_balance_full(const struct cmd_struct *cmd,
+			    const struct cmd_context *cmdcxt,
+			    int argc, char **argv)
 {
 	struct btrfs_ioctl_balance_args args;
 
@@ -919,7 +926,7 @@ static int cmd_balance_full(const struct cmd_struct *cmd, int argc, char **argv)
 	return do_balance(argv[1], &args, BALANCE_START_NOWARN);
 }
 static DEFINE_COMMAND(balance_full, "--full-balance", cmd_balance_full,
-		      NULL, NULL, CMD_HIDDEN);
+		      NULL, NULL, CMD_HIDDEN, 0);
 
 static const char balance_cmd_group_info[] =
 "balance data across devices, or change block groups using filters";
@@ -936,7 +943,8 @@ static const struct cmd_group balance_cmd_group = {
 	}
 };
 
-static int cmd_balance(const struct cmd_struct *unused, int argc, char **argv)
+static int cmd_balance(const struct cmd_struct *unused,
+		       const struct cmd_context *cmdcxt, int argc, char **argv)
 {
 	if (argc == 2 && strcmp("start", argv[1]) != 0) {
 		/* old 'btrfs filesystem balance <path>' syntax */
@@ -948,7 +956,7 @@ static int cmd_balance(const struct cmd_struct *unused, int argc, char **argv)
 		return do_balance(argv[1], &args, 0);
 	}
 
-	return handle_command_group(&balance_cmd_group, argc, argv);
+	return handle_command_group(&balance_cmd_group, cmdcxt, argc, argv);
 }
 
 DEFINE_GROUP_COMMAND(balance, "balance");
cmds-device.c +22 -9
index 6c74ca8e..ac9e82b1 100644
@@ -49,6 +49,7 @@ static const char * const cmd_device_add_usage[] = {
 };
 
 static int cmd_device_add(const struct cmd_struct *cmd,
+			  const struct cmd_context *cmdcxt,
 			  int argc, char **argv)
 {
 	char	*mntpnt;
@@ -144,6 +145,7 @@ error_out:
 static DEFINE_SIMPLE_COMMAND(device_add, "add");
 
 static int _cmd_device_remove(const struct cmd_struct *cmd,
+			      const struct cmd_context *cmdcxt,
 			      int argc, char **argv)
 {
 	char	*mntpnt;
@@ -238,9 +240,10 @@ static const char * const cmd_device_remove_usage[] = {
 };
 
 static int cmd_device_remove(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
-	return _cmd_device_remove(cmd, argc, argv);
+	return _cmd_device_remove(cmd, cmdcxt, argc, argv);
 }
 static DEFINE_SIMPLE_COMMAND(device_remove, "remove");
 
@@ -253,12 +256,13 @@ static const char * const cmd_device_delete_usage[] = {
 };
 
 static int cmd_device_delete(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
-	return _cmd_device_remove(cmd, argc, argv);
+	return _cmd_device_remove(cmd, cmdcxt, argc, argv);
 }
 static DEFINE_COMMAND(device_delete, "delete", cmd_device_delete,
-		      cmd_device_delete_usage, NULL, CMD_ALIAS);
+		      cmd_device_delete_usage, NULL, CMD_ALIAS, 0);
 
 static const char * const cmd_device_scan_usage[] = {
 	"btrfs device scan [(-d|--all-devices)|<device> [<device>...]]",
@@ -267,7 +271,9 @@ static const char * const cmd_device_scan_usage[] = {
 	NULL
 };
 
-static int cmd_device_scan(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_device_scan(const struct cmd_struct *cmd,
+			   const struct cmd_context *cmdcxt,
+			   int argc, char **argv)
 {
 	int i;
 	int devstart;
@@ -340,7 +346,9 @@ static const char * const cmd_device_ready_usage[] = {
 	NULL
 };
 
-static int cmd_device_ready(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_device_ready(const struct cmd_struct *cmd,
+			    const struct cmd_context *cmdcxt,
+			    int argc, char **argv)
 {
 	struct	btrfs_ioctl_vol_args args;
 	int	fd;
@@ -399,7 +407,9 @@ static const char * const cmd_device_stats_usage[] = {
 	NULL
 };
 
-static int cmd_device_stats(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_device_stats(const struct cmd_struct *cmd,
+			    const struct cmd_context *cmdcxt,
+			    int argc, char **argv)
 {
 	char *dev_path;
 	struct btrfs_ioctl_fs_info_args fi_args;
@@ -565,7 +575,9 @@ out:
 	return ret;
 }
 
-static int cmd_device_usage(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_device_usage(const struct cmd_struct *cmd,
+			    const struct cmd_context *cmdcxt,
+			    int argc, char **argv)
 {
 	unsigned unit_mode;
 	int ret = 0;
@@ -618,8 +630,9 @@ static const struct cmd_group device_cmd_group = {
 	}
 };
 
-static int cmd_device(const struct cmd_struct *unused, int argc, char **argv)
+static int cmd_device(const struct cmd_struct *unused,
+		      const struct cmd_context *cmdcxt, int argc, char **argv)
 {
-	return handle_command_group(&device_cmd_group, argc, argv);
+	return handle_command_group(&device_cmd_group, cmdcxt, argc, argv);
 }
 DEFINE_GROUP_COMMAND_TOKEN(device);
cmds-fi-du.c +1 -0
index ebcb0c15..c85c0063 100644
@@ -558,6 +558,7 @@ static const char * const cmd_filesystem_du_usage[] = {
 };
 
 static int cmd_filesystem_du(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
 	int ret = 0, err = 0;
cmds-fi-usage.c +1 -0
index 6da96411..5d220cc2 100644
@@ -966,6 +966,7 @@ static const char * const cmd_filesystem_usage_usage[] = {
 };
 
 static int cmd_filesystem_usage(const struct cmd_struct *cmd,
+				const struct cmd_context *cmdcxt,
 				int argc, char **argv)
 {
 	int ret = 0;
cmds-filesystem.c +11 -3
index 8ddb7ea5..27e0865c 100644
@@ -116,6 +116,7 @@ static void print_df(struct btrfs_ioctl_space_args *sargs, unsigned unit_mode)
 }
 
 static int cmd_filesystem_df(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
 	struct btrfs_ioctl_space_args *sargs = NULL;
@@ -668,6 +669,7 @@ static const char * const cmd_filesystem_show_usage[] = {
 };
 
 static int cmd_filesystem_show(const struct cmd_struct *cmd,
+			       const struct cmd_context *cmdcxt,
 			       int argc, char **argv)
 {
 	LIST_HEAD(all_uuids);
@@ -816,6 +818,7 @@ static const char * const cmd_filesystem_sync_usage[] = {
 };
 
 static int cmd_filesystem_sync(const struct cmd_struct *cmd,
+			       const struct cmd_context *cmdcxt,
 			       int argc, char **argv)
 {
 	int 	fd, res;
@@ -914,6 +917,7 @@ error:
 }
 
 static int cmd_filesystem_defrag(const struct cmd_struct *cmd,
+				 const struct cmd_context *cmdcxt,
 				 int argc, char **argv)
 {
 	int fd;
@@ -1094,6 +1098,7 @@ static const char * const cmd_filesystem_resize_usage[] = {
 };
 
 static int cmd_filesystem_resize(const struct cmd_struct *cmd,
+				 const struct cmd_context *cmdcxt,
 				 int argc, char **argv)
 {
 	struct btrfs_ioctl_vol_args	args;
@@ -1173,6 +1178,7 @@ static const char * const cmd_filesystem_label_usage[] = {
 };
 
 static int cmd_filesystem_label(const struct cmd_struct *cmd,
+				const struct cmd_context *cmdcxt,
 				int argc, char **argv)
 {
 	clean_args_no_options(cmd, argc, argv);
@@ -1203,9 +1209,10 @@ static const char * const cmd_filesystem_balance_usage[] = {
 };
 
 static int cmd_filesystem_balance(const struct cmd_struct *unused,
+				  const struct cmd_context *cmdcxt,
 				  int argc, char **argv)
 {
-	return cmd_execute(&cmd_struct_balance, argc, argv);
+	return cmd_execute(&cmd_struct_balance, cmdcxt, argc, argv);
 }
 
 /*
@@ -1215,7 +1222,7 @@ static int cmd_filesystem_balance(const struct cmd_struct *unused,
  * for historical compatibility and is hidden.
  */
 static DEFINE_COMMAND(filesystem_balance, "balance", cmd_filesystem_balance,
-		      cmd_filesystem_balance_usage, NULL, CMD_HIDDEN);
+		      cmd_filesystem_balance_usage, NULL, CMD_HIDDEN, 0);
 
 static const char filesystem_cmd_group_info[] =
 "overall filesystem tasks and information";
@@ -1236,8 +1243,9 @@ static const struct cmd_group filesystem_cmd_group = {
 };
 
 static int cmd_filesystem(const struct cmd_struct *unused,
+			  const struct cmd_context *cmdcxt,
 			  int argc, char **argv)
 {
-	return handle_command_group(&filesystem_cmd_group, argc, argv);
+	return handle_command_group(&filesystem_cmd_group, cmdcxt, argc, argv);
 }
 DEFINE_GROUP_COMMAND_TOKEN(filesystem);
cmds-inspect-dump-super.c +1 -0
index 6341d2ac..da171779 100644
@@ -505,6 +505,7 @@ static const char * const cmd_inspect_dump_super_usage[] = {
 };
 
 static int cmd_inspect_dump_super(const struct cmd_struct *cmd,
+				  const struct cmd_context *cmdcxt,
 				  int argc, char **argv)
 {
 	int all = 0;
cmds-inspect-dump-tree.c +1 -0
index 22bc9cb9..9e0b950b 100644
@@ -202,6 +202,7 @@ static const char * const cmd_inspect_dump_tree_usage[] = {
 };
 
 static int cmd_inspect_dump_tree(const struct cmd_struct *cmd,
+				 const struct cmd_context *cmdcxt,
 				 int argc, char **argv)
 {
 	struct btrfs_root *root;
cmds-inspect-tree-stats.c +1 -0
index e5e68562..768af025 100644
@@ -428,6 +428,7 @@ static const char * const cmd_inspect_tree_stats_usage[] = {
 };
 
 static int cmd_inspect_tree_stats(const struct cmd_struct *cmd,
+				  const struct cmd_context *cmdcxt,
 				  int argc, char **argv)
 {
 	struct btrfs_key key;
cmds-inspect.c +8 -2
index bc86e999..ade9db7e 100644
@@ -88,6 +88,7 @@ static const char * const cmd_inspect_inode_resolve_usage[] = {
 };
 
 static int cmd_inspect_inode_resolve(const struct cmd_struct *cmd,
+				     const struct cmd_context *cmdcxt,
 				     int argc, char **argv)
 {
 	int fd;
@@ -136,6 +137,7 @@ static const char * const cmd_inspect_logical_resolve_usage[] = {
 };
 
 static int cmd_inspect_logical_resolve(const struct cmd_struct *cmd,
+				       const struct cmd_context *cmdcxt,
 				       int argc, char **argv)
 {
 	int ret;
@@ -269,6 +271,7 @@ static const char * const cmd_inspect_subvolid_resolve_usage[] = {
 };
 
 static int cmd_inspect_subvolid_resolve(const struct cmd_struct *cmd,
+					const struct cmd_context *cmdcxt,
 					int argc, char **argv)
 {
 	int ret;
@@ -313,6 +316,7 @@ static const char* const cmd_inspect_rootid_usage[] = {
 };
 
 static int cmd_inspect_rootid(const struct cmd_struct *cmd,
+			      const struct cmd_context *cmdcxt,
 			      int argc, char **argv)
 {
 	int ret;
@@ -593,6 +597,7 @@ out:
 }
 
 static int cmd_inspect_min_dev_size(const struct cmd_struct *cmd,
+				    const struct cmd_context *cmdcxt,
 				    int argc, char **argv)
 {
 	int ret;
@@ -653,8 +658,9 @@ static const struct cmd_group inspect_cmd_group = {
 	}
 };
 
-static int cmd_inspect(const struct cmd_struct *unused, int argc, char **argv)
+static int cmd_inspect(const struct cmd_struct *unused,
+		       const struct cmd_context *cmdcxt, int argc, char **argv)
 {
-	return handle_command_group(&inspect_cmd_group, argc, argv);
+	return handle_command_group(&inspect_cmd_group, cmdcxt, argc, argv);
 }
 DEFINE_GROUP_COMMAND(inspect, "inspect");
cmds-property.c +5 -1
index 4aa2f18f..498fa456 100644
@@ -341,6 +341,7 @@ static const char * const cmd_property_get_usage[] = {
 };
 
 static int cmd_property_get(const struct cmd_struct *cmd,
+			    const struct cmd_context *cmdcxt,
 			    int argc, char **argv)
 {
 	int ret;
@@ -368,6 +369,7 @@ static const char * const cmd_property_set_usage[] = {
 };
 
 static int cmd_property_set(const struct cmd_struct *cmd,
+			    const struct cmd_context *cmdcxt,
 			    int argc, char **argv)
 {
 	int ret;
@@ -393,6 +395,7 @@ static const char * const cmd_property_list_usage[] = {
 };
 
 static int cmd_property_list(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
 	int ret;
@@ -420,8 +423,9 @@ static const struct cmd_group property_cmd_group = {
 };
 
 static int cmd_property(const struct cmd_struct *unused,
+			const struct cmd_context *cmdcxt,
 			int argc, char **argv)
 {
-	return handle_command_group(&property_cmd_group, argc, argv);
+	return handle_command_group(&property_cmd_group, cmdcxt, argc, argv);
 }
 DEFINE_GROUP_COMMAND_TOKEN(property);
cmds-qgroup.c +13 -4
index 986f272c..f9e81e30 100644
@@ -216,6 +216,7 @@ static const char * const cmd_qgroup_assign_usage[] = {
 };
 
 static int cmd_qgroup_assign(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
 	return _cmd_qgroup_assign(cmd, 1, argc, argv);
@@ -229,6 +230,7 @@ static const char * const cmd_qgroup_remove_usage[] = {
 };
 
 static int cmd_qgroup_remove(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
 	return _cmd_qgroup_assign(cmd, 0, argc, argv);
@@ -242,6 +244,7 @@ static const char * const cmd_qgroup_create_usage[] = {
 };
 
 static int cmd_qgroup_create(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
 	int ret;
@@ -263,6 +266,7 @@ static const char * const cmd_qgroup_destroy_usage[] = {
 };
 
 static int cmd_qgroup_destroy(const struct cmd_struct *cmd,
+			      const struct cmd_context *cmdcxt,
 			      int argc, char **argv)
 {
 	int ret;
@@ -300,7 +304,9 @@ static const char * const cmd_qgroup_show_usage[] = {
 	NULL
 };
 
-static int cmd_qgroup_show(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_qgroup_show(const struct cmd_struct *cmd,
+			   const struct cmd_context *cmdcxt,
+			   int argc, char **argv)
 {
 	char *path;
 	int ret = 0;
@@ -434,7 +440,9 @@ static const char * const cmd_qgroup_limit_usage[] = {
 	NULL
 };
 
-static int cmd_qgroup_limit(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_qgroup_limit(const struct cmd_struct *cmd,
+			    const struct cmd_context *cmdcxt,
+			    int argc, char **argv)
 {
 	int ret = 0;
 	int fd;
@@ -532,8 +540,9 @@ static const struct cmd_group qgroup_cmd_group = {
 	}
 };
 
-static int cmd_qgroup(const struct cmd_struct *unused, int argc, char **argv)
+static int cmd_qgroup(const struct cmd_struct *unused,
+		      const struct cmd_context *cmdcxt, int argc, char **argv)
 {
-	return handle_command_group(&qgroup_cmd_group, argc, argv);
+	return handle_command_group(&qgroup_cmd_group, cmdcxt, argc, argv);
 }
 DEFINE_GROUP_COMMAND_TOKEN(qgroup);
cmds-quota.c +10 -4
index c634c4e9..2a88d4c4 100644
@@ -67,7 +67,9 @@ static const char * const cmd_quota_enable_usage[] = {
 	NULL
 };
 
-static int cmd_quota_enable(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_quota_enable(const struct cmd_struct *cmd,
+			    const struct cmd_context *cmdcxt,
+			    int argc, char **argv)
 {
 	int ret;
 
@@ -88,6 +90,7 @@ static const char * const cmd_quota_disable_usage[] = {
 };
 
 static int cmd_quota_disable(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
 	int ret;
@@ -111,7 +114,9 @@ static const char * const cmd_quota_rescan_usage[] = {
 	NULL
 };
 
-static int cmd_quota_rescan(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_quota_rescan(const struct cmd_struct *cmd,
+			    const struct cmd_context *cmdcxt,
+			    int argc, char **argv)
 {
 	int ret = 0;
 	int fd;
@@ -214,8 +219,9 @@ static const struct cmd_group quota_cmd_group = {
 	}
 };
 
-static int cmd_quota(const struct cmd_struct *unused, int argc, char **argv)
+static int cmd_quota(const struct cmd_struct *unused,
+		     const struct cmd_context *cmdcxt, int argc, char **argv)
 {
-	return handle_command_group(&quota_cmd_group, argc, argv);
+	return handle_command_group(&quota_cmd_group, cmdcxt, argc, argv);
 }
 DEFINE_GROUP_COMMAND_TOKEN(quota);
cmds-receive.c +2 -1
index 5429c607..57ce2272 100644
@@ -1279,7 +1279,8 @@ static const char * const cmd_receive_usage[] = {
 	NULL
 };
 
-static int cmd_receive(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_receive(const struct cmd_struct *cmd,
+		       const struct cmd_context *cmdcxt, int argc, char **argv)
 {
 	char *tomnt = NULL;
 	char fromfile[PATH_MAX];
cmds-replace.c +6 -2
index 2057d69e..64c93537 100644
@@ -115,6 +115,7 @@ static const char *const cmd_replace_start_usage[] = {
 };
 
 static int cmd_replace_start(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
 	struct btrfs_ioctl_dev_replace_args start_args = {0};
@@ -327,6 +328,7 @@ static const char *const cmd_replace_status_usage[] = {
 };
 
 static int cmd_replace_status(const struct cmd_struct *cmd,
+			      const struct cmd_context *cmdcxt,
 			      int argc, char **argv)
 {
 	int fd;
@@ -497,6 +499,7 @@ static const char *const cmd_replace_cancel_usage[] = {
 };
 
 static int cmd_replace_cancel(const struct cmd_struct *cmd,
+			      const struct cmd_context *cmdcxt,
 			      int argc, char **argv)
 {
 	struct btrfs_ioctl_dev_replace_args args = {0};
@@ -557,8 +560,9 @@ static const struct cmd_group replace_cmd_group = {
 	}
 };
 
-static int cmd_replace(const struct cmd_struct *unused, int argc, char **argv)
+static int cmd_replace(const struct cmd_struct *unused,
+		       const struct cmd_context *cmdcxt, int argc, char **argv)
 {
-	return handle_command_group(&replace_cmd_group, argc, argv);
+	return handle_command_group(&replace_cmd_group, cmdcxt, argc, argv);
 }
 DEFINE_GROUP_COMMAND_TOKEN(replace);
cmds-rescue.c +7 -2
index f96d8010..ec1ea222 100644
@@ -46,6 +46,7 @@ static const char * const cmd_rescue_chunk_recover_usage[] = {
 };
 
 static int cmd_rescue_chunk_recover(const struct cmd_struct *cmd,
+				    const struct cmd_context *cmdcxt,
 				    int argc, char *argv[])
 {
 	int ret = 0;
@@ -115,6 +116,7 @@ static const char * const cmd_rescue_super_recover_usage[] = {
  *   4 : Abort to recover bad superblocks
  */
 static int cmd_rescue_super_recover(const struct cmd_struct *cmd,
+				    const struct cmd_context *cmdcxt,
 				    int argc, char **argv)
 {
 	int ret;
@@ -162,6 +164,7 @@ static const char * const cmd_rescue_zero_log_usage[] = {
 };
 
 static int cmd_rescue_zero_log(const struct cmd_struct *cmd,
+			       const struct cmd_context *cmdcxt,
 			       int argc, char **argv)
 {
 	struct btrfs_root *root;
@@ -217,6 +220,7 @@ static const char * const cmd_rescue_fix_device_size_usage[] = {
 };
 
 static int cmd_rescue_fix_device_size(const struct cmd_struct *cmd,
+				      const struct cmd_context *cmdcxt,
 				      int argc, char **argv)
 {
 	struct btrfs_fs_info *fs_info;
@@ -269,8 +273,9 @@ static const struct cmd_group rescue_cmd_group = {
 	}
 };
 
-static int cmd_rescue(const struct cmd_struct *unused, int argc, char **argv)
+static int cmd_rescue(const struct cmd_struct *unused,
+		      const struct cmd_context *cmdcxt, int argc, char **argv)
 {
-	return handle_command_group(&rescue_cmd_group, argc, argv);
+	return handle_command_group(&rescue_cmd_group, cmdcxt, argc, argv);
 }
 DEFINE_GROUP_COMMAND_TOKEN(rescue);
cmds-restore.c +2 -1
index 87cfb582..03c90cb6 100644
@@ -1415,7 +1415,8 @@ static const char * const cmd_restore_usage[] = {
 	NULL
 };
 
-static int cmd_restore(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_restore(const struct cmd_struct *cmd,
+		       const struct cmd_context *cmdcxt, int argc, char **argv)
 {
 	struct btrfs_root *root;
 	struct btrfs_key key;
cmds-scrub.c +15 -6
index 872c996b..d4d5a10c 100644
@@ -1571,7 +1571,9 @@ static const char * const cmd_scrub_start_usage[] = {
 	NULL
 };
 
-static int cmd_scrub_start(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_scrub_start(const struct cmd_struct *cmd,
+			   const struct cmd_context *cmdcxt,
+			   int argc, char **argv)
 {
 	return scrub_start(cmd, argc, argv, false);
 }
@@ -1583,7 +1585,9 @@ static const char * const cmd_scrub_cancel_usage[] = {
 	NULL
 };
 
-static int cmd_scrub_cancel(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_scrub_cancel(const struct cmd_struct *cmd,
+			    const struct cmd_context *cmdcxt,
+			    int argc, char **argv)
 {
 	char *path;
 	int ret;
@@ -1638,7 +1642,9 @@ static const char * const cmd_scrub_resume_usage[] = {
 	NULL
 };
 
-static int cmd_scrub_resume(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_scrub_resume(const struct cmd_struct *cmd,
+			    const struct cmd_context *cmdcxt,
+			    int argc, char **argv)
 {
 	return scrub_start(cmd, argc, argv, true);
 }
@@ -1653,7 +1659,9 @@ static const char * const cmd_scrub_status_usage[] = {
 	NULL
 };
 
-static int cmd_scrub_status(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_scrub_status(const struct cmd_struct *cmd,
+			    const struct cmd_context *cmdcxt,
+			    int argc, char **argv)
 {
 	char *path;
 	struct btrfs_ioctl_fs_info_args fi_args;
@@ -1799,9 +1807,10 @@ static const struct cmd_group scrub_cmd_group = {
 	}
 };
 
-static int cmd_scrub(const struct cmd_struct *unused, int argc, char **argv)
+static int cmd_scrub(const struct cmd_struct *unused,
+		     const struct cmd_context *cmdcxt, int argc, char **argv)
 {
-	return handle_command_group(&scrub_cmd_group, argc, argv);
+	return handle_command_group(&scrub_cmd_group, cmdcxt, argc, argv);
 }
 
 DEFINE_GROUP_COMMAND_TOKEN(scrub);
cmds-send.c +2 -1
index e2d87785..c810f842 100644
@@ -523,7 +523,8 @@ static const char * const cmd_send_usage[] = {
 	NULL
 };
 
-static int cmd_send(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_send(const struct cmd_struct *cmd,
+		    const struct cmd_context *cmdcxt, int argc, char **argv)
 {
 	char *subvol = NULL;
 	int ret;
cmds-subvolume.c +18 -6
index dc529315..3498ff21 100644
@@ -117,6 +117,7 @@ static const char * const cmd_subvol_create_usage[] = {
 };
 
 static int cmd_subvol_create(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
 	int	retval, res, len;
@@ -253,6 +254,7 @@ static const char * const cmd_subvol_delete_usage[] = {
 };
 
 static int cmd_subvol_delete(const struct cmd_struct *cmd,
+			     const struct cmd_context *cmdcxt,
 			     int argc, char **argv)
 {
 	int res, ret = 0;
@@ -479,7 +481,9 @@ static const char * const cmd_subvol_list_usage[] = {
 	NULL,
 };
 
-static int cmd_subvol_list(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_subvol_list(const struct cmd_struct *cmd,
+			   const struct cmd_context *cmdcxt,
+			   int argc, char **argv)
 {
 	struct btrfs_list_filter_set *filter_set;
 	struct btrfs_list_comparer_set *comparer_set;
@@ -652,6 +656,7 @@ static const char * const cmd_subvol_snapshot_usage[] = {
 };
 
 static int cmd_subvol_snapshot(const struct cmd_struct *cmd,
+			       const struct cmd_context *cmdcxt,
 			       int argc, char **argv)
 {
 	char	*subvol, *dst;
@@ -803,6 +808,7 @@ static const char * const cmd_subvol_get_default_usage[] = {
 };
 
 static int cmd_subvol_get_default(const struct cmd_struct *cmd,
+				  const struct cmd_context *cmdcxt,
 				  int argc, char **argv)
 {
 	int fd = -1;
@@ -872,6 +878,7 @@ static const char * const cmd_subvol_set_default_usage[] = {
 };
 
 static int cmd_subvol_set_default(const struct cmd_struct *cmd,
+				  const struct cmd_context *cmdcxt,
 				  int argc, char **argv)
 {
 	int	ret=0, fd;
@@ -937,6 +944,7 @@ static const char * const cmd_subvol_find_new_usage[] = {
 };
 
 static int cmd_subvol_find_new(const struct cmd_struct *cmd,
+			       const struct cmd_context *cmdcxt,
 			       int argc, char **argv)
 {
 	int fd;
@@ -992,7 +1000,9 @@ static const char * const cmd_subvol_show_usage[] = {
 	NULL
 };
 
-static int cmd_subvol_show(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_subvol_show(const struct cmd_struct *cmd,
+			   const struct cmd_context *cmdcxt,
+			   int argc, char **argv)
 {
 	struct root_info get_ri;
 	struct btrfs_list_filter_set *filter_set = NULL;
@@ -1343,7 +1353,9 @@ static int enumerate_dead_subvols(int fd, u64 **ids)
 	return idx;
 }
 
-static int cmd_subvol_sync(const struct cmd_struct *cmd, int argc, char **argv)
+static int cmd_subvol_sync(const struct cmd_struct *cmd,
+			   const struct cmd_context *cmdcxt,
+			   int argc, char **argv)
 {
 	int fd = -1;
 	int i;
@@ -1454,9 +1466,9 @@ static const struct cmd_group subvolume_cmd_group = {
 	}
 };
 
-static int cmd_subvolume(const struct cmd_struct *unused,
-			 int argc, char **argv)
+int cmd_subvolume(const struct cmd_struct *unused,
+		  const struct cmd_context *cmdcxt, int argc, char **argv)
 {
-	return handle_command_group(&subvolume_cmd_group, argc, argv);
+	return handle_command_group(&subvolume_cmd_group, cmdcxt, argc, argv);
 }
 DEFINE_GROUP_COMMAND_TOKEN(subvolume);
commands.h +25 -7
index 4c5469ac..83316c6d 100644
@@ -17,6 +17,17 @@
 #ifndef __BTRFS_COMMANDS_H__
 #define __BTRFS_COMMANDS_H__
 
+enum cmd_output {
+	CMD_OUTPUT_TEXT = 0,
+	CMD_OUTPUT_MAX,
+};
+
+#define CMD_OUTPUT_FLAG(x)	(1 << (CMD_OUTPUT_##x))
+
+struct cmd_context {
+	enum cmd_output output_mode;
+};
+
 enum {
 	CMD_HIDDEN = (1 << 0),	/* should not be in help listings */
 	CMD_ALIAS = (1 << 1),	/* alias of next command in cmd_group */
@@ -24,7 +35,8 @@ enum {
 
 struct cmd_struct {
 	const char *token;
-	int (*fn)(const struct cmd_struct *cmd, int argc, char **argv);
+	int (*fn)(const struct cmd_struct *cmd,
+		  const struct cmd_context *cmdcxt, int argc, char **argv);
 
 	/*
 	 * Usage strings
@@ -54,6 +66,8 @@ struct cmd_struct {
 
 	/* CMD_* flags above */
 	int flags;
+
+	unsigned int cmd_format_flags;
 };
 
 /*
@@ -65,7 +79,8 @@ struct cmd_struct {
 	extern const struct cmd_struct __CMD_NAME(name)
 
 /* Define a command with all members specified */
-#define DEFINE_COMMAND(name, _token, _fn, _usagestr, _group, _flags)	\
+#define DEFINE_COMMAND(name, _token, _fn, _usagestr, _group, _flags,	\
+		       _cmd_format_flags)				\
 	const struct cmd_struct __CMD_NAME(name) =			\
 		{							\
 			.token = (_token),				\
@@ -73,6 +88,7 @@ struct cmd_struct {
 			.usagestr = (_usagestr),			\
 			.next = (_group),				\
 			.flags = (_flags),				\
+			.cmd_format_flags = (_cmd_format_flags),	\
 		}
 
 /*
@@ -82,7 +98,7 @@ struct cmd_struct {
  */
 #define DEFINE_SIMPLE_COMMAND(name, token)				\
 	DEFINE_COMMAND(name, token, cmd_ ##name,			\
-		       cmd_ ##name ##_usage, NULL, 0)
+		       cmd_ ##name ##_usage, NULL, 0, 0)
 
 /*
  * Define a command group callback.
@@ -91,7 +107,7 @@ struct cmd_struct {
  */
 #define DEFINE_GROUP_COMMAND(name, token)				\
 	DEFINE_COMMAND(name, token, cmd_ ##name,			\
-		       NULL, &(name ## _cmd_group), 0)
+		       NULL, &(name ## _cmd_group), 0, 0)
 
 /*
  * Define a command group callback when the name and the string are
@@ -108,13 +124,15 @@ struct cmd_group {
 };
 
 static inline int cmd_execute(const struct cmd_struct *cmd,
+			      const struct cmd_context *cmdcxt,
 			      int argc, char **argv)
 {
-	return cmd->fn(cmd, argc, argv);
+	return cmd->fn(cmd, cmdcxt, argc, argv);
 }
 
-int handle_command_group(const struct cmd_group *grp, int argc,
-			 char **argv);
+int handle_command_group(const struct cmd_group *grp,
+			 const struct cmd_context *cmdcxt,
+			 int argc, char **argv);
 
 extern const char * const generic_cmd_help_usage[];
 
help.c +41 -10

115 lines not on this page · raw message

help.h +2 -0
index 7468cf8b..5b338a49 100644
@@ -55,6 +55,8 @@
 struct cmd_struct;
 struct cmd_group;
 
+extern const char *cmd_outputs[];
+
 __attribute__((noreturn))
 void usage(const struct cmd_struct *cmd);
 void usage_command(const struct cmd_struct *cmd, bool full, bool err);
Signature · 1 line
2.12.3
#28 lore raw

PATCH v2 18/20 btrfs-progs: add generic support for json output

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

This patch adds support for JSON and JSON-compat output. The latter is intended to be compatible with Javascript's integers being represented as 64-bit floats, with only 53 bits usable for the integer component. Compat mode output will post 64-bit integers as an array of two 32-bit integers in [high, low] format.

This patch also adds support for reporting which output formats a command supports as well as detection of the json-c library.

---
 Makefile.inc.in |  4 ++--
 commands.h      | 13 +++++++++++++
 configure.ac    |  6 ++++++
 help.c          | 25 ++++++++++++++-----------
 4 files changed, 35 insertions(+), 13 deletions(-)
Makefile.inc.in +2 -2
index 56271903..68bddbed 100644
@@ -18,9 +18,9 @@ BTRFSRESTORE_ZSTD = @BTRFSRESTORE_ZSTD@
 SUBST_CFLAGS = @CFLAGS@
 SUBST_LDFLAGS = @LDFLAGS@
 
-LIBS_BASE = @UUID_LIBS@ @BLKID_LIBS@ -L. -pthread
+LIBS_BASE = @UUID_LIBS@ @BLKID_LIBS@ @JSON_LIBS@ -L. -pthread
 LIBS_COMP = @ZLIB_LIBS@ @LZO2_LIBS@ @ZSTD_LIBS@
-STATIC_LIBS_BASE = @UUID_LIBS_STATIC@ @BLKID_LIBS_STATIC@ -L. -pthread
+STATIC_LIBS_BASE = @UUID_LIBS_STATIC@ @BLKID_LIBS_STATIC@ @JSON_LIBS_STATIC@ -L. -pthread
 STATIC_LIBS_COMP = @ZLIB_LIBS_STATIC@ @LZO2_LIBS_STATIC@ @ZSTD_LIBS_STATIC@
 
 prefix ?= @prefix@
commands.h +13 -0
index 83316c6d..bf74eaf8 100644
@@ -19,9 +19,22 @@
 
 enum cmd_output {
 	CMD_OUTPUT_TEXT = 0,
+#ifdef HAVE_JSON
+	CMD_OUTPUT_JSON,
+	CMD_OUTPUT_JSON_COMPAT,
+#endif
 	CMD_OUTPUT_MAX,
 };
 
+/*
+ * If we don't have the JSON library, map the flags to text to avoid
+ * more ifdefs elsewhere.
+ */
+#ifndef HAVE_JSON
+#define CMD_OUTPUT_JSON		CMD_OUTPUT_TEXT
+#define CMD_OUTPUT_JSON_COMPAT	CMD_OUTPUT_TEXT
+#endif
+
 #define CMD_OUTPUT_FLAG(x)	(1 << (CMD_OUTPUT_##x))
 
 struct cmd_context {
configure.ac +6 -0
index 56d17c3a..6aec672a 100644
@@ -197,6 +197,12 @@ PKG_STATIC(UUID_LIBS_STATIC, [uuid])
 PKG_CHECK_MODULES(ZLIB, [zlib])
 PKG_STATIC(ZLIB_LIBS_STATIC, [zlib])
 
+PKG_CHECK_MODULES(JSON, [json-c], [
+	AC_DEFINE(HAVE_JSON, [1], [Have JSON]),
+	PKG_STATIC(JSON_LIBS_STATIC, [json-c], [
+		AC_DEFINE(HAVE_JSON_STATIC, [1], [Have JSON static])], [true])
+	], [true])
+
 AC_ARG_ENABLE([zstd],
 	AS_HELP_STRING([--disable-zstd], [build without zstd support]),
 	[], [enable_zstd=yes]
help.c +14 -11
index 063e9740..f1710621 100644
@@ -32,6 +32,10 @@
 
 const char *cmd_outputs[CMD_OUTPUT_MAX] = {
 	"text",
+#ifdef HAVE_JSON
+	[CMD_OUTPUT_JSON] = "json",
+	[CMD_OUTPUT_JSON_COMPAT] = "json:compat",
+#endif
 };
 
 static char argv0_buf[ARGV0_BUF_SIZE] = "btrfs";
@@ -186,18 +190,17 @@ static int do_usage_one_command(const char * const *usagestr,
 		fprintf(outf, "%*s%s\n", pad, "", *usagestr++);
 
 	/* options (optional) */
-	if (!*usagestr || ((flags & USAGE_OPTIONS) == 0))
-		return 0;
-
-	/*
-	 * options (if present) should always (even if there is no long
-	 * description) be prepended with an empty line, skip it
-	 */
-	usagestr++;
+	if (*usagestr && (flags & USAGE_OPTIONS)) {
+		/*
+		 * options (if present) should always (even if there is no long
+		 * description) be prepended with an empty line, skip it
+		 */
+		usagestr++;
 
-	fputc('\n', outf);
-	while (*usagestr)
-		fprintf(outf, "%*s%s\n", pad, "", *usagestr++);
+		fputc('\n', outf);
+		while (*usagestr)
+			fprintf(outf, "%*s%s\n", pad, "", *usagestr++);
+	}
 
 	if (flags & USAGE_FORMAT) {
 		/* We always support text */
Signature · 1 line
2.12.3
#29 lore raw

PATCH v2 19/20 btrfs-progs: qgroups: add json output for usage command

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

One of the common requests I receive is for 'df' like facilities for subvolume usage. Really, the request is for monitoring tools to be able to understand when subvolumes may be approaching quota in the same manner traditional file systems approach ENOSPC.

This patch allows us to export the qgroups data in a machine-readable format so that monitoring tools can parse it easily.

---
 Documentation/btrfs-qgroup.asciidoc |   3 +
 cmds-qgroup.c                       |  22 +++-
 qgroup.c                            | 222 ++++++++++++++++++++++++++++++++++++
 qgroup.h                            |   8 +-
 4 files changed, 251 insertions(+), 4 deletions(-)
Documentation/btrfs-qgroup.asciidoc +3 -0
index 360b3269..7863a4d9 100644
@@ -87,6 +87,9 @@ the btrfs filesystem identified by <path>.
 *show* [options] <path>::
 Show all qgroups in the btrfs filesystem identified by <path>.
 +
+If enabled, this command supports extended output in json and json:compat modes.
+Use of either json mode implies -P and --raw.
++
 `Options`
 +
 -p::::
cmds-qgroup.c +20 -2
index f9e81e30..fd637a45 100644
@@ -301,6 +301,10 @@ static const char * const cmd_qgroup_show_usage[] = {
 	"               you can use '+' or '-' in front of each item.",
 	"               (+:ascending, -:descending, ascending default)",
 	"--sync         force sync of the filesystem before getting info",
+	"",
+#ifdef HAVE_JSON
+	"json and json:compat output implies -P and --raw.",
+#endif
 	NULL
 };
 
@@ -386,6 +390,10 @@ static int cmd_qgroup_show(const struct cmd_struct *cmd,
 	}
 	btrfs_qgroup_setup_units(unit_mode);
 
+	if (cmdcxt->output_mode == CMD_OUTPUT_JSON ||
+	    cmdcxt->output_mode == CMD_OUTPUT_JSON_COMPAT)
+		unit_mode = UNITS_RAW;
+
 	if (check_argc_exact(argc - optind, 1))
 		usage(cmd);
 
@@ -420,7 +428,15 @@ static int cmd_qgroup_show(const struct cmd_struct *cmd,
 					BTRFS_QGROUP_FILTER_PARENT,
 					qgroupid);
 	}
-	ret = btrfs_show_qgroups(fd, filter_set, comparer_set, verbose);
+
+	if (cmdcxt->output_mode == CMD_OUTPUT_JSON ||
+	    cmdcxt->output_mode == CMD_OUTPUT_JSON_COMPAT) {
+		bool compat = (cmdcxt->output_mode == CMD_OUTPUT_JSON_COMPAT);
+
+		ret = btrfs_qgroup_output_json(fd, filter_set, comparer_set,
+					       compat);
+	} else
+		ret = btrfs_show_qgroups(fd, filter_set, comparer_set, verbose);
 	close_file_or_dir(fd, dirstream);
 	free(filter_set);
 	free(comparer_set);
@@ -428,7 +444,9 @@ static int cmd_qgroup_show(const struct cmd_struct *cmd,
 out:
 	return !!ret;
 }
-static DEFINE_SIMPLE_COMMAND(qgroup_show, "show");
+static DEFINE_COMMAND(qgroup_show, "show", cmd_qgroup_show,
+		      cmd_qgroup_show_usage, NULL, 0,
+		      CMD_OUTPUT_FLAG(JSON)|CMD_OUTPUT_FLAG(JSON_COMPAT));
 
 static const char * const cmd_qgroup_limit_usage[] = {
 	"btrfs qgroup limit [options] <size>|none [<qgroupid>] <path>",
qgroup.c +222 -0

240 lines not on this page · raw message

qgroup.h +6 -2
index 688f92b2..4344c7d8 100644
@@ -95,8 +95,12 @@ struct btrfs_qgroup_stats {
 
 int btrfs_qgroup_parse_sort_string(const char *opt_arg,
 				struct btrfs_qgroup_comparer_set **comps);
-int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *,
-		       struct btrfs_qgroup_comparer_set *, bool verbose);
+int btrfs_show_qgroups(int fd, struct btrfs_qgroup_filter_set *filter_set,
+		       struct btrfs_qgroup_comparer_set *comp_set,
+		       bool verbose);
+int btrfs_qgroup_output_json(int fd, struct btrfs_qgroup_filter_set *filter_set,
+			     struct btrfs_qgroup_comparer_set *comp_set,
+			     bool compat);
 void btrfs_qgroup_setup_print_column(enum btrfs_qgroup_column_enum column);
 void btrfs_qgroup_setup_units(unsigned unit_mode);
 struct btrfs_qgroup_filter_set *btrfs_qgroup_alloc_filter_set(void);
Signature · 1 line
2.12.3
#30 lore raw

PATCH v2 20/20 btrfs-progs: handle command groups directly for common case

In reply to [email protected]

From: Jeff Mahoney <[email protected]>

Most command groups just pass their own command group to handle_command_group. We can remove the explicit definitions of command group callbacks by passing the cmd_struct to handle_command_group and allowing it to resolve the group from it.

---
 btrfs.c           | 14 +++++++-------
 cmds-balance.c    |  6 +++---
 cmds-device.c     |  5 -----
 cmds-filesystem.c |  6 ------
 cmds-inspect.c    |  5 -----
 cmds-property.c   |  6 ------
 cmds-qgroup.c     |  5 -----
 cmds-quota.c      |  5 -----
 cmds-replace.c    |  5 -----
 cmds-rescue.c     |  5 -----
 cmds-scrub.c      |  6 ------
 cmds-subvolume.c  |  5 -----
 commands.h        |  7 ++++---
 13 files changed, 14 insertions(+), 66 deletions(-)
btrfs.c +7 -7
index 32b8e090..427e14c8 100644
@@ -140,26 +140,26 @@ static void handle_help_options_next_level(const struct cmd_struct *cmd,
 	}
 }
 
-int handle_command_group(const struct cmd_group *grp,
+int handle_command_group(const struct cmd_struct *cmd,
 			 const struct cmd_context *cmdcxt,
 			 int argc, char **argv)
 
 {
-	const struct cmd_struct *cmd;
+	const struct cmd_struct *subcmd;
 
 	argc--;
 	argv++;
 	if (argc < 1) {
-		usage_command_group(grp, false, false);
+		usage_command_group(cmd->next, false, false);
 		exit(1);
 	}
 
-	cmd = parse_command_token(argv[0], grp);
+	subcmd = parse_command_token(argv[0], cmd->next);
 
-	handle_help_options_next_level(cmd, cmdcxt, argc, argv);
+	handle_help_options_next_level(subcmd, cmdcxt, argc, argv);
 
-	fixup_argv0(argv, cmd->token);
-	return cmd_execute(cmd, cmdcxt, argc, argv);
+	fixup_argv0(argv, subcmd->token);
+	return cmd_execute(subcmd, cmdcxt, argc, argv);
 }
 
 static const struct cmd_group btrfs_cmd_group;
cmds-balance.c +3 -3
index c17b9ee3..e414ca27 100644
@@ -943,7 +943,7 @@ static const struct cmd_group balance_cmd_group = {
 	}
 };
 
-static int cmd_balance(const struct cmd_struct *unused,
+static int cmd_balance(const struct cmd_struct *cmd,
 		       const struct cmd_context *cmdcxt, int argc, char **argv)
 {
 	if (argc == 2 && strcmp("start", argv[1]) != 0) {
@@ -956,7 +956,7 @@ static int cmd_balance(const struct cmd_struct *unused,
 		return do_balance(argv[1], &args, 0);
 	}
 
-	return handle_command_group(&balance_cmd_group, cmdcxt, argc, argv);
+	return handle_command_group(cmd, cmdcxt, argc, argv);
 }
 
-DEFINE_GROUP_COMMAND(balance, "balance");
+DEFINE_COMMAND(balance, "balance", cmd_balance, NULL, &balance_cmd_group, 0, 0);
cmds-device.c +0 -5
index ac9e82b1..f8c0ff20 100644
@@ -630,9 +630,4 @@ static const struct cmd_group device_cmd_group = {
 	}
 };
 
-static int cmd_device(const struct cmd_struct *unused,
-		      const struct cmd_context *cmdcxt, int argc, char **argv)
-{
-	return handle_command_group(&device_cmd_group, cmdcxt, argc, argv);
-}
 DEFINE_GROUP_COMMAND_TOKEN(device);
cmds-filesystem.c +0 -6
index 27e0865c..e3e54864 100644
@@ -1242,10 +1242,4 @@ static const struct cmd_group filesystem_cmd_group = {
 	}
 };
 
-static int cmd_filesystem(const struct cmd_struct *unused,
-			  const struct cmd_context *cmdcxt,
-			  int argc, char **argv)
-{
-	return handle_command_group(&filesystem_cmd_group, cmdcxt, argc, argv);
-}
 DEFINE_GROUP_COMMAND_TOKEN(filesystem);
cmds-inspect.c +0 -5
index ade9db7e..561a0fbd 100644
@@ -658,9 +658,4 @@ static const struct cmd_group inspect_cmd_group = {
 	}
 };
 
-static int cmd_inspect(const struct cmd_struct *unused,
-		       const struct cmd_context *cmdcxt, int argc, char **argv)
-{
-	return handle_command_group(&inspect_cmd_group, cmdcxt, argc, argv);
-}
 DEFINE_GROUP_COMMAND(inspect, "inspect");
cmds-property.c +0 -6
index 498fa456..58f6c48a 100644
@@ -422,10 +422,4 @@ static const struct cmd_group property_cmd_group = {
 	}
 };
 
-static int cmd_property(const struct cmd_struct *unused,
-			const struct cmd_context *cmdcxt,
-			int argc, char **argv)
-{
-	return handle_command_group(&property_cmd_group, cmdcxt, argc, argv);
-}
 DEFINE_GROUP_COMMAND_TOKEN(property);
cmds-qgroup.c +0 -5
index fd637a45..e20c1159 100644
@@ -558,9 +558,4 @@ static const struct cmd_group qgroup_cmd_group = {
 	}
 };
 
-static int cmd_qgroup(const struct cmd_struct *unused,
-		      const struct cmd_context *cmdcxt, int argc, char **argv)
-{
-	return handle_command_group(&qgroup_cmd_group, cmdcxt, argc, argv);
-}
 DEFINE_GROUP_COMMAND_TOKEN(qgroup);
cmds-quota.c +0 -5
index 2a88d4c4..7b524123 100644
@@ -219,9 +219,4 @@ static const struct cmd_group quota_cmd_group = {
 	}
 };
 
-static int cmd_quota(const struct cmd_struct *unused,
-		     const struct cmd_context *cmdcxt, int argc, char **argv)
-{
-	return handle_command_group(&quota_cmd_group, cmdcxt, argc, argv);
-}
 DEFINE_GROUP_COMMAND_TOKEN(quota);
cmds-replace.c +0 -5
index 64c93537..8b2091c9 100644
@@ -560,9 +560,4 @@ static const struct cmd_group replace_cmd_group = {
 	}
 };
 
-static int cmd_replace(const struct cmd_struct *unused,
-		       const struct cmd_context *cmdcxt, int argc, char **argv)
-{
-	return handle_command_group(&replace_cmd_group, cmdcxt, argc, argv);
-}
 DEFINE_GROUP_COMMAND_TOKEN(replace);
cmds-rescue.c +0 -5
index ec1ea222..364d6dd9 100644
@@ -273,9 +273,4 @@ static const struct cmd_group rescue_cmd_group = {
 	}
 };
 
-static int cmd_rescue(const struct cmd_struct *unused,
-		      const struct cmd_context *cmdcxt, int argc, char **argv)
-{
-	return handle_command_group(&rescue_cmd_group, cmdcxt, argc, argv);
-}
 DEFINE_GROUP_COMMAND_TOKEN(rescue);
cmds-scrub.c +0 -6
index d4d5a10c..b0238032 100644
@@ -1807,10 +1807,4 @@ static const struct cmd_group scrub_cmd_group = {
 	}
 };
 
-static int cmd_scrub(const struct cmd_struct *unused,
-		     const struct cmd_context *cmdcxt, int argc, char **argv)
-{
-	return handle_command_group(&scrub_cmd_group, cmdcxt, argc, argv);
-}
-
 DEFINE_GROUP_COMMAND_TOKEN(scrub);
cmds-subvolume.c +0 -5
index 3498ff21..7a420a64 100644
@@ -1466,9 +1466,4 @@ static const struct cmd_group subvolume_cmd_group = {
 	}
 };
 
-int cmd_subvolume(const struct cmd_struct *unused,
-		  const struct cmd_context *cmdcxt, int argc, char **argv)
-{
-	return handle_command_group(&subvolume_cmd_group, cmdcxt, argc, argv);
-}
 DEFINE_GROUP_COMMAND_TOKEN(subvolume);
commands.h +4 -3
index bf74eaf8..65be8742 100644
@@ -107,7 +107,8 @@ struct cmd_struct {
 /*
  * Define a command for the common case - just a name and string.
  * It's assumed that the callback is called cmd_<name> and the usage
- * array is named cmd_<name>_usage.
+ * array is named cmd_<name>_usage.  Text is the only supported output
+ * format.
  */
 #define DEFINE_SIMPLE_COMMAND(name, token)				\
 	DEFINE_COMMAND(name, token, cmd_ ##name,			\
@@ -119,7 +120,7 @@ struct cmd_struct {
  * struct cmd_group is called <name>_cmd_group.
  */
 #define DEFINE_GROUP_COMMAND(name, token)				\
-	DEFINE_COMMAND(name, token, cmd_ ##name,			\
+	DEFINE_COMMAND(name, token, handle_command_group,		\
 		       NULL, &(name ## _cmd_group), 0, 0)
 
 /*
@@ -143,7 +144,7 @@ static inline int cmd_execute(const struct cmd_struct *cmd,
 	return cmd->fn(cmd, cmdcxt, argc, argv);
 }
 
-int handle_command_group(const struct cmd_group *grp,
+int handle_command_group(const struct cmd_struct *cmd,
 			 const struct cmd_context *cmdcxt,
 			 int argc, char **argv);
 
Signature · 1 line
2.12.3