X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=btrfs-list.c;h=b6d7658522207aee33c34c195b3d32364001be21;hb=90a16b10b328d63ea90b3f4a04fd52a0bc0b689f;hp=82001fbdf84d066335617fe879e432b9d26a9b4a;hpb=1aeb6baee382afe4c68cbeb3adbc5a82d1c8266e;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/btrfs-list.c b/btrfs-list.c index 82001fb..b6d7658 100644 --- a/btrfs-list.c +++ b/btrfs-list.c @@ -124,11 +124,6 @@ void btrfs_list_setup_print_column(enum btrfs_list_column_enum column) btrfs_list_columns[i].need_print = 1; } -static void root_lookup_init(struct root_lookup *tree) -{ - tree->root.rb_node = NULL; -} - static int comp_entry_with_rootid(struct root_info *entry1, struct root_info *entry2, int is_descending) @@ -282,7 +277,7 @@ static int sort_comp(struct root_info *entry1, struct root_info *entry2, int i, ret = 0; if (!set || !set->ncomps) - goto comp_rootid; + return comp_entry_with_rootid(entry1, entry2, 0); for (i = 0; i < set->ncomps; i++) { if (!set->comps[i].comp_func) @@ -297,10 +292,8 @@ static int sort_comp(struct root_info *entry1, struct root_info *entry2, rootid_compared = 1; } - if (!rootid_compared) { -comp_rootid: + if (!rootid_compared) ret = comp_entry_with_rootid(entry1, entry2, 0); - } return ret; } @@ -394,7 +387,7 @@ static struct root_info *root_tree_search(struct root_lookup *root_tree, static int update_root(struct root_lookup *root_lookup, u64 root_id, u64 ref_tree, u64 root_offset, u64 flags, u64 dir_id, char *name, int name_len, u64 ogen, u64 gen, - time_t otime, void *uuid, void *puuid, void *ruuid) + time_t otime, u8 *uuid, u8 *puuid, u8 *ruuid) { struct root_info *ri; @@ -457,7 +450,7 @@ static int update_root(struct root_lookup *root_lookup, static int add_root(struct root_lookup *root_lookup, u64 root_id, u64 ref_tree, u64 root_offset, u64 flags, u64 dir_id, char *name, int name_len, u64 ogen, u64 gen, - time_t otime, void *uuid, void *puuid, void *ruuid) + time_t otime, u8 *uuid, u8 *puuid, u8 *ruuid) { struct root_info *ri; int ret; @@ -511,14 +504,26 @@ static int add_root(struct root_lookup *root_lookup, memcpy(&ri->ruuid, ruuid, BTRFS_UUID_SIZE); ret = root_tree_insert(root_lookup, ri); - if (ret) { - error("failed to insert tree %llu", - (unsigned long long)root_id); + if (ret < 0) { + error("failed to insert subvolume %llu to tree: %s", + (unsigned long long)root_id, strerror(-ret)); exit(1); } return 0; } +/* + * Simplified add_root for back references, omits the uuid and original info + * parameters, root offset and flags. + */ +static int add_root_backref(struct root_lookup *root_lookup, u64 root_id, + u64 ref_tree, u64 dir_id, char *name, int name_len) +{ + return add_root(root_lookup, root_id, ref_tree, 0, 0, dir_id, name, + name_len, 0, 0, 0, NULL, NULL, NULL); +} + + static void free_root_info(struct rb_node *node) { struct root_info *ri; @@ -970,18 +975,15 @@ static int list_subvol_search(int fd, struct root_lookup *root_lookup) u64 ogen; u64 flags; int i; - u8 uuid[BTRFS_UUID_SIZE]; - u8 puuid[BTRFS_UUID_SIZE]; - u8 ruuid[BTRFS_UUID_SIZE]; - root_lookup_init(root_lookup); + root_lookup->root.rb_node = NULL; memset(&args, 0, sizeof(args)); sk->tree_id = BTRFS_ROOT_TREE_OBJECTID; /* 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; @@ -1009,11 +1011,16 @@ static int list_subvol_search(int fd, struct root_lookup *root_lookup) name = (char *)(ref + 1); dir_id = btrfs_stack_root_ref_dirid(ref); - add_root(root_lookup, sh.objectid, sh.offset, - 0, 0, dir_id, name, name_len, 0, 0, 0, - NULL, NULL, NULL); - } else if (sh.type == BTRFS_ROOT_ITEM_KEY) { + add_root_backref(root_lookup, sh.objectid, + sh.offset, dir_id, name, + name_len); + } 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]; + u8 ruuid[BTRFS_UUID_SIZE]; ri = (struct btrfs_root_item *)(args.buf + off); gen = btrfs_root_generation(ri); @@ -1258,7 +1265,7 @@ static void filter_and_sort_subvol(struct root_lookup *all_subvols, struct root_info *entry; int ret; - root_lookup_init(sort_tree); + sort_tree->root.rb_node = NULL; n = rb_last(&all_subvols->root); while (n) { @@ -1266,8 +1273,18 @@ static void filter_and_sort_subvol(struct root_lookup *all_subvols, ret = resolve_root(all_subvols, entry, top_id); if (ret == -ENOENT) { - entry->full_path = strdup("DELETED"); - entry->deleted = 1; + if (entry->root_id != BTRFS_FS_TREE_OBJECTID) { + entry->full_path = strdup("DELETED"); + entry->deleted = 1; + } else { + /* + * The full path is not supposed to be printed, + * but we don't want to print an empty string, + * in case it appears somewhere. + */ + entry->full_path = strdup("TOPLEVEL"); + entry->deleted = 0; + } } ret = filter_root(entry, filter_set); if (ret) @@ -1333,21 +1350,21 @@ static void print_subvolume_column(struct root_info *subv, strcpy(uuidparse, "-"); else uuid_unparse(subv->uuid, uuidparse); - printf("%s", uuidparse); + printf("%-36s", uuidparse); break; case BTRFS_LIST_PUUID: if (uuid_is_null(subv->puuid)) strcpy(uuidparse, "-"); else uuid_unparse(subv->puuid, uuidparse); - printf("%s", uuidparse); + printf("%-36s", uuidparse); break; case BTRFS_LIST_RUUID: if (uuid_is_null(subv->ruuid)) strcpy(uuidparse, "-"); else uuid_unparse(subv->ruuid, uuidparse); - printf("%s", uuidparse); + printf("%-36s", uuidparse); break; case BTRFS_LIST_PATH: BUG_ON(!subv->full_path); @@ -1452,6 +1469,11 @@ static void print_all_subvol_info(struct root_lookup *sorted_tree, n = rb_first(&sorted_tree->root); while (n) { entry = rb_entry(n, struct root_info, sort_node); + + /* The toplevel subvolume is not listed by default */ + if (entry->root_id == BTRFS_FS_TREE_OBJECTID) + goto next; + switch (layout) { case BTRFS_LIST_LAYOUT_DEFAULT: print_one_subvol_info_default(entry); @@ -1463,6 +1485,7 @@ static void print_all_subvol_info(struct root_lookup *sorted_tree, print_one_subvol_info_raw(entry, raw_prefix); break; } +next: n = rb_next(n); } } @@ -1519,6 +1542,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(""); + 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; @@ -1544,7 +1598,9 @@ int btrfs_get_subvol(int fd, struct root_info *the_ri) rbn = rb_next(rbn); continue; } - if (!comp_entry_with_rootid(the_ri, ri, 0)) { + + if (!comp_entry_with_rootid(the_ri, ri, 0) || + !uuid_compare(the_ri->uuid, ri->uuid)) { memcpy(the_ri, ri, offsetof(struct root_info, path)); the_ri->path = strdup_or_null(ri->path); the_ri->name = strdup_or_null(ri->name);