summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--btrfs-list.c42
-rw-r--r--btrfs-list.h2
-rw-r--r--cmds-subvolume.c6
3 files changed, 45 insertions, 5 deletions
diff --git a/btrfs-list.c b/btrfs-list.c
index d605871c..f079d998 100644
--- a/btrfs-list.c
+++ b/btrfs-list.c
@@ -584,7 +584,8 @@ void __free_all_subvolumn(struct root_lookup *root_tree)
* This can't be called until all the root_info->path fields are filled
* in by lookup_ino_path
*/
-static int resolve_root(struct root_lookup *rl, struct root_info *ri)
+static int resolve_root(struct root_lookup *rl, struct root_info *ri,
+ u64 top_id)
{
char *full_path = NULL;
int len = 0;
@@ -621,6 +622,11 @@ static int resolve_root(struct root_lookup *rl, struct root_info *ri)
next = found->ref_tree;
+ if (next == top_id) {
+ ri->top_id = top_id;
+ break;
+ }
+
/* if the ref_tree refers to ourselves, we're at the top */
if (next == found->root_id) {
ri->top_id = next;
@@ -1157,6 +1163,11 @@ static int filter_cgen_equal(struct root_info *ri, u64 data)
return ri->ogen == data;
}
+static int filter_topid_equal(struct root_info *ri, u64 data)
+{
+ return ri->top_id == data;
+}
+
static btrfs_list_filter_func all_filter_funcs[] = {
[BTRFS_LIST_FILTER_ROOTID] = filter_by_rootid,
[BTRFS_LIST_FILTER_SNAPSHOT_ONLY] = filter_snapshot,
@@ -1167,6 +1178,7 @@ static btrfs_list_filter_func all_filter_funcs[] = {
[BTRFS_LIST_FILTER_CGEN_MORE] = filter_cgen_more,
[BTRFS_LIST_FILTER_CGEN_LESS] = filter_cgen_less,
[BTRFS_LIST_FILTER_CGEN_EQUAL] = filter_cgen_equal,
+ [BTRFS_LIST_FILTER_TOPID_EQUAL] = filter_topid_equal,
};
struct btrfs_list_filter_set *btrfs_list_alloc_filter_set(void)
@@ -1248,11 +1260,13 @@ static int filter_root(struct root_info *ri,
static void __filter_and_sort_subvol(struct root_lookup *all_subvols,
struct root_lookup *sort_tree,
struct btrfs_list_filter_set *filter_set,
- struct btrfs_list_comparer_set *comp_set)
+ struct btrfs_list_comparer_set *comp_set,
+ int fd)
{
struct rb_node *n;
struct root_info *entry;
int ret;
+ u64 top_id = btrfs_list_get_path_rootid(fd);
root_lookup_init(sort_tree);
@@ -1260,7 +1274,7 @@ static void __filter_and_sort_subvol(struct root_lookup *all_subvols,
while (n) {
entry = rb_entry(n, struct root_info, rb_node);
- resolve_root(all_subvols, entry);
+ resolve_root(all_subvols, entry, top_id);
ret = filter_root(entry, filter_set);
if (ret)
sort_tree_insert(sort_tree, entry, comp_set);
@@ -1443,7 +1457,7 @@ int btrfs_list_subvols(int fd, struct btrfs_list_filter_set *filter_set,
return ret;
__filter_and_sort_subvol(&root_lookup, &root_sort, filter_set,
- comp_set);
+ comp_set, fd);
print_all_volume_info(&root_sort, is_tab_result);
__free_all_subvolumn(&root_lookup);
@@ -1636,6 +1650,7 @@ char *btrfs_list_path_for_root(int fd, u64 root)
struct rb_node *n;
char *ret_path = NULL;
int ret;
+ u64 top_id = btrfs_list_get_path_rootid(fd);
ret = __list_subvol_search(fd, &root_lookup);
if (ret < 0)
@@ -1650,7 +1665,7 @@ char *btrfs_list_path_for_root(int fd, u64 root)
struct root_info *entry;
entry = rb_entry(n, struct root_info, rb_node);
- resolve_root(&root_lookup, entry);
+ resolve_root(&root_lookup, entry, top_id);
if (entry->root_id == root) {
ret_path = entry->full_path;
entry->full_path = NULL;
@@ -1758,3 +1773,20 @@ int btrfs_list_parse_filter_string(char *optarg,
return 0;
}
+u64 btrfs_list_get_path_rootid(int fd)
+{
+ int ret;
+ struct btrfs_ioctl_ino_lookup_args args;
+
+ memset(&args, 0, sizeof(args));
+ args.objectid = BTRFS_FIRST_FREE_OBJECTID;
+
+ ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args);
+ if (ret < 0) {
+ fprintf(stderr,
+ "ERROR: can't perform the search -%s\n",
+ strerror(errno));
+ return ret;
+ }
+ return args.treeid;
+}
diff --git a/btrfs-list.h b/btrfs-list.h
index 9d3687ea..cde4b3cc 100644
--- a/btrfs-list.h
+++ b/btrfs-list.h
@@ -70,6 +70,7 @@ enum btrfs_list_filter_enum {
BTRFS_LIST_FILTER_CGEN_EQUAL = BTRFS_LIST_FILTER_CGEN,
BTRFS_LIST_FILTER_CGEN_LESS,
BTRFS_LIST_FILTER_CGEN_MORE,
+ BTRFS_LIST_FILTER_TOPID_EQUAL,
BTRFS_LIST_FILTER_MAX,
};
@@ -103,3 +104,4 @@ int btrfs_list_subvols(int fd, struct btrfs_list_filter_set *filter_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);
+u64 btrfs_list_get_path_rootid(int fd);
diff --git a/cmds-subvolume.c b/cmds-subvolume.c
index 8399e72e..b96af3eb 100644
--- a/cmds-subvolume.c
+++ b/cmds-subvolume.c
@@ -289,6 +289,7 @@ static int cmd_subvol_list(int argc, char **argv)
struct btrfs_list_comparer_set *comparer_set;
u64 flags = 0;
int fd;
+ u64 top_id;
int ret;
int order;
int c;
@@ -387,6 +388,11 @@ static int cmd_subvol_list(int argc, char **argv)
return 12;
}
+ top_id = btrfs_list_get_path_rootid(fd);
+ btrfs_list_setup_filter(&filter_set,
+ BTRFS_LIST_FILTER_TOPID_EQUAL,
+ top_id);
+
ret = btrfs_list_subvols(fd, filter_set, comparer_set,
is_tab_result);
if (ret)