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>
This commit is contained in:
parent
a3b048b306
commit
cc6baf5e39
48
utils.c
48
utils.c
|
@ -1707,6 +1707,25 @@ scan_again:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* A not-so-good version fls64. No fascinating optimization since
|
||||||
* no one except parse_size use it
|
* no one except parse_size use it
|
||||||
|
@ -1802,24 +1821,45 @@ u64 parse_qgroupid(const char *p)
|
||||||
char *ptr_parse_end = NULL;
|
char *ptr_parse_end = NULL;
|
||||||
u64 level;
|
u64 level;
|
||||||
u64 id;
|
u64 id;
|
||||||
|
int fd;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (p[0] == '/')
|
||||||
|
goto path;
|
||||||
|
|
||||||
|
/* Numeric format like '0/257' is the primary case */
|
||||||
if (!s) {
|
if (!s) {
|
||||||
id = strtoull(p, &ptr_parse_end, 10);
|
id = strtoull(p, &ptr_parse_end, 10);
|
||||||
if (ptr_parse_end != ptr_src_end)
|
if (ptr_parse_end != ptr_src_end)
|
||||||
goto err;
|
goto path;
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
level = strtoull(p, &ptr_parse_end, 10);
|
level = strtoull(p, &ptr_parse_end, 10);
|
||||||
if (ptr_parse_end != s)
|
if (ptr_parse_end != s)
|
||||||
goto err;
|
goto path;
|
||||||
|
|
||||||
id = strtoull(s + 1, &ptr_parse_end, 10);
|
id = strtoull(s + 1, &ptr_parse_end, 10);
|
||||||
if (ptr_parse_end != ptr_src_end)
|
if (ptr_parse_end != ptr_src_end)
|
||||||
goto err;
|
goto path;
|
||||||
|
|
||||||
return (level << BTRFS_QGROUP_LEVEL_SHIFT) | id;
|
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:
|
err:
|
||||||
fprintf(stderr, "ERROR: invalid qgroupid %s\n", p);
|
fprintf(stderr, "ERROR: invalid qgroupid or subvolume path: %s\n", p);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue