diff options
-rw-r--r-- | btrfs-list.c | 24 | ||||
-rw-r--r-- | btrfs-list.h | 4 | ||||
-rw-r--r-- | cmds-subvolume.c | 8 |
3 files changed, 32 insertions, 4 deletions
diff --git a/btrfs-list.c b/btrfs-list.c index 9411e4d1..f3618b9c 100644 --- a/btrfs-list.c +++ b/btrfs-list.c @@ -1173,6 +1173,11 @@ static int filter_by_parent(struct root_info *ri, u64 data) return !uuid_compare(ri->puuid, (u8 *)(unsigned long)data); } +static int filter_deleted(struct root_info *ri, u64 data) +{ + return ri->deleted; +} + static btrfs_list_filter_func all_filter_funcs[] = { [BTRFS_LIST_FILTER_ROOTID] = filter_by_rootid, [BTRFS_LIST_FILTER_SNAPSHOT_ONLY] = filter_snapshot, @@ -1186,6 +1191,7 @@ static btrfs_list_filter_func all_filter_funcs[] = { [BTRFS_LIST_FILTER_TOPID_EQUAL] = filter_topid_equal, [BTRFS_LIST_FILTER_FULL_PATH] = filter_full_path, [BTRFS_LIST_FILTER_BY_PARENT] = filter_by_parent, + [BTRFS_LIST_FILTER_DELETED] = filter_deleted, }; struct btrfs_list_filter_set *btrfs_list_alloc_filter_set(void) @@ -1222,6 +1228,11 @@ int btrfs_list_setup_filter(struct btrfs_list_filter_set **filter_set, BUG_ON(filter >= BTRFS_LIST_FILTER_MAX); BUG_ON(set->nfilters > set->total); + if (filter == BTRFS_LIST_FILTER_DELETED) { + set->only_deleted = 1; + return 0; + } + if (set->nfilters == set->total) { size = set->total + BTRFS_LIST_NFILTERS_INCREASE; size = sizeof(*set) + size * sizeof(struct btrfs_list_filter); @@ -1254,6 +1265,12 @@ static int filter_root(struct root_info *ri, if (!set || !set->nfilters) return 1; + if (set->only_deleted && !ri->deleted) + return 0; + + if (!set->only_deleted && ri->deleted) + return 0; + for (i = 0; i < set->nfilters; i++) { if (!set->filters[i].filter_func) break; @@ -1281,12 +1298,13 @@ static void __filter_and_sort_subvol(struct root_lookup *all_subvols, entry = rb_entry(n, struct root_info, rb_node); ret = resolve_root(all_subvols, entry, top_id); - if (ret == -ENOENT) - goto skip; + if (ret == -ENOENT) { + entry->full_path = strdup("DELETED"); + entry->deleted = 1; + } ret = filter_root(entry, filter_set); if (ret) sort_tree_insert(sort_tree, entry, comp_set); -skip: n = rb_prev(n); } } diff --git a/btrfs-list.h b/btrfs-list.h index 51644673..724e9737 100644 --- a/btrfs-list.h +++ b/btrfs-list.h @@ -71,6 +71,8 @@ struct root_info { char *name; char *full_path; + + int deleted; }; typedef int (*btrfs_list_filter_func)(struct root_info *, u64); @@ -90,6 +92,7 @@ struct btrfs_list_comparer { struct btrfs_list_filter_set { int total; int nfilters; + int only_deleted; struct btrfs_list_filter filters[0]; }; @@ -127,6 +130,7 @@ enum btrfs_list_filter_enum { BTRFS_LIST_FILTER_TOPID_EQUAL, BTRFS_LIST_FILTER_FULL_PATH, BTRFS_LIST_FILTER_BY_PARENT, + BTRFS_LIST_FILTER_DELETED, BTRFS_LIST_FILTER_MAX, }; diff --git a/cmds-subvolume.c b/cmds-subvolume.c index 63c708ef..76dab1f4 100644 --- a/cmds-subvolume.c +++ b/cmds-subvolume.c @@ -317,6 +317,7 @@ static const char * const cmd_subvol_list_usage[] = { "-t print the result as a table", "-s list snapshots only in the filesystem", "-r list readonly subvolumes (including snapshots)", + "-d list deleted subvolumes that are not yet cleaned", "-G [+|-]value", " filter the subvolumes by generation", " (+value: >= value; -value: <= value; value: = value)", @@ -355,7 +356,7 @@ static int cmd_subvol_list(int argc, char **argv) optind = 1; while(1) { c = getopt_long(argc, argv, - "acgopqsurG:C:t", long_options, NULL); + "acdgopqsurG:C:t", long_options, NULL); if (c < 0) break; @@ -369,6 +370,11 @@ static int cmd_subvol_list(int argc, char **argv) case 'c': btrfs_list_setup_print_column(BTRFS_LIST_OGENERATION); break; + case 'd': + btrfs_list_setup_filter(&filter_set, + BTRFS_LIST_FILTER_DELETED, + 0); + break; case 'g': btrfs_list_setup_print_column(BTRFS_LIST_GENERATION); break; |