]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect-image: Notify btrfs when we're done using a loop device
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 11 Jan 2023 15:21:01 +0000 (16:21 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 12 Jan 2023 15:36:09 +0000 (16:36 +0100)
Let's explicitly let btrfs know when we're done using a loop device.
Otherwise, btrfs will keep the device UUID cached which will result
in mount() failures if we ever generate a device or filesystem with
the same UUID again.

src/shared/blockdev-util.c
src/shared/btrfs-util.c
src/shared/btrfs-util.h
src/shared/dissect-image.c

index 85ae8ff8078bc424e041ed3cbf0318dbf45d998d..7a4d21d02e2f2bc3c34626735eb96102361eb52c 100644 (file)
@@ -707,6 +707,10 @@ int block_device_remove_all_partitions(sd_device *dev, int fd) {
                 if (r < 0)
                         return r;
 
+                r = btrfs_forget_device(devname);
+                if (r < 0 && r != -ENOENT)
+                        log_debug_errno(r, "Failed to forget btrfs device %s, ignoring: %m", devname);
+
                 r = block_device_remove_partition(fd, devname, nr);
                 if (r == -ENODEV) {
                         log_debug("Kernel removed partition %s before us, ignoring", devname);
index 0ef3c608bbeebbac107d521b24a59e23840e3f1b..c68405754152805e825b2b40d64434beb60d6bf0 100644 (file)
@@ -1986,3 +1986,21 @@ int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret) {
 
         return -ENXIO;
 }
+
+int btrfs_forget_device(const char *path) {
+        _cleanup_close_ int control_fd = -EBADF;
+        struct btrfs_ioctl_vol_args args = {};
+
+        assert(path);
+
+        if (strlen(path) > BTRFS_PATH_NAME_MAX)
+                return -E2BIG;
+
+        strcpy(args.name, path);
+
+        control_fd = open("/dev/btrfs-control", O_RDWR|O_CLOEXEC);
+        if (control_fd < 0)
+                return -errno;
+
+        return RET_NERRNO(ioctl(control_fd, BTRFS_IOC_FORGET_DEV, &args));
+}
index 5f568f23528d3f84957b205ef867eceaa8017cc9..080d5a607d8d5c5e64a8deaa2f9aee85f4aee65a 100644 (file)
@@ -136,3 +136,5 @@ static inline bool btrfs_might_be_subvol(const struct stat *st) {
 
         return S_ISDIR(st->st_mode) && st->st_ino == 256;
 }
+
+int btrfs_forget_device(const char *path);
index 3eefe3efa4e39b2eefefa0422538ca3898220cf0..45a9e9413cbbad208979407b6f7745b94880c433 100644 (file)
@@ -25,6 +25,7 @@
 #include "ask-password-api.h"
 #include "blkid-util.h"
 #include "blockdev-util.h"
+#include "btrfs-util.h"
 #include "chase-symlinks.h"
 #include "conf-files.h"
 #include "constants.h"
@@ -1739,6 +1740,16 @@ static DecryptedImage* decrypted_image_free(DecryptedImage *d) {
                 DecryptedPartition *p = d->decrypted + i;
 
                 if (p->device && p->name && !p->relinquished) {
+                        _cleanup_free_ char *node = NULL;
+
+                        node = path_join("/dev/mapper", p->name);
+                        if (node) {
+                                r = btrfs_forget_device(node);
+                                if (r < 0 && r != -ENOENT)
+                                        log_debug_errno(r, "Failed to forget btrfs device %s, ignoring: %m", node);
+                        } else
+                                log_oom_debug();
+
                         /* Let's deactivate lazily, as the dm volume may be already/still used by other processes. */
                         r = sym_crypt_deactivate_by_name(p->device, p->name, CRYPT_DEACTIVATE_DEFERRED);
                         if (r < 0)