From: Qu Wenruo Date: Fri, 27 Feb 2015 08:26:36 +0000 (+0800) Subject: btrfs-progs: Allow parse_qgroupid() to resolve subvolume path into qgroupid X-Git-Tag: upstream/4.16.1~2336 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cc6baf5e39fbfba24bff9aa1cdf9d0f83b4eb648;p=platform%2Fupstream%2Fbtrfs-progs.git 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 [constify string in __is_subvol] Signed-off-by: David Sterba --- diff --git a/utils.c b/utils.c index ca8efca..7b977ee 100644 --- a/utils.c +++ b/utils.c @@ -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); }