diff options
author | Qu Wenruo <quwenruo@cn.fujitsu.com> | 2015-02-27 16:26:36 +0800 |
---|---|---|
committer | David Sterba <dsterba@suse.cz> | 2015-03-24 00:27:50 +0100 |
commit | cc6baf5e39fbfba24bff9aa1cdf9d0f83b4eb648 (patch) | |
tree | 448abe5ef0000d0849231f7d7f10165bcfa25702 /utils.c | |
parent | a3b048b306eabd40716607b248f8894ba6b22dab (diff) |
btrfs-progs: Allow parse_qgroupid() to resolve subvolume path into qgroupid
Now parse_qgroupid() can resolve subvolume path into qgroupid.
This is quite handy for handling level 0 qgroupid, and user don't need
to resolve rootid by hand now.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
[constify string in __is_subvol]
Signed-off-by: David Sterba <dsterba@suse.cz>
Diffstat (limited to 'utils.c')
-rw-r--r-- | utils.c | 48 |
1 files changed, 44 insertions, 4 deletions
@@ -1708,6 +1708,25 @@ scan_again: } /* + * Unsafe subvolume check. + * + * This only checks ino == BTRFS_FIRST_FREE_OBJECTID, even it is not in a + * btrfs mount point. + * Must use together with other reliable method like btrfs ioctl. + */ +static int __is_subvol(const char *path) +{ + struct stat st; + int ret; + + ret = lstat(path, &st); + if (ret < 0) + return ret; + + return st.st_ino == BTRFS_FIRST_FREE_OBJECTID; +} + +/* * A not-so-good version fls64. No fascinating optimization since * no one except parse_size use it */ @@ -1802,24 +1821,45 @@ u64 parse_qgroupid(const char *p) char *ptr_parse_end = NULL; u64 level; u64 id; + int fd; + int ret = 0; + + if (p[0] == '/') + goto path; + /* Numeric format like '0/257' is the primary case */ if (!s) { id = strtoull(p, &ptr_parse_end, 10); if (ptr_parse_end != ptr_src_end) - goto err; + goto path; return id; } level = strtoull(p, &ptr_parse_end, 10); if (ptr_parse_end != s) - goto err; + goto path; id = strtoull(s + 1, &ptr_parse_end, 10); if (ptr_parse_end != ptr_src_end) - goto err; + goto path; return (level << BTRFS_QGROUP_LEVEL_SHIFT) | id; + +path: + /* Path format like subv at 'my_subvol' is the fallback case */ + ret = __is_subvol(p); + if (ret < 0 || !ret) + goto err; + fd = open(p, O_RDONLY); + if (fd < 0) + goto err; + ret = lookup_ino_rootid(fd, &id); + close(fd); + if (ret < 0) + goto err; + return id; + err: - fprintf(stderr, "ERROR: invalid qgroupid %s\n", p); + fprintf(stderr, "ERROR: invalid qgroupid or subvolume path: %s\n", p); exit(-1); } |