summaryrefslogtreecommitdiff
path: root/src/gpt-auto-generator
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2022-04-07 16:09:45 +0200
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-04-10 22:52:29 +0900
commit41bc484906e973f6c91f8398a3ba309b7ee16f5a (patch)
tree57fad1132c0a90f01e527ac948f898ddea9863a4 /src/gpt-auto-generator
parent345418a9e67a5f5f86901b2e1f86f52526ca7ba1 (diff)
downloadsystemd-41bc484906e973f6c91f8398a3ba309b7ee16f5a.tar.gz
tree-wide: take BSD lock on loopback devices we dissect/mount/operate on
So here's something we should always keep in mind: systemd-udevd actually does *two* things with BSD file locks on block devices: 1. While it probes a device it takes a LOCK_SH lock. Thus everyone else taking a LOCK_EX lock will temporarily block udev from probing devices, which is good when making changes to it. 2. Whenever a device is closed after write (detected via inotify), udevd will issue BLKRRPART (requesting the kernel to reread the partition table). It does this while holding a LOCK_EX lock on the block device. Thus anyone else taking LOCK_SH or LOCK_EX will temporarily block udevd from issuing that ioctl. And that's quite relevant, since the kernel will temporarily flush out all partitions while re-reading the partition table and then create them anew. Thus it is smart to take LOCK_SH when dissecting a block device to ensure that no BLKRRPART is issued in the background, until we mounted the devices.
Diffstat (limited to 'src/gpt-auto-generator')
-rw-r--r--src/gpt-auto-generator/gpt-auto-generator.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c
index 08bb9ac724..4731687b7f 100644
--- a/src/gpt-auto-generator/gpt-auto-generator.c
+++ b/src/gpt-auto-generator/gpt-auto-generator.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <stdlib.h>
+#include <sys/file.h>
#include <unistd.h>
#include "sd-device.h"
@@ -696,6 +697,12 @@ static int enumerate_partitions(dev_t devnum) {
if (r <= 0)
return r;
+ /* Let's take a LOCK_SH lock on the block device, in case udevd is already running. If we don't take
+ * the lock, udevd might end up issuing BLKRRPART in the middle, and we don't want that, since that
+ * might remove all partitions while we are operating on them. */
+ if (flock(fd, LOCK_SH) < 0)
+ return log_error_errno(errno, "Failed to lock root block device: %m");
+
r = dissect_image(
fd,
NULL, NULL,