Btrfs-Progs: fix subvolumes's some full_path invaild problems.
authorWang Shilong <wangsl-fnst@cn.fujistu.com>
Thu, 27 Sep 2012 17:04:20 +0000 (01:04 +0800)
committerroot <root@localhost.localdomain>
Thu, 4 Oct 2012 20:26:33 +0000 (16:26 -0400)
In the privous way, we list all the subvolumes in the filesystem default.

But if a subvolume mounts on another directory, some result's full_path
may be invaild.

According to this, we try to list subvolumes under directoy only by default.

In this way, all the subvolume can be arrived by the full_path.

Signed-off-by: Wang Shilong <wangsl-fnst@cn.fujitsu.com>
btrfs-list.c
btrfs-list.h
cmds-subvolume.c

index d605871..f079d99 100644 (file)
@@ -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;
+}
index 9d3687e..cde4b3c 100644 (file)
@@ -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);
index 8399e72..b96af3e 100644 (file)
@@ -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)