diff options
author | Lennart Poettering <lennart@poettering.net> | 2022-04-07 16:09:45 +0200 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-04-10 22:52:29 +0900 |
commit | 41bc484906e973f6c91f8398a3ba309b7ee16f5a (patch) | |
tree | 57fad1132c0a90f01e527ac948f898ddea9863a4 /src/gpt-auto-generator/gpt-auto-generator.c | |
parent | 345418a9e67a5f5f86901b2e1f86f52526ca7ba1 (diff) | |
download | systemd-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/gpt-auto-generator.c')
-rw-r--r-- | src/gpt-auto-generator/gpt-auto-generator.c | 7 |
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, |