]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
btrfs: always remove the per-subvol qgroup when removing a subvol
authorLennart Poettering <lennart@poettering.net>
Thu, 15 Oct 2015 16:37:03 +0000 (18:37 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 15 Oct 2015 16:37:03 +0000 (18:37 +0200)
btrfs doesn't do that automatically, hence let's do that explicitly each
time.

src/basic/btrfs-util.c
src/basic/btrfs-util.h
src/basic/missing.h

index 074deeccdaa2154138b808dba138fbec574d51dd..ec7e00986b48d1eec85c219dd7003f8973fb6be2 100644 (file)
@@ -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;
 }
 
index 8632c3638c227f0dad1eead3ffadcfdc673aba47..ad7c7009abbf3552706a593f71e8d32e80658d53 100644 (file)
@@ -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);
index 59e835a4664b84b61392710ac2a1308d512cc335..8d11b80d95d7ea1dd17964a7bb93663887febbe9 100644 (file)
@@ -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;