From cd6a82d835fe80a1e22eb040ee25557604f7767e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Apr 2023 10:14:43 +0200 Subject: [PATCH] dissect-image: issue BLKFLSBUF before probing an fs at block device offset != 0 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. (cherry picked from commit 4d49f44f0fcdaa51b7311fb9420018995945f3f3) (cherry picked from commit 2be23f69eef7d9b12e4ddeffcf676ba54a9a6ad7) --- src/shared/dissect-image.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 74e89e0737..9bf128cc03 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -118,6 +118,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,