From: Daan De Meyer Date: Wed, 11 Jan 2023 15:21:01 +0000 (+0100) Subject: dissect-image: Notify btrfs when we're done using a loop device X-Git-Tag: v253-rc1~119 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5228c58ebe8fb77d579f333263986a0798299ab7;p=thirdparty%2Fsystemd.git dissect-image: Notify btrfs when we're done using a loop device 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. --- diff --git a/src/shared/blockdev-util.c b/src/shared/blockdev-util.c index 85ae8ff8078..7a4d21d02e2 100644 --- a/src/shared/blockdev-util.c +++ b/src/shared/blockdev-util.c @@ -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); diff --git a/src/shared/btrfs-util.c b/src/shared/btrfs-util.c index 0ef3c608bbe..c6840575415 100644 --- a/src/shared/btrfs-util.c +++ b/src/shared/btrfs-util.c @@ -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)); +} diff --git a/src/shared/btrfs-util.h b/src/shared/btrfs-util.h index 5f568f23528..080d5a607d8 100644 --- a/src/shared/btrfs-util.h +++ b/src/shared/btrfs-util.h @@ -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); diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 3eefe3efa4e..45a9e9413cb 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -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)