Btrfs-progs: btrfs-list: split list_subvols
authorChris Mason <chris.mason@oracle.com>
Wed, 2 Nov 2011 15:22:09 +0000 (11:22 -0400)
committerChris Mason <chris.mason@oracle.com>
Wed, 2 Nov 2011 15:36:30 +0000 (11:36 -0400)
split list_subvols to separate functions and allow printing only in the
containing function. lets us make use of those functions when resolving
logical addresses.

Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
btrfs-list.c

index 817a450..bd0df9e 100644 (file)
@@ -199,10 +199,9 @@ static int add_root(struct root_lookup *root_lookup,
  * 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, int print_parent)
+static int resolve_root(struct root_lookup *rl, struct root_info *ri,
+                       u64 *root_id, u64 *parent_id, u64 *top_id, char **path)
 {
-       u64 top_id;
-       u64 parent_id = 0;
        char *full_path = NULL;
        int len = 0;
        struct root_info *found;
@@ -211,6 +210,7 @@ static int resolve_root(struct root_lookup *rl, struct root_info *ri, int print_
         * we go backwards from the root_info object and add pathnames
         * from parent directories as we go.
         */
+       *parent_id = 0;
        found = ri;
        while (1) {
                char *tmp;
@@ -234,13 +234,12 @@ static int resolve_root(struct root_lookup *rl, struct root_info *ri, int print_
 
                next = found->ref_tree;
                /* record the first parent */
-               if ( parent_id == 0 ) {
-                       parent_id = next;
-               }
+               if (*parent_id == 0)
+                       *parent_id = next;
 
                /* if the ref_tree refers to ourselves, we're at the top */
                if (next == found->root_id) {
-                       top_id = next;
+                       *top_id = next;
                        break;
                }
 
@@ -250,20 +249,14 @@ static int resolve_root(struct root_lookup *rl, struct root_info *ri, int print_
                 */
                found = tree_search(&rl->root, next);
                if (!found) {
-                       top_id = next;
+                       *top_id = next;
                        break;
                }
        }
-       if (print_parent) {
-               printf("ID %llu parent %llu top level %llu path %s\n",
-                      (unsigned long long)ri->root_id, (unsigned long long)parent_id, (unsigned long long)top_id,
-                       full_path);
-       } else {
-               printf("ID %llu top level %llu path %s\n",
-                      (unsigned long long)ri->root_id, (unsigned long long)top_id,
-                       full_path);
-       }
-       free(full_path);
+
+       *root_id = ri->root_id;
+       *path = full_path;
+
        return 0;
 }
 
@@ -560,25 +553,23 @@ build:
        return full;
 }
 
-int list_subvols(int fd, int print_parent, int get_default)
+static int __list_subvol_search(int fd, struct root_lookup *root_lookup)
 {
-       struct root_lookup root_lookup;
-       struct rb_node *n;
        int ret;
        struct btrfs_ioctl_search_args args;
        struct btrfs_ioctl_search_key *sk = &args.key;
        struct btrfs_ioctl_search_header *sh;
        struct btrfs_root_ref *ref;
-       struct btrfs_dir_item *di;
        unsigned long off = 0;
        int name_len;
        char *name;
        u64 dir_id;
-       u64 subvol_id = 0;
        int i;
-       int e;
 
-       root_lookup_init(&root_lookup);
+       root_lookup_init(root_lookup);
+       memset(&args, 0, sizeof(args));
+
+       root_lookup_init(root_lookup);
 
        memset(&args, 0, sizeof(args));
 
@@ -605,12 +596,8 @@ int list_subvols(int fd, int print_parent, int get_default)
 
        while(1) {
                ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
-               e = errno;
-               if (ret < 0) {
-                       fprintf(stderr, "ERROR: can't perform the search - %s\n",
-                               strerror(e));
+               if (ret < 0)
                        return ret;
-               }
                /* the ioctl returns the number of item it found in nr_items */
                if (sk->nr_items == 0)
                        break;
@@ -631,7 +618,7 @@ int list_subvols(int fd, int print_parent, int get_default)
                                name = (char *)(ref + 1);
                                dir_id = btrfs_stack_root_ref_dirid(ref);
 
-                               add_root(&root_lookup, sh->objectid, sh->offset,
+                               add_root(root_lookup, sh->objectid, sh->offset,
                                         dir_id, name, name_len);
                        }
 
@@ -656,11 +643,15 @@ int list_subvols(int fd, int print_parent, int get_default)
                } else
                        break;
        }
-       /*
-        * now we have an rbtree full of root_info objects, but we need to fill
-        * in their path names within the subvol that is referencing each one.
-        */
-       n = rb_first(&root_lookup.root);
+
+       return 0;
+}
+
+static int __list_subvol_fill_paths(int fd, struct root_lookup *root_lookup)
+{
+       struct rb_node *n;
+
+       n = rb_first(&root_lookup->root);
        while (n) {
                struct root_info *entry;
                int ret;
@@ -671,52 +662,30 @@ int list_subvols(int fd, int print_parent, int get_default)
                n = rb_next(n);
        }
 
-       memset(&args, 0, sizeof(args));
-
-       /* search in the tree of tree roots */
-       sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
-
-       /* search dir item */
-       sk->max_type = BTRFS_DIR_ITEM_KEY;
-       sk->min_type = BTRFS_DIR_ITEM_KEY;
-
-       sk->max_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
-       sk->min_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
-       sk->max_offset = (u64)-1;
-       sk->max_transid = (u64)-1;
-
-       /* just a big number, doesn't matter much */
-       sk->nr_items = 4096;
-
-       /* try to get the objectid of default subvolume */
-       if (get_default) {
-               ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
-               if (ret < 0) {
-                       fprintf(stderr, "ERROR: can't perform the search\n");
-                       return ret;
-               }
+       return 0;
+}
 
-               off = 0;
-               /* go through each item to find dir item named "default" */
-               for (i = 0; i < sk->nr_items; i++) {
-                       sh = (struct btrfs_ioctl_search_header *)(args.buf +
-                                                                 off);
-                       off += sizeof(*sh);
-                       if (sh->type == BTRFS_DIR_ITEM_KEY) {
-                               di = (struct btrfs_dir_item *)(args.buf + off);
-                               name_len = le16_to_cpu(di->name_len);
-                               name = (char *)di + sizeof(struct btrfs_dir_item);
-                               if (!strncmp("default", name, name_len)) {
-                                       subvol_id = btrfs_disk_key_objectid(
-                                               &di->location);
-                                       break;
-                               }
-                       }
+int list_subvols(int fd, int print_parent)
+{
+       struct root_lookup root_lookup;
+       struct rb_node *n;
+       int ret;
 
-                       off += sh->len;
-               }
+       ret = __list_subvol_search(fd, &root_lookup);
+       if (ret) {
+               fprintf(stderr, "ERROR: can't perform the search - %s\n",
+                               strerror(errno));
+               return ret;
        }
 
+       /*
+        * now we have an rbtree full of root_info objects, but we need to fill
+        * in their path names within the subvol that is referencing each one.
+        */
+       ret = __list_subvol_fill_paths(fd, &root_lookup);
+       if (ret < 0)
+               return ret;
+
        /* now that we have all the subvol-relative paths filled in,
         * we have to string the subvols together so that we can get
         * a path all the way back to the FS root
@@ -724,14 +693,24 @@ int list_subvols(int fd, int print_parent, int get_default)
        n = rb_last(&root_lookup.root);
        while (n) {
                struct root_info *entry;
+               u64 root_id;
+               u64 level;
+               u64 parent_id;
+               char *path;
                entry = rb_entry(n, struct root_info, rb_node);
-               if (!get_default)
-                       resolve_root(&root_lookup, entry, print_parent);
-               /* we only want the default subvolume */
-               else if (subvol_id == entry->root_id)
-                       resolve_root(&root_lookup, entry, print_parent);
-               else if (subvol_id == 0)
-                       break;
+               resolve_root(&root_lookup, entry, &root_id, &parent_id,
+                               &level, &path);
+               if (print_parent) {
+                       printf("ID %llu parent %llu top level %llu path %s\n",
+                               (unsigned long long)root_id,
+                               (unsigned long long)parent_id,
+                               (unsigned long long)level, path);
+               } else {
+                       printf("ID %llu top level %llu path %s\n",
+                               (unsigned long long)root_id,
+                               (unsigned long long)level, path);
+               }
+               free(path);
                n = rb_prev(n);
        }