Btrfs-progs: add "btrfs subvolume get-default" subcommand

Add subcommand to get the default subvolume of btrfs filesystem

V2->V3:
* add man page
* based on http://git.darksatanic.net/repo/btrfs-progs-unstable.git
  integration-20110705

Reviewed-by: Andreas Philipp <philipp.andreas@gmail.com>
Reviewed-by: Goffredo Baroncelli <kreijack@libero.it>
Reported-by: Yang, Yi <yi.y.yang@intel.com>
Signed-off-by: Zhong, Xin <xin.zhong@intel.com>
This commit is contained in:
Zhong, Xin 2011-07-12 10:48:37 +08:00 committed by Chris Mason
parent fdbebea13b
commit a70b0b2bba
5 changed files with 98 additions and 4 deletions

View file

@ -560,7 +560,7 @@ build:
return full;
}
int list_subvols(int fd, int print_parent)
int list_subvols(int fd, int print_parent, int get_default)
{
struct root_lookup root_lookup;
struct rb_node *n;
@ -569,10 +569,12 @@ int list_subvols(int fd, int print_parent)
struct btrfs_ioctl_search_key *sk = &args.key;
struct btrfs_ioctl_search_header *sh;
struct btrfs_root_ref *ref;
struct btrfs_dir_item *di;
unsigned long off = 0;
int name_len;
char *name;
u64 dir_id;
u64 subvol_id = 0;
int i;
int e;
@ -669,6 +671,52 @@ int list_subvols(int fd, int print_parent)
n = rb_next(n);
}
memset(&args, 0, sizeof(args));
/* search in the tree of tree roots */
sk->tree_id = BTRFS_ROOT_TREE_OBJECTID;
/* search dir item */
sk->max_type = BTRFS_DIR_ITEM_KEY;
sk->min_type = BTRFS_DIR_ITEM_KEY;
sk->max_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
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 that we have all the subvol-relative paths filled in,
* we have to string the subvols together so that we can get
* a path all the way back to the FS root
@ -677,7 +725,13 @@ int list_subvols(int fd, int print_parent)
while (n) {
struct root_info *entry;
entry = rb_entry(n, struct root_info, rb_node);
resolve_root(&root_lookup, entry, print_parent);
if (!get_default)
resolve_root(&root_lookup, entry, print_parent);
/* we only want the default subvolume */
else if (subvol_id == entry->root_id)
resolve_root(&root_lookup, entry, print_parent);
else if (subvol_id == 0)
break;
n = rb_prev(n);
}

View file

@ -94,6 +94,9 @@ static struct Command commands[] = {
"-l len defragment only up to len bytes\n"
"-t size minimal size of file to be considered for defragmenting\n"
},
{ do_get_default_subvol, 1, "subvolume get-default", "<path>\n"
"Get the default subvolume of a filesystem."
},
{ do_fssync, 1,
"filesystem sync", "<path>\n"
"Force a sync on the filesystem <path>.",

View file

@ -339,7 +339,7 @@ int do_subvol_list(int argc, char **argv)
fprintf(stderr, "ERROR: can't access '%s'\n", subvol);
return 12;
}
ret = list_subvols(fd, print_parent);
ret = list_subvols(fd, print_parent, 0);
if (ret)
return 19;
return 0;
@ -953,6 +953,35 @@ int do_change_label(int nargs, char **argv)
}
int do_get_default_subvol(int nargs, char **argv)
{
int fd;
int ret;
char *subvol;
subvol = argv[1];
ret = test_issubvolume(subvol);
if (ret < 0) {
fprintf(stderr, "ERROR: error accessing '%s'\n", subvol);
return 12;
}
if (!ret) {
fprintf(stderr, "ERROR: '%s' is not a subvolume\n", subvol);
return 13;
}
fd = open_file_or_dir(subvol);
if (fd < 0) {
fprintf(stderr, "ERROR: can't access '%s'\n", subvol);
return 12;
}
ret = list_subvols(fd, 0, 1);
if (ret)
return 19;
return 0;
}
int do_df_filesystem(int nargs, char **argv)
{
struct btrfs_ioctl_space_args *sargs;

View file

@ -32,7 +32,8 @@ int do_scan(int nargs, char **argv);
int do_resize(int nargs, char **argv);
int do_subvol_list(int nargs, char **argv);
int do_set_default_subvol(int nargs, char **argv);
int list_subvols(int fd, int print_parent);
int do_get_default_subvol(int nargs, char **argv);
int list_subvols(int fd, int print_parent, int get_default);
int do_df_filesystem(int nargs, char **argv);
int find_updated_files(int fd, u64 root_id, u64 oldest_gen);
int do_find_newer(int argc, char **argv);

View file

@ -15,6 +15,8 @@ btrfs \- control a btrfs filesystem
.PP
\fBbtrfs\fP \fBsubvolume set-default\fP\fI <id> <path>\fP
.PP
\fBbtrfs\fP \fBsubvolume get-default\fP\fI <path>\fP
.PP
\fBbtrfs\fP \fBfilesystem sync\fP\fI <path> \fP
.PP
\fBbtrfs\fP \fBfilesystem resize\fP\fI [+/\-]<size>[gkm]|max <filesystem>\fP
@ -120,6 +122,11 @@ Set the subvolume of the filesystem \fI<path>\fR which is mounted as
is returned by the \fBsubvolume list\fR command.
.TP
\fBsubvolume get-default\fR\fI <path>\fR
Get the default subvolume of the filesystem \fI<path>\fR. The output format
is similar to \fBsubvolume list\fR command.
.TP
\fBfilesystem defragment\fP -c[zlib|lzo] [-l \fIlen\fR] [-s \fIstart\fR] [-t \fIsize\fR] -[vf] <\fIfile\fR>|<\fIdir\fR> [<\fIfile\fR>|<\fIdir\fR>...]
Defragment file data and/or directory metadata. To defragment all files in a