mirror of
https://github.com/kdave/btrfs-progs
synced 2025-01-10 16:00:17 +00:00
Btrfs-progs: enhance btrfs subvol list only to show read-only snapshots
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-fnst@cn.fujitsu.com> Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
This commit is contained in:
parent
162df1e30c
commit
3defb82384
37
btrfs-list.c
37
btrfs-list.c
@ -59,6 +59,9 @@ struct root_info {
|
|||||||
/* equal the offset of the root's key */
|
/* equal the offset of the root's key */
|
||||||
u64 root_offset;
|
u64 root_offset;
|
||||||
|
|
||||||
|
/* flags of the root */
|
||||||
|
u64 flags;
|
||||||
|
|
||||||
/* the id of the root that references this one */
|
/* the id of the root that references this one */
|
||||||
u64 ref_tree;
|
u64 ref_tree;
|
||||||
|
|
||||||
@ -394,9 +397,9 @@ static struct root_info *root_tree_search(struct root_lookup *root_tree,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int update_root(struct root_lookup *root_lookup,
|
static int update_root(struct root_lookup *root_lookup,
|
||||||
u64 root_id, u64 ref_tree, u64 root_offset, u64 dir_id,
|
u64 root_id, u64 ref_tree, u64 root_offset, u64 flags,
|
||||||
char *name, int name_len, u64 ogen, u64 gen, time_t ot,
|
u64 dir_id, char *name, int name_len, u64 ogen, u64 gen,
|
||||||
void *uuid)
|
time_t ot, void *uuid)
|
||||||
{
|
{
|
||||||
struct root_info *ri;
|
struct root_info *ri;
|
||||||
|
|
||||||
@ -419,6 +422,8 @@ static int update_root(struct root_lookup *root_lookup,
|
|||||||
ri->ref_tree = ref_tree;
|
ri->ref_tree = ref_tree;
|
||||||
if (root_offset)
|
if (root_offset)
|
||||||
ri->root_offset = root_offset;
|
ri->root_offset = root_offset;
|
||||||
|
if (flags)
|
||||||
|
ri->flags = flags;
|
||||||
if (dir_id)
|
if (dir_id)
|
||||||
ri->dir_id = dir_id;
|
ri->dir_id = dir_id;
|
||||||
if (gen)
|
if (gen)
|
||||||
@ -450,15 +455,15 @@ static int update_root(struct root_lookup *root_lookup,
|
|||||||
* uuid: uuid of the root
|
* uuid: uuid of the root
|
||||||
*/
|
*/
|
||||||
static int add_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 dir_id,
|
u64 root_id, u64 ref_tree, u64 root_offset, u64 flags,
|
||||||
char *name, int name_len, u64 ogen, u64 gen, time_t ot,
|
u64 dir_id, char *name, int name_len, u64 ogen, u64 gen,
|
||||||
void *uuid)
|
time_t ot, void *uuid)
|
||||||
{
|
{
|
||||||
struct root_info *ri;
|
struct root_info *ri;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = update_root(root_lookup, root_id, ref_tree, root_offset, dir_id,
|
ret = update_root(root_lookup, root_id, ref_tree, root_offset, flags,
|
||||||
name, name_len, ogen, gen, ot, uuid);
|
dir_id, name, name_len, ogen, gen, ot, uuid);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -485,6 +490,8 @@ static int add_root(struct root_lookup *root_lookup,
|
|||||||
ri->dir_id = dir_id;
|
ri->dir_id = dir_id;
|
||||||
if (root_offset)
|
if (root_offset)
|
||||||
ri->root_offset = root_offset;
|
ri->root_offset = root_offset;
|
||||||
|
if (flags)
|
||||||
|
ri->flags = flags;
|
||||||
if (gen)
|
if (gen)
|
||||||
ri->gen = gen;
|
ri->gen = gen;
|
||||||
if (ogen)
|
if (ogen)
|
||||||
@ -961,6 +968,7 @@ static int __list_subvol_search(int fd, struct root_lookup *root_lookup)
|
|||||||
u64 dir_id;
|
u64 dir_id;
|
||||||
u64 gen = 0;
|
u64 gen = 0;
|
||||||
u64 ogen;
|
u64 ogen;
|
||||||
|
u64 flags;
|
||||||
int i;
|
int i;
|
||||||
time_t t;
|
time_t t;
|
||||||
u8 uuid[BTRFS_UUID_SIZE];
|
u8 uuid[BTRFS_UUID_SIZE];
|
||||||
@ -1016,11 +1024,12 @@ static int __list_subvol_search(int fd, struct root_lookup *root_lookup)
|
|||||||
dir_id = btrfs_stack_root_ref_dirid(ref);
|
dir_id = btrfs_stack_root_ref_dirid(ref);
|
||||||
|
|
||||||
add_root(root_lookup, sh->objectid, sh->offset,
|
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);
|
NULL);
|
||||||
} else if (sh->type == BTRFS_ROOT_ITEM_KEY) {
|
} else if (sh->type == BTRFS_ROOT_ITEM_KEY) {
|
||||||
ri = (struct btrfs_root_item *)(args.buf + off);
|
ri = (struct btrfs_root_item *)(args.buf + off);
|
||||||
gen = btrfs_root_generation(ri);
|
gen = btrfs_root_generation(ri);
|
||||||
|
flags = btrfs_root_flags(ri);
|
||||||
if(sh->len >
|
if(sh->len >
|
||||||
sizeof(struct btrfs_root_item_v0)) {
|
sizeof(struct btrfs_root_item_v0)) {
|
||||||
t = ri->otime.sec;
|
t = ri->otime.sec;
|
||||||
@ -1033,8 +1042,8 @@ static int __list_subvol_search(int fd, struct root_lookup *root_lookup)
|
|||||||
}
|
}
|
||||||
|
|
||||||
add_root(root_lookup, sh->objectid, 0,
|
add_root(root_lookup, sh->objectid, 0,
|
||||||
sh->offset, 0, NULL, 0, ogen, gen, t,
|
sh->offset, flags, 0, NULL, 0, ogen,
|
||||||
uuid);
|
gen, t, uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
off += sh->len;
|
off += sh->len;
|
||||||
@ -1077,9 +1086,15 @@ static int filter_snapshot(struct root_info *ri, u64 data)
|
|||||||
return !!ri->root_offset;
|
return !!ri->root_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int filter_flags(struct root_info *ri, u64 flags)
|
||||||
|
{
|
||||||
|
return ri->flags & flags;
|
||||||
|
}
|
||||||
|
|
||||||
static btrfs_list_filter_func all_filter_funcs[] = {
|
static btrfs_list_filter_func all_filter_funcs[] = {
|
||||||
[BTRFS_LIST_FILTER_ROOTID] = filter_by_rootid,
|
[BTRFS_LIST_FILTER_ROOTID] = filter_by_rootid,
|
||||||
[BTRFS_LIST_FILTER_SNAPSHOT_ONLY] = filter_snapshot,
|
[BTRFS_LIST_FILTER_SNAPSHOT_ONLY] = filter_snapshot,
|
||||||
|
[BTRFS_LIST_FILTER_FLAGS] = filter_flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct btrfs_list_filter_set *btrfs_list_alloc_filter_set(void)
|
struct btrfs_list_filter_set *btrfs_list_alloc_filter_set(void)
|
||||||
|
@ -61,6 +61,7 @@ enum btrfs_list_column_enum {
|
|||||||
enum btrfs_list_filter_enum {
|
enum btrfs_list_filter_enum {
|
||||||
BTRFS_LIST_FILTER_ROOTID,
|
BTRFS_LIST_FILTER_ROOTID,
|
||||||
BTRFS_LIST_FILTER_SNAPSHOT_ONLY,
|
BTRFS_LIST_FILTER_SNAPSHOT_ONLY,
|
||||||
|
BTRFS_LIST_FILTER_FLAGS,
|
||||||
BTRFS_LIST_FILTER_MAX,
|
BTRFS_LIST_FILTER_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -259,13 +259,14 @@ static int cmd_subvol_delete(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char * const cmd_subvol_list_usage[] = {
|
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)",
|
"List subvolumes (and snapshots)",
|
||||||
"",
|
"",
|
||||||
"-p print parent ID",
|
"-p print parent ID",
|
||||||
"-u print the uuid of subvolumes (and snapshots)",
|
"-u print the uuid of subvolumes (and snapshots)",
|
||||||
"-s value list snapshots with generation in ascending/descending order",
|
"-s value list snapshots with generation in ascending/descending order",
|
||||||
" (1: ascending, 0: descending)",
|
" (1: ascending, 0: descending)",
|
||||||
|
"-r list readonly subvolumes (including snapshots)",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -273,6 +274,7 @@ static int cmd_subvol_list(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
struct btrfs_list_filter_set *filter_set;
|
struct btrfs_list_filter_set *filter_set;
|
||||||
struct btrfs_list_comparer_set *comparer_set;
|
struct btrfs_list_comparer_set *comparer_set;
|
||||||
|
u64 flags = 0;
|
||||||
int fd;
|
int fd;
|
||||||
int ret;
|
int ret;
|
||||||
int order;
|
int order;
|
||||||
@ -283,7 +285,7 @@ static int cmd_subvol_list(int argc, char **argv)
|
|||||||
|
|
||||||
optind = 1;
|
optind = 1;
|
||||||
while(1) {
|
while(1) {
|
||||||
int c = getopt(argc, argv, "ps:u");
|
int c = getopt(argc, argv, "ps:ur");
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -305,11 +307,18 @@ static int cmd_subvol_list(int argc, char **argv)
|
|||||||
case 'u':
|
case 'u':
|
||||||
btrfs_list_setup_print_column(BTRFS_LIST_UUID);
|
btrfs_list_setup_print_column(BTRFS_LIST_UUID);
|
||||||
break;
|
break;
|
||||||
|
case 'r':
|
||||||
|
flags |= BTRFS_ROOT_SUBVOL_RDONLY;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage(cmd_subvol_list_usage);
|
usage(cmd_subvol_list_usage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags)
|
||||||
|
btrfs_list_setup_filter(&filter_set, BTRFS_LIST_FILTER_FLAGS,
|
||||||
|
flags);
|
||||||
|
|
||||||
if (check_argc_exact(argc - optind, 1))
|
if (check_argc_exact(argc - optind, 1))
|
||||||
usage(cmd_subvol_list_usage);
|
usage(cmd_subvol_list_usage);
|
||||||
|
|
||||||
|
2
ctree.h
2
ctree.h
@ -139,6 +139,8 @@ static int btrfs_csum_sizes[] = { 4, 0 };
|
|||||||
#define BTRFS_FT_XATTR 8
|
#define BTRFS_FT_XATTR 8
|
||||||
#define BTRFS_FT_MAX 9
|
#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)
|
* the key defines the order in the tree, and so it also defines (optimal)
|
||||||
* block layout. objectid corresonds to the inode number. The flags
|
* block layout. objectid corresonds to the inode number. The flags
|
||||||
|
Loading…
Reference in New Issue
Block a user