mirror of
https://github.com/systemd/systemd.git
synced 2025-01-11 09:18:07 +03:00
btrfs: always remove the per-subvol qgroup when removing a subvol
btrfs doesn't do that automatically, hence let's do that explicitly each time.
This commit is contained in:
parent
19833db683
commit
3f952f92b9
@ -799,6 +799,45 @@ int btrfs_resize_loopback(const char *p, uint64_t new_size, bool grow_only) {
|
||||
return btrfs_resize_loopback_fd(fd, new_size, grow_only);
|
||||
}
|
||||
|
||||
static int make_qgroup_id(uint64_t level, uint64_t id, uint64_t *ret) {
|
||||
assert(ret);
|
||||
|
||||
if (level >= (UINT64_C(1) << (64 - BTRFS_QGROUP_LEVEL_SHIFT)))
|
||||
return -EINVAL;
|
||||
|
||||
if (id >= (UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT))
|
||||
return -EINVAL;
|
||||
|
||||
*ret = (level << BTRFS_QGROUP_LEVEL_SHIFT) | id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qgroup_create_or_destroy(int fd, bool b, uint64_t level, uint64_t id) {
|
||||
|
||||
struct btrfs_ioctl_qgroup_create_args args = {
|
||||
.create = b,
|
||||
};
|
||||
|
||||
int r;
|
||||
|
||||
r = make_qgroup_id(level, id, (uint64_t*) &args.qgroupid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btrfs_qgroup_create(int fd, uint64_t level, uint64_t id) {
|
||||
return qgroup_create_or_destroy(fd, true, level, id);
|
||||
}
|
||||
|
||||
int btrfs_qgroup_destroy(int fd, uint64_t level, uint64_t id) {
|
||||
return qgroup_create_or_destroy(fd, false, level, id);
|
||||
}
|
||||
|
||||
static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol_id, bool recursive) {
|
||||
struct btrfs_ioctl_search_args args = {
|
||||
.key.tree_id = BTRFS_ROOT_TREE_OBJECTID,
|
||||
@ -828,16 +867,6 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
return -EINVAL;
|
||||
|
||||
/* First, try to remove the subvolume. If it happens to be
|
||||
* already empty, this will just work. */
|
||||
strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1);
|
||||
if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) >= 0)
|
||||
return 0;
|
||||
if (!recursive || errno != ENOTEMPTY)
|
||||
return -errno;
|
||||
|
||||
/* OK, the subvolume is not empty, let's look for child
|
||||
* subvolumes, and remove them, first */
|
||||
subvol_fd = openat(fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
|
||||
if (subvol_fd < 0)
|
||||
return -errno;
|
||||
@ -848,6 +877,19 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
|
||||
return r;
|
||||
}
|
||||
|
||||
/* First, try to remove the subvolume. If it happens to be
|
||||
* already empty, this will just work. */
|
||||
strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1);
|
||||
if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) >= 0) {
|
||||
(void) btrfs_qgroup_destroy(fd, 0, subvol_id);
|
||||
return 0;
|
||||
}
|
||||
if (!recursive || errno != ENOTEMPTY)
|
||||
return -errno;
|
||||
|
||||
/* OK, the subvolume is not empty, let's look for child
|
||||
* subvolumes, and remove them, first */
|
||||
|
||||
args.key.min_offset = args.key.max_offset = subvol_id;
|
||||
|
||||
while (btrfs_ioctl_search_args_compare(&args) <= 0) {
|
||||
@ -925,6 +967,7 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
|
||||
if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) < 0)
|
||||
return -errno;
|
||||
|
||||
(void) btrfs_qgroup_destroy(fd, 0, subvol_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -86,3 +86,6 @@ int btrfs_resize_loopback(const char *path, uint64_t size, bool grow_only);
|
||||
|
||||
int btrfs_subvol_remove(const char *path, bool recursive);
|
||||
int btrfs_subvol_remove_fd(int fd, const char *subvolume, bool recursive);
|
||||
|
||||
int btrfs_qgroup_create(int fd, uint64_t level, uint64_t id);
|
||||
int btrfs_qgroup_destroy(int fd, uint64_t level, uint64_t id);
|
||||
|
@ -248,6 +248,10 @@ static inline int getrandom(void *buffer, size_t count, unsigned flags) {
|
||||
#define BTRFS_SEARCH_ARGS_BUFSIZE (4096 - sizeof(struct btrfs_ioctl_search_key))
|
||||
#endif
|
||||
|
||||
#ifndef BTRFS_QGROUP_LEVEL_SHIFT
|
||||
#define BTRFS_QGROUP_LEVEL_SHIFT 48
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LINUX_BTRFS_H
|
||||
struct btrfs_ioctl_vol_args {
|
||||
int64_t fd;
|
||||
|
Loading…
Reference in New Issue
Block a user