Btrfs-progs: restructure list_subvolumes

The current code of list_subvols() has very bad scalability, if we want to
add new filter conditions or new sort methods, we have to modify lots of code.

Beside that, the most code of list_snapshots() is similar to list_subvols(),

So I restructure list_subvols(), and split the subvolume filter function,
the subvolume sort function and the output function from list_subvols().
In order to implement it, we defined some importtant structures:
struct btrfs_list_filter {
	btrfs_list_filter_func filter_func;
	void *data;
};

struct btrfs_list_comparer {
	btrfs_list_comp_func comp_func;
	int is_descending;
};

struct {
	char	*name;
	char	*column_name;
	int	need_print;
} btrfs_list_columns[];

If we want to add a new filter condition, we can choose a suitable filter
function, or implement a new filter function[1], and add it into a set of
the filters, and then pass the filter set into list_subvols(). We also can
mix several filters (just add those filters into the set, and pass the set
into list_subvols()) if the users specify two or more filter conditions.

The subvolume sort function is similar to the subvolume filter function. The
differentiation is the order of comparers in the array which is passed into
list_subvols() show us the priority of the sort methods.

The output function is different with the above two functions, we define a
array to manage all the columns that can be outputed, and use a member variant
(->need_print) to control the output of the relative column. Some columns are
outputed by default. But we can change it according to the requirement of the
users.

After appling this patch, we needn't implement a independent list_snapshots()
function, just pass a filter function which is used to identify the snapshot
into list_subvols().

[1]: If we implement new filter functions or compare functions, we must add
them into the array all_filter_funcs or the array all_comp_funcs, and modify
the relative enum variants(btrfs_list_filter_enum, btrfs_list_comp_enum).

Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
This commit is contained in:
Miao Xie 2012-09-18 14:51:49 +08:00 committed by root
parent 7cb1cf7542
commit 162df1e30c
5 changed files with 728 additions and 446 deletions

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,74 @@
* Boston, MA 021110-1307, USA.
*/
int list_subvols(int fd, int print_parent, int get_default, int print_uuid);
int list_snapshots(int fd, int print_parent, int order, int print_uuid);
int find_updated_files(int fd, u64 root_id, u64 oldest_gen);
char *path_for_root(int fd, u64 root);
#include "kerncompat.h"
struct root_info;
typedef int (*btrfs_list_filter_func)(struct root_info *, u64);
typedef int (*btrfs_list_comp_func)(struct root_info *, struct root_info *,
int);
struct btrfs_list_filter {
btrfs_list_filter_func filter_func;
u64 data;
};
struct btrfs_list_comparer {
btrfs_list_comp_func comp_func;
int is_descending;
};
struct btrfs_list_filter_set {
int total;
int nfilters;
struct btrfs_list_filter filters[0];
};
struct btrfs_list_comparer_set {
int total;
int ncomps;
struct btrfs_list_comparer comps[0];
};
enum btrfs_list_column_enum {
BTRFS_LIST_OBJECTID,
BTRFS_LIST_GENERATION,
BTRFS_LIST_OGENERATION,
BTRFS_LIST_PARENT,
BTRFS_LIST_TOP_LEVEL,
BTRFS_LIST_OTIME,
BTRFS_LIST_UUID,
BTRFS_LIST_PATH,
BTRFS_LIST_ALL,
};
enum btrfs_list_filter_enum {
BTRFS_LIST_FILTER_ROOTID,
BTRFS_LIST_FILTER_SNAPSHOT_ONLY,
BTRFS_LIST_FILTER_MAX,
};
enum btrfs_list_comp_enum {
BTRFS_LIST_COMP_ROOTID,
BTRFS_LIST_COMP_OGEN,
BTRFS_LIST_COMP_GEN,
BTRFS_LIST_COMP_MAX,
};
void btrfs_list_setup_print_column(enum btrfs_list_column_enum column);
struct btrfs_list_filter_set *btrfs_list_alloc_filter_set(void);
void btrfs_list_free_filter_set(struct btrfs_list_filter_set *filter_set);
int btrfs_list_setup_filter(struct btrfs_list_filter_set **filter_set,
enum btrfs_list_filter_enum filter, u64 data);
struct btrfs_list_comparer_set *btrfs_list_alloc_comparer_set(void);
void btrfs_list_free_comparer_set(struct btrfs_list_comparer_set *comp_set);
int btrfs_list_setup_comparer(struct btrfs_list_comparer_set **comp_set,
enum btrfs_list_comp_enum comparer,
int is_descending);
int btrfs_list_subvols(int fd, struct btrfs_list_filter_set *filter_set,
struct btrfs_list_comparer_set *comp_set);
int btrfs_list_find_updated_files(int fd, u64 root_id, u64 oldest_gen);
int btrfs_list_get_default_subvolume(int fd, u64 *default_id);
char *btrfs_list_path_for_root(int fd, u64 root);

View file

@ -194,7 +194,7 @@ static int cmd_logical_resolve(int argc, char **argv)
char *name;
if (getpath) {
name = path_for_root(fd, root);
name = btrfs_list_path_for_root(fd, root);
if (IS_ERR(name))
return PTR_ERR(name);
if (!name) {

View file

@ -28,6 +28,7 @@
#include "ioctl.h"
#include "qgroup.h"
#include "ctree.h"
#include "commands.h"
#include "btrfs-list.h"
@ -270,13 +271,15 @@ static const char * const cmd_subvol_list_usage[] = {
static int cmd_subvol_list(int argc, char **argv)
{
struct btrfs_list_filter_set *filter_set;
struct btrfs_list_comparer_set *comparer_set;
int fd;
int ret;
int print_parent = 0;
int print_snap_only = 0;
int order = 0;
int order;
char *subvol;
int print_uuid = 0;
filter_set = btrfs_list_alloc_filter_set();
comparer_set = btrfs_list_alloc_comparer_set();
optind = 1;
while(1) {
@ -286,14 +289,21 @@ static int cmd_subvol_list(int argc, char **argv)
switch(c) {
case 'p':
print_parent = 1;
btrfs_list_setup_print_column(BTRFS_LIST_PARENT);
break;
case 's':
print_snap_only = 1;
order = atoi(optarg);
btrfs_list_setup_filter(&filter_set,
BTRFS_LIST_FILTER_SNAPSHOT_ONLY,
0);
btrfs_list_setup_comparer(&comparer_set,
BTRFS_LIST_COMP_OGEN,
!order);
btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION);
btrfs_list_setup_print_column(BTRFS_LIST_OTIME);
break;
case 'u':
print_uuid =1;
btrfs_list_setup_print_column(BTRFS_LIST_UUID);
break;
default:
usage(cmd_subvol_list_usage);
@ -320,10 +330,8 @@ static int cmd_subvol_list(int argc, char **argv)
fprintf(stderr, "ERROR: can't access '%s'\n", subvol);
return 12;
}
if (!print_snap_only)
ret = list_subvols(fd, print_parent, 0, print_uuid);
else
ret = list_snapshots(fd, print_parent, order, print_uuid);
ret = btrfs_list_subvols(fd, filter_set, comparer_set);
if (ret)
return 19;
return 0;
@ -483,6 +491,8 @@ static int cmd_subvol_get_default(int argc, char **argv)
int fd;
int ret;
char *subvol;
struct btrfs_list_filter_set *filter_set;
u64 default_id;
if (check_argc_exact(argc, 2))
usage(cmd_subvol_get_default_usage);
@ -504,7 +514,30 @@ static int cmd_subvol_get_default(int argc, char **argv)
fprintf(stderr, "ERROR: can't access '%s'\n", subvol);
return 12;
}
ret = list_subvols(fd, 0, 1, 0);
ret = btrfs_list_get_default_subvolume(fd, &default_id);
if (ret) {
fprintf(stderr, "ERROR: can't perform the search - %s\n",
strerror(errno));
return ret;
}
if (default_id == 0) {
fprintf(stderr, "ERROR: 'default' dir item not found\n");
return ret;
}
/* no need to resolve roots if FS_TREE is default */
if (default_id == BTRFS_FS_TREE_OBJECTID) {
printf("ID 5 (FS_TREE)\n");
return ret;
}
filter_set = btrfs_list_alloc_filter_set();
btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_ROOTID,
default_id);
ret = btrfs_list_subvols(fd, filter_set, NULL);
if (ret)
return 19;
return 0;
@ -585,7 +618,7 @@ static int cmd_find_new(int argc, char **argv)
fprintf(stderr, "ERROR: can't access '%s'\n", subvol);
return 12;
}
ret = find_updated_files(fd, 0, last_gen);
ret = btrfs_list_find_updated_files(fd, 0, last_gen);
if (ret)
return 19;
return 0;

View file

@ -244,7 +244,8 @@ int subvol_uuid_search_init(int mnt_fd, struct subvol_uuid_search *s)
if (!root_item_valid)
goto skip;
path = path_for_root(mnt_fd, sh->objectid);
path = btrfs_list_path_for_root(mnt_fd,
sh->objectid);
if (!path)
path = strdup("");
if (IS_ERR(path)) {