summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--btrfs-list.c4
-rw-r--r--cmds-subvolume.c54
-rw-r--r--utils.c52
-rw-r--r--utils.h5
4 files changed, 109 insertions, 6 deletions
diff --git a/btrfs-list.c b/btrfs-list.c
index 8eec05ea..92a537f4 100644
--- a/btrfs-list.c
+++ b/btrfs-list.c
@@ -1582,7 +1582,9 @@ int btrfs_get_subvol(int fd, struct root_info *the_ri)
rbn = rb_next(rbn);
continue;
}
- if (!comp_entry_with_rootid(the_ri, ri, 0)) {
+
+ if (!comp_entry_with_rootid(the_ri, ri, 0) ||
+ !uuid_compare(the_ri->uuid, ri->uuid)) {
memcpy(the_ri, ri, offsetof(struct root_info, path));
the_ri->path = strdup_or_null(ri->path);
the_ri->name = strdup_or_null(ri->name);
diff --git a/cmds-subvolume.c b/cmds-subvolume.c
index de6204ea..666f6e05 100644
--- a/cmds-subvolume.c
+++ b/cmds-subvolume.c
@@ -891,8 +891,13 @@ static int cmd_subvol_find_new(int argc, char **argv)
}
static const char * const cmd_subvol_show_usage[] = {
- "btrfs subvolume show <subvol-path>",
- "Show more information of the subvolume",
+ "btrfs subvolume show [options] <subvol-path>|<mnt>",
+ "Show more information about the subvolume",
+ "-r|--rootid rootid of the subvolume",
+ "-u|--uuid uuid of the subvolume",
+ "",
+ "If no option is specified, <subvol-path> will be shown, otherwise",
+ "the rootid or uuid are resolved relative to the <mnt> path.",
NULL
};
@@ -907,12 +912,46 @@ static int cmd_subvol_show(int argc, char **argv)
int fd = -1;
int ret = 1;
DIR *dirstream1 = NULL;
+ int by_rootid = 0;
+ int by_uuid = 0;
+ u64 rootid_arg;
+ u8 uuid_arg[BTRFS_UUID_SIZE];
+
+ while (1) {
+ int c;
+ static const struct option long_options[] = {
+ { "rootid", required_argument, NULL, 'r'},
+ { "uuid", required_argument, NULL, 'u'},
+ { NULL, 0, NULL, 0 }
+ };
- clean_args_no_options(argc, argv, cmd_subvol_show_usage);
+ c = getopt_long(argc, argv, "r:u:", long_options, NULL);
+ if (c < 0)
+ break;
+
+ switch (c) {
+ case 'r':
+ rootid_arg = arg_strtou64(optarg);
+ by_rootid = 1;
+ break;
+ case 'u':
+ uuid_parse(optarg, uuid_arg);
+ by_uuid = 1;
+ break;
+ default:
+ usage(cmd_subvol_show_usage);
+ }
+ }
if (check_argc_exact(argc - optind, 1))
usage(cmd_subvol_show_usage);
+ if (by_rootid && by_uuid) {
+ error(
+ "options --rootid and --uuid cannot be used at the same time");
+ usage(cmd_subvol_show_usage);
+ }
+
memset(&get_ri, 0, sizeof(get_ri));
fullpath = realpath(argv[optind], NULL);
if (!fullpath) {
@@ -921,7 +960,14 @@ static int cmd_subvol_show(int argc, char **argv)
goto out;
}
- ret = get_subvol_info(fullpath, &get_ri);
+ if (by_rootid) {
+ ret = get_subvol_info_by_rootid(fullpath, &get_ri, rootid_arg);
+ } else if (by_uuid) {
+ ret = get_subvol_info_by_uuid(fullpath, &get_ri, uuid_arg);
+ } else {
+ ret = get_subvol_info(fullpath, &get_ri);
+ }
+
if (ret) {
if (ret < 0) {
error("Failed to get subvol info %s: %s",
diff --git a/utils.c b/utils.c
index 243ee1e5..bb049133 100644
--- a/utils.c
+++ b/utils.c
@@ -2433,6 +2433,58 @@ out:
return ret;
}
+int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri, u64 r_id)
+{
+ int fd;
+ int ret;
+ DIR *dirstream = NULL;
+
+ fd = btrfs_open_dir(mnt, &dirstream, 1);
+ if (fd < 0)
+ return -EINVAL;
+
+ memset(get_ri, 0, sizeof(*get_ri));
+ get_ri->root_id = r_id;
+
+ if (r_id == BTRFS_FS_TREE_OBJECTID)
+ ret = btrfs_get_toplevel_subvol(fd, get_ri);
+ else
+ ret = btrfs_get_subvol(fd, get_ri);
+
+ if (ret)
+ error("can't find rootid '%llu' on '%s': %d", r_id, mnt, ret);
+
+ close_file_or_dir(fd, dirstream);
+
+ return ret;
+}
+
+int get_subvol_info_by_uuid(const char *mnt, struct root_info *get_ri, u8 *uuid_arg)
+{
+ int fd;
+ int ret;
+ DIR *dirstream = NULL;
+
+ fd = btrfs_open_dir(mnt, &dirstream, 1);
+ if (fd < 0)
+ return -EINVAL;
+
+ memset(get_ri, 0, sizeof(*get_ri));
+ uuid_copy(get_ri->uuid, uuid_arg);
+
+ ret = btrfs_get_subvol(fd, get_ri);
+ if (ret) {
+ char uuid_parsed[BTRFS_UUID_UNPARSED_SIZE];
+ uuid_unparse(uuid_arg, uuid_parsed);
+ error("can't find uuid '%s' on '%s': %d",
+ uuid_parsed, mnt, ret);
+ }
+
+ close_file_or_dir(fd, dirstream);
+
+ return ret;
+}
+
/* Set the seed manually */
void init_rand_seed(u64 seed)
{
diff --git a/utils.h b/utils.h
index bf8eb1ed..091f8fab 100644
--- a/utils.h
+++ b/utils.h
@@ -134,7 +134,10 @@ int test_isdir(const char *path);
const char *subvol_strip_mountpoint(const char *mnt, const char *full_path);
int get_subvol_info(const char *fullpath, struct root_info *get_ri);
-
+int get_subvol_info_by_rootid(const char *mnt, struct root_info *get_ri,
+ u64 rootid_arg);
+int get_subvol_info_by_uuid(const char *mnt, struct root_info *get_ri,
+ u8 *uuid_arg);
int find_next_key(struct btrfs_path *path, struct btrfs_key *key);
const char* btrfs_group_type_str(u64 flag);
const char* btrfs_group_profile_str(u64 flag);