]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect-image: issue BLKFLSBUF before probing an fs at block device offset != 0
authorLennart Poettering <lennart@poettering.net>
Thu, 20 Apr 2023 08:14:43 +0000 (10:14 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 20 Apr 2023 11:38:32 +0000 (13:38 +0200)
See added code comment for a longer explanation. TLDR: Linux maintains
distinct block device caches for partition and "whole" block devices,
and a simply BLKFLSBUF should make the worst confusions this causes go
away.

src/shared/dissect-image.c

index 20ef2a5ee40ffcafa9c3a37e94e29745a971cf82..45bed868cbc60ffbd61cba53fa336f17833d9737 100644 (file)
@@ -252,6 +252,21 @@ int probe_filesystem_full(
         if (!b)
                 return -ENOMEM;
 
+        /* The Linux kernel maintains separate block device caches for main ("whole") and partition block
+         * devices, which means making a change to one might not be reflected immediately when reading via
+         * the other. That's massively confusing when mixing accesses to such devices. Let's address this in
+         * a limited way: when probing a file system that is not at the beginning of the block device we
+         * apparently probe a partition via the main block device, and in that case let's first flush the
+         * main block device cache, so that we get the data that the per-partition block device last
+         * sync'ed on.
+         *
+         * This only works under the assumption that any tools that write to the partition block devices
+         * issue an syncfs()/fsync() on the device after making changes. Typically file system formatting
+         * tools that write a superblock onto a partition block device do that, however. */
+        if (offset != 0)
+                if (ioctl(fd, BLKFLSBUF, 0) < 0)
+                        log_debug_errno(errno, "Failed to flush block device cache, ignoring: %m");
+
         errno = 0;
         r = blkid_probe_set_device(
                         b,