diff options
-rw-r--r-- | btrfs-list.c | 37 | ||||
-rw-r--r-- | btrfs-list.h | 1 | ||||
-rw-r--r-- | cmds-subvolume.c | 9 | ||||
-rw-r--r-- | utils.c | 13 |
4 files changed, 40 insertions, 20 deletions
diff --git a/btrfs-list.c b/btrfs-list.c index 8f207b6f..8eec05ea 100644 --- a/btrfs-list.c +++ b/btrfs-list.c @@ -983,7 +983,7 @@ static int list_subvol_search(int fd, struct root_lookup *root_lookup) /* Search both live and deleted subvolumes */ sk->min_type = BTRFS_ROOT_ITEM_KEY; sk->max_type = BTRFS_ROOT_BACKREF_KEY; - sk->min_objectid = BTRFS_FIRST_FREE_OBJECTID; + sk->min_objectid = BTRFS_FS_TREE_OBJECTID; sk->max_objectid = BTRFS_LAST_FREE_OBJECTID; sk->max_offset = (u64)-1; sk->max_transid = (u64)-1; @@ -1014,7 +1014,9 @@ static int list_subvol_search(int fd, struct root_lookup *root_lookup) add_root_backref(root_lookup, sh.objectid, sh.offset, dir_id, name, name_len); - } else if (sh.type == BTRFS_ROOT_ITEM_KEY) { + } else if (sh.type == BTRFS_ROOT_ITEM_KEY && + (sh.objectid >= BTRFS_FIRST_FREE_OBJECTID || + sh.objectid == BTRFS_FS_TREE_OBJECTID)) { time_t otime; u8 uuid[BTRFS_UUID_SIZE]; u8 puuid[BTRFS_UUID_SIZE]; @@ -1524,6 +1526,37 @@ static char *strdup_or_null(const char *s) return strdup(s); } +int btrfs_get_toplevel_subvol(int fd, struct root_info *the_ri) +{ + int ret; + struct root_lookup rl; + struct rb_node *rbn; + struct root_info *ri; + u64 root_id; + + ret = btrfs_list_get_path_rootid(fd, &root_id); + if (ret) + return ret; + + ret = btrfs_list_subvols(fd, &rl); + if (ret) + return ret; + + rbn = rb_first(&rl.root); + ri = rb_entry(rbn, struct root_info, rb_node); + + if (ri->root_id != BTRFS_FS_TREE_OBJECTID) + return -ENOENT; + + memcpy(the_ri, ri, offsetof(struct root_info, path)); + the_ri->path = strdup_or_null("/"); + the_ri->name = strdup_or_null("<FS_TREE>"); + the_ri->full_path = strdup_or_null("/"); + rb_free_nodes(&rl.root, free_root_info); + + return ret; +} + int btrfs_get_subvol(int fd, struct root_info *the_ri) { int ret, rr; diff --git a/btrfs-list.h b/btrfs-list.h index 528d5a98..6e5fc778 100644 --- a/btrfs-list.h +++ b/btrfs-list.h @@ -175,5 +175,6 @@ int btrfs_list_get_default_subvolume(int fd, u64 *default_id); 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); #endif diff --git a/cmds-subvolume.c b/cmds-subvolume.c index 9f220851..4cd2e0ec 100644 --- a/cmds-subvolume.c +++ b/cmds-subvolume.c @@ -921,15 +921,6 @@ static int cmd_subvol_show(int argc, char **argv) } ret = get_subvol_info(fullpath, &get_ri); - if (ret == 2) { - /* - * Since the top level btrfs was given don't - * take that as error - */ - printf("%s is toplevel subvolume\n", fullpath); - ret = 0; - goto out; - } if (ret) { if (ret < 0) { error("Failed to get subvol info %s: %s\n", @@ -4168,18 +4168,13 @@ int get_subvol_info(const char *fullpath, struct root_info *get_ri) if (mntfd < 0) goto out; - if (sv_id == BTRFS_FS_TREE_OBJECTID) { - ret = 2; - /* - * So that caller may decide if thats an error or just fine. - */ - goto out; - } - memset(get_ri, 0, sizeof(*get_ri)); get_ri->root_id = sv_id; - ret = btrfs_get_subvol(mntfd, get_ri); + if (sv_id == BTRFS_FS_TREE_OBJECTID) + ret = btrfs_get_toplevel_subvol(mntfd, get_ri); + else + ret = btrfs_get_subvol(mntfd, get_ri); if (ret) error("can't find '%s': %d", svpath, ret); |