summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--btrfs-list.c24
-rw-r--r--btrfs-list.h4
-rw-r--r--cmds-subvolume.c8
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;