From: Miao Xie <mi...@cn.fujitsu.com>

We want 'btrfs subvolume list' only to list readonly subvolumes, this patch set
introduces a new option 'r' to implement it.

You can use the command like that:

        btrfs subvolume list -r <path>

Original-Signed-off-by: Zhou Bo <zhoub-f...@cn.fujitsu.com>
Signed-off-by: Miao Xie <mi...@cn.fujitsu.com>
---
Changelog v3 -> v4:
- re-base to the new list_subvols()

Changelog v2 -> v3:
- re-implement this function based on the new list_subvols()

Changelog v1 -> v2:
- change the changelog of the patches and make them more elaborate
---
 btrfs-list.c     |   39 ++++++++++++++++++++++++++++-----------
 btrfs-list.h     |    1 +
 cmds-subvolume.c |   13 +++++++++++--
 ctree.h          |    2 ++
 4 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/btrfs-list.c b/btrfs-list.c
index bace903..7c422bc 100644
--- a/btrfs-list.c
+++ b/btrfs-list.c
@@ -60,6 +60,9 @@ struct root_info {
        /* equal the offset of the root's key */
        u64 root_offset;
 
+       /* flags of the root */
+       u64 flags;
+
        /* the id of the root that references this one */
        u64 ref_tree;
 
@@ -395,9 +398,9 @@ 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 dir_id,
-                      char *name, int name_len, u64 ogen, u64 gen, time_t ot,
-                      void *uuid)
+                      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 ot, void *uuid)
 {
        struct root_info *ri;
 
@@ -420,6 +423,8 @@ static int update_root(struct root_lookup *root_lookup,
                ri->ref_tree = ref_tree;
        if (root_offset)
                ri->root_offset = root_offset;
+       if (flags)
+               ri->flags = flags;
        if (dir_id)
                ri->dir_id = dir_id;
        if (gen)
@@ -451,15 +456,15 @@ static int update_root(struct root_lookup *root_lookup,
  * uuid: uuid of the root
  */
 static int add_root(struct root_lookup *root_lookup,
-                   u64 root_id, u64 ref_tree, u64 root_offset, u64 dir_id,
-                   char *name, int name_len, u64 ogen, u64 gen, time_t ot,
-                   void *uuid)
+                   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 ot, void *uuid)
 {
        struct root_info *ri;
        int ret;
 
-       ret = update_root(root_lookup, root_id, ref_tree, root_offset, dir_id,
-                         name, name_len, ogen, gen, ot, uuid);
+       ret = update_root(root_lookup, root_id, ref_tree, root_offset, flags,
+                         dir_id, name, name_len, ogen, gen, ot, uuid);
        if (!ret)
                return 0;
 
@@ -486,6 +491,8 @@ static int add_root(struct root_lookup *root_lookup,
                ri->dir_id = dir_id;
        if (root_offset)
                ri->root_offset = root_offset;
+       if (flags)
+               ri->flags = flags;
        if (gen)
                ri->gen = gen;
        if (ogen)
@@ -962,6 +969,7 @@ static int __list_subvol_search(int fd, struct root_lookup 
*root_lookup)
        u64 dir_id;
        u64 gen = 0;
        u64 ogen;
+       u64 flags;
        int i;
        time_t t;
        u8 uuid[BTRFS_UUID_SIZE];
@@ -1017,11 +1025,12 @@ static int __list_subvol_search(int fd, struct 
root_lookup *root_lookup)
                                dir_id = btrfs_stack_root_ref_dirid(ref);
 
                                add_root(root_lookup, sh->objectid, sh->offset,
-                                        0, dir_id, name, name_len, 0, 0, 0,
+                                        0, 0, dir_id, name, name_len, 0, 0, 0,
                                         NULL);
                        } else if (sh->type == BTRFS_ROOT_ITEM_KEY) {
                                ri = (struct btrfs_root_item *)(args.buf + off);
                                gen = btrfs_root_generation(ri);
+                               flags = btrfs_root_flags(ri);
                                if(sh->len >
                                   sizeof(struct btrfs_root_item_v0)) {
                                        t = ri->otime.sec;
@@ -1034,8 +1043,8 @@ static int __list_subvol_search(int fd, struct 
root_lookup *root_lookup)
                                }
 
                                add_root(root_lookup, sh->objectid, 0,
-                                        sh->offset, 0, NULL, 0, ogen, gen, t,
-                                        uuid);
+                                        sh->offset, flags, 0, NULL, 0, ogen,
+                                        gen, t, uuid);
                        }
 
                        off += sh->len;
@@ -1080,9 +1089,17 @@ static int filter_snapshot(struct root_info *ri, void 
*arg)
        return !!ri->root_offset;
 }
 
+static int filter_flags(struct root_info *ri, void *arg)
+{
+       u64 flags = *((u64 *)arg);
+
+       return ri->flags & flags;
+}
+
 static btrfs_list_filter_func all_filter_funcs[] = {
        [BTRFS_LIST_FILTER_ROOTID]              = filter_by_rootid,
        [BTRFS_LIST_FILTER_SNAPSHOT_ONLY]       = filter_snapshot,
+       [BTRFS_LIST_FILTER_FLAGS]               = filter_flags,
 };
 
 struct btrfs_list_filter_set *btrfs_list_alloc_filter_set(void)
diff --git a/btrfs-list.h b/btrfs-list.h
index ca3eb7b..3d6bdc1 100644
--- a/btrfs-list.h
+++ b/btrfs-list.h
@@ -59,6 +59,7 @@ enum btrfs_list_column_enum {
 enum btrfs_list_filter_enum {
        BTRFS_LIST_FILTER_ROOTID,
        BTRFS_LIST_FILTER_SNAPSHOT_ONLY,
+       BTRFS_LIST_FILTER_FLAGS,
        BTRFS_LIST_FILTER_MAX,
 };
 
diff --git a/cmds-subvolume.c b/cmds-subvolume.c
index b1cf2bd..0ca1e15 100644
--- a/cmds-subvolume.c
+++ b/cmds-subvolume.c
@@ -259,13 +259,14 @@ static int cmd_subvol_delete(int argc, char **argv)
 }
 
 static const char * const cmd_subvol_list_usage[] = {
-       "btrfs subvolume list [-pu] [-s 0|1] <path>",
+       "btrfs subvolume list [-pur] [-s 0|1] <path>",
        "List subvolumes (and snapshots)",
        "",
        "-p           print parent ID",
        "-u           print the uuid of subvolumes (and snapshots)",
        "-s value     list snapshots with generation in ascending/descending 
order",
        "             (1: ascending, 0: descending)",
+       "-r           list readonly subvolumes(including snapshots)",
        NULL
 };
 
@@ -273,6 +274,7 @@ static int cmd_subvol_list(int argc, char **argv)
 {
        struct btrfs_list_filter_set *filter_set;
        struct btrfs_list_comparer_set *comparer_set;
+       u64 flags = 0;
        int fd;
        int ret;
        int order;
@@ -283,7 +285,7 @@ static int cmd_subvol_list(int argc, char **argv)
 
        optind = 1;
        while(1) {
-               int c = getopt(argc, argv, "ps:u");
+               int c = getopt(argc, argv, "ps:ur");
                if (c < 0)
                        break;
 
@@ -305,11 +307,18 @@ static int cmd_subvol_list(int argc, char **argv)
                case 'u':
                        btrfs_list_setup_print_column(BTRFS_LIST_UUID);
                        break;
+               case 'r':
+                       flags |= BTRFS_ROOT_SUBVOL_RDONLY;
+                       break;
                default:
                        usage(cmd_subvol_list_usage);
                }
        }
 
+       if (flags)
+               btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_FLAGS,
+                                       (void *)&flags);
+
        if (check_argc_exact(argc - optind, 1))
                usage(cmd_subvol_list_usage);
 
diff --git a/ctree.h b/ctree.h
index c55d033..4bb66ff 100644
--- a/ctree.h
+++ b/ctree.h
@@ -139,6 +139,8 @@ static int btrfs_csum_sizes[] = { 4, 0 };
 #define BTRFS_FT_XATTR         8
 #define BTRFS_FT_MAX           9
 
+#define BTRFS_ROOT_SUBVOL_RDONLY       (1ULL << 0)
+
 /*
  * the key defines the order in the tree, and so it also defines (optimal)
  * block layout.  objectid corresonds to the inode number.  The flags
-- 
1.7.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to