mirror of
https://github.com/kdave/btrfs-progs
synced 2025-04-21 22:45:18 +00:00
Btrfs-progs: btrfs-list: split list_subvols
split list_subvols to separate functions and allow printing only in the containing function. lets us make use of those functions when resolving logical addresses. Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net> Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
bb42e12554
commit
bab2c565cc
149
btrfs-list.c
149
btrfs-list.c
@ -199,10 +199,9 @@ static int add_root(struct root_lookup *root_lookup,
|
|||||||
* This can't be called until all the root_info->path fields are filled
|
* This can't be called until all the root_info->path fields are filled
|
||||||
* in by lookup_ino_path
|
* in by lookup_ino_path
|
||||||
*/
|
*/
|
||||||
static int resolve_root(struct root_lookup *rl, struct root_info *ri, int print_parent)
|
static int resolve_root(struct root_lookup *rl, struct root_info *ri,
|
||||||
|
u64 *root_id, u64 *parent_id, u64 *top_id, char **path)
|
||||||
{
|
{
|
||||||
u64 top_id;
|
|
||||||
u64 parent_id = 0;
|
|
||||||
char *full_path = NULL;
|
char *full_path = NULL;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
struct root_info *found;
|
struct root_info *found;
|
||||||
@ -211,6 +210,7 @@ static int resolve_root(struct root_lookup *rl, struct root_info *ri, int print_
|
|||||||
* we go backwards from the root_info object and add pathnames
|
* we go backwards from the root_info object and add pathnames
|
||||||
* from parent directories as we go.
|
* from parent directories as we go.
|
||||||
*/
|
*/
|
||||||
|
*parent_id = 0;
|
||||||
found = ri;
|
found = ri;
|
||||||
while (1) {
|
while (1) {
|
||||||
char *tmp;
|
char *tmp;
|
||||||
@ -234,13 +234,12 @@ static int resolve_root(struct root_lookup *rl, struct root_info *ri, int print_
|
|||||||
|
|
||||||
next = found->ref_tree;
|
next = found->ref_tree;
|
||||||
/* record the first parent */
|
/* record the first parent */
|
||||||
if ( parent_id == 0 ) {
|
if (*parent_id == 0)
|
||||||
parent_id = next;
|
*parent_id = next;
|
||||||
}
|
|
||||||
|
|
||||||
/* if the ref_tree refers to ourselves, we're at the top */
|
/* if the ref_tree refers to ourselves, we're at the top */
|
||||||
if (next == found->root_id) {
|
if (next == found->root_id) {
|
||||||
top_id = next;
|
*top_id = next;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,20 +249,14 @@ static int resolve_root(struct root_lookup *rl, struct root_info *ri, int print_
|
|||||||
*/
|
*/
|
||||||
found = tree_search(&rl->root, next);
|
found = tree_search(&rl->root, next);
|
||||||
if (!found) {
|
if (!found) {
|
||||||
top_id = next;
|
*top_id = next;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (print_parent) {
|
|
||||||
printf("ID %llu parent %llu top level %llu path %s\n",
|
*root_id = ri->root_id;
|
||||||
(unsigned long long)ri->root_id, (unsigned long long)parent_id, (unsigned long long)top_id,
|
*path = full_path;
|
||||||
full_path);
|
|
||||||
} else {
|
|
||||||
printf("ID %llu top level %llu path %s\n",
|
|
||||||
(unsigned long long)ri->root_id, (unsigned long long)top_id,
|
|
||||||
full_path);
|
|
||||||
}
|
|
||||||
free(full_path);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,25 +553,23 @@ build:
|
|||||||
return full;
|
return full;
|
||||||
}
|
}
|
||||||
|
|
||||||
int list_subvols(int fd, int print_parent, int get_default)
|
static int __list_subvol_search(int fd, struct root_lookup *root_lookup)
|
||||||
{
|
{
|
||||||
struct root_lookup root_lookup;
|
|
||||||
struct rb_node *n;
|
|
||||||
int ret;
|
int ret;
|
||||||
struct btrfs_ioctl_search_args args;
|
struct btrfs_ioctl_search_args args;
|
||||||
struct btrfs_ioctl_search_key *sk = &args.key;
|
struct btrfs_ioctl_search_key *sk = &args.key;
|
||||||
struct btrfs_ioctl_search_header *sh;
|
struct btrfs_ioctl_search_header *sh;
|
||||||
struct btrfs_root_ref *ref;
|
struct btrfs_root_ref *ref;
|
||||||
struct btrfs_dir_item *di;
|
|
||||||
unsigned long off = 0;
|
unsigned long off = 0;
|
||||||
int name_len;
|
int name_len;
|
||||||
char *name;
|
char *name;
|
||||||
u64 dir_id;
|
u64 dir_id;
|
||||||
u64 subvol_id = 0;
|
|
||||||
int i;
|
int i;
|
||||||
int e;
|
|
||||||
|
|
||||||
root_lookup_init(&root_lookup);
|
root_lookup_init(root_lookup);
|
||||||
|
memset(&args, 0, sizeof(args));
|
||||||
|
|
||||||
|
root_lookup_init(root_lookup);
|
||||||
|
|
||||||
memset(&args, 0, sizeof(args));
|
memset(&args, 0, sizeof(args));
|
||||||
|
|
||||||
@ -605,12 +596,8 @@ int list_subvols(int fd, int print_parent, int get_default)
|
|||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
|
ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
|
||||||
e = errno;
|
if (ret < 0)
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "ERROR: can't perform the search - %s\n",
|
|
||||||
strerror(e));
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
|
||||||
/* the ioctl returns the number of item it found in nr_items */
|
/* the ioctl returns the number of item it found in nr_items */
|
||||||
if (sk->nr_items == 0)
|
if (sk->nr_items == 0)
|
||||||
break;
|
break;
|
||||||
@ -631,7 +618,7 @@ int list_subvols(int fd, int print_parent, int get_default)
|
|||||||
name = (char *)(ref + 1);
|
name = (char *)(ref + 1);
|
||||||
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,
|
||||||
dir_id, name, name_len);
|
dir_id, name, name_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,11 +643,15 @@ int list_subvols(int fd, int print_parent, int get_default)
|
|||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* now we have an rbtree full of root_info objects, but we need to fill
|
return 0;
|
||||||
* in their path names within the subvol that is referencing each one.
|
}
|
||||||
*/
|
|
||||||
n = rb_first(&root_lookup.root);
|
static int __list_subvol_fill_paths(int fd, struct root_lookup *root_lookup)
|
||||||
|
{
|
||||||
|
struct rb_node *n;
|
||||||
|
|
||||||
|
n = rb_first(&root_lookup->root);
|
||||||
while (n) {
|
while (n) {
|
||||||
struct root_info *entry;
|
struct root_info *entry;
|
||||||
int ret;
|
int ret;
|
||||||
@ -671,52 +662,30 @@ int list_subvols(int fd, int print_parent, int get_default)
|
|||||||
n = rb_next(n);
|
n = rb_next(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&args, 0, sizeof(args));
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* search in the tree of tree roots */
|
int list_subvols(int fd, int print_parent)
|
||||||
sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
|
{
|
||||||
|
struct root_lookup root_lookup;
|
||||||
|
struct rb_node *n;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* search dir item */
|
ret = __list_subvol_search(fd, &root_lookup);
|
||||||
sk->max_type = BTRFS_DIR_ITEM_KEY;
|
if (ret) {
|
||||||
sk->min_type = BTRFS_DIR_ITEM_KEY;
|
fprintf(stderr, "ERROR: can't perform the search - %s\n",
|
||||||
|
strerror(errno));
|
||||||
sk->max_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
|
return ret;
|
||||||
sk->min_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
|
|
||||||
sk->max_offset = (u64)-1;
|
|
||||||
sk->max_transid = (u64)-1;
|
|
||||||
|
|
||||||
/* just a big number, doesn't matter much */
|
|
||||||
sk->nr_items = 4096;
|
|
||||||
|
|
||||||
/* try to get the objectid of default subvolume */
|
|
||||||
if (get_default) {
|
|
||||||
ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
|
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "ERROR: can't perform the search\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
off = 0;
|
|
||||||
/* go through each item to find dir item named "default" */
|
|
||||||
for (i = 0; i < sk->nr_items; i++) {
|
|
||||||
sh = (struct btrfs_ioctl_search_header *)(args.buf +
|
|
||||||
off);
|
|
||||||
off += sizeof(*sh);
|
|
||||||
if (sh->type == BTRFS_DIR_ITEM_KEY) {
|
|
||||||
di = (struct btrfs_dir_item *)(args.buf + off);
|
|
||||||
name_len = le16_to_cpu(di->name_len);
|
|
||||||
name = (char *)di + sizeof(struct btrfs_dir_item);
|
|
||||||
if (!strncmp("default", name, name_len)) {
|
|
||||||
subvol_id = btrfs_disk_key_objectid(
|
|
||||||
&di->location);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
off += sh->len;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* now we have an rbtree full of root_info objects, but we need to fill
|
||||||
|
* in their path names within the subvol that is referencing each one.
|
||||||
|
*/
|
||||||
|
ret = __list_subvol_fill_paths(fd, &root_lookup);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* now that we have all the subvol-relative paths filled in,
|
/* now that we have all the subvol-relative paths filled in,
|
||||||
* we have to string the subvols together so that we can get
|
* we have to string the subvols together so that we can get
|
||||||
* a path all the way back to the FS root
|
* a path all the way back to the FS root
|
||||||
@ -724,14 +693,24 @@ int list_subvols(int fd, int print_parent, int get_default)
|
|||||||
n = rb_last(&root_lookup.root);
|
n = rb_last(&root_lookup.root);
|
||||||
while (n) {
|
while (n) {
|
||||||
struct root_info *entry;
|
struct root_info *entry;
|
||||||
|
u64 root_id;
|
||||||
|
u64 level;
|
||||||
|
u64 parent_id;
|
||||||
|
char *path;
|
||||||
entry = rb_entry(n, struct root_info, rb_node);
|
entry = rb_entry(n, struct root_info, rb_node);
|
||||||
if (!get_default)
|
resolve_root(&root_lookup, entry, &root_id, &parent_id,
|
||||||
resolve_root(&root_lookup, entry, print_parent);
|
&level, &path);
|
||||||
/* we only want the default subvolume */
|
if (print_parent) {
|
||||||
else if (subvol_id == entry->root_id)
|
printf("ID %llu parent %llu top level %llu path %s\n",
|
||||||
resolve_root(&root_lookup, entry, print_parent);
|
(unsigned long long)root_id,
|
||||||
else if (subvol_id == 0)
|
(unsigned long long)parent_id,
|
||||||
break;
|
(unsigned long long)level, path);
|
||||||
|
} else {
|
||||||
|
printf("ID %llu top level %llu path %s\n",
|
||||||
|
(unsigned long long)root_id,
|
||||||
|
(unsigned long long)level, path);
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
n = rb_prev(n);
|
n = rb_prev(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user