summaryrefslogtreecommitdiff
path: root/src/partition
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2023-04-13 02:43:52 +0900
committerLennart Poettering <lennart@poettering.net>2023-04-13 09:07:00 +0200
commit37734dc677df0ac9ddc837d11aa3f5002a4d67a0 (patch)
tree38a21548fd40ef211891ff4a4a3ee7aee98f7e10 /src/partition
parent5d0fd36495772f86de9c3b902a97602eb49b8415 (diff)
downloadsystemd-37734dc677df0ac9ddc837d11aa3f5002a4d67a0.tar.gz
repart: always take BSD lock when whole block device is opened
Fixes #27236.
Diffstat (limited to 'src/partition')
-rw-r--r--src/partition/repart.c55
1 files changed, 40 insertions, 15 deletions
diff --git a/src/partition/repart.c b/src/partition/repart.c
index 725cad1f4a..23ad58f443 100644
--- a/src/partition/repart.c
+++ b/src/partition/repart.c
@@ -1998,6 +1998,28 @@ static int derive_uuid(sd_id128_t base, const char *token, sd_id128_t *ret) {
return 0;
}
+static int context_open_and_lock_backing_fd(Context *context, const char *node) {
+ _cleanup_close_ int fd = -EBADF;
+
+ assert(context);
+ assert(node);
+
+ if (context->backing_fd >= 0)
+ return 0;
+
+ fd = open(node, O_RDONLY|O_CLOEXEC);
+ if (fd < 0)
+ return log_error_errno(errno, "Failed to open device '%s': %m", node);
+
+ /* Tell udev not to interfere while we are processing the device */
+ if (flock(fd, arg_dry_run ? LOCK_SH : LOCK_EX) < 0)
+ return log_error_errno(errno, "Failed to lock device '%s': %m", node);
+
+ log_debug("Device %s opened and locked.", node);
+ context->backing_fd = TAKE_FD(fd);
+ return 1;
+}
+
static int context_load_partition_table(Context *context) {
_cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
_cleanup_(fdisk_unref_tablep) struct fdisk_table *t = NULL;
@@ -2026,11 +2048,9 @@ static int context_load_partition_table(Context *context) {
else {
uint32_t ssz;
- if (context->backing_fd < 0) {
- context->backing_fd = open(context->node, O_RDONLY|O_CLOEXEC);
- if (context->backing_fd < 0)
- return log_error_errno(errno, "Failed to open device '%s': %m", context->node);
- }
+ r = context_open_and_lock_backing_fd(context, context->node);
+ if (r < 0)
+ return r;
/* Auto-detect sector size if not specified. */
r = probe_sector_size_prefer_ioctl(context->backing_fd, &ssz);
@@ -2075,13 +2095,9 @@ static int context_load_partition_table(Context *context) {
if (context->backing_fd < 0) {
/* If we have no fd referencing the device yet, make a copy of the fd now, so that we have one */
- context->backing_fd = fd_reopen(fdisk_get_devfd(c), O_RDONLY|O_CLOEXEC);
- if (context->backing_fd < 0)
- return log_error_errno(context->backing_fd, "Failed to duplicate fdisk fd: %m");
-
- /* Tell udev not to interfere while we are processing the device */
- if (flock(context->backing_fd, arg_dry_run ? LOCK_SH : LOCK_EX) < 0)
- return log_error_errno(errno, "Failed to lock block device: %m");
+ r = context_open_and_lock_backing_fd(context, FORMAT_PROC_FD_PATH(fdisk_get_devfd(c)));
+ if (r < 0)
+ return r;
}
/* The offsets/sizes libfdisk returns to us will be in multiple of the sector size of the
@@ -6198,7 +6214,7 @@ static int acquire_root_devno(
char **ret,
int *ret_fd) {
- _cleanup_free_ char *found_path = NULL;
+ _cleanup_free_ char *found_path = NULL, *node = NULL;
dev_t devno, fd_devno = MODE_INVALID;
_cleanup_close_ int fd = -EBADF;
struct stat st;
@@ -6253,13 +6269,22 @@ static int acquire_root_devno(
if (r < 0)
log_debug_errno(r, "Failed to find whole disk block device for '%s', ignoring: %m", p);
- r = devname_from_devnum(S_IFBLK, devno, ret);
+ r = devname_from_devnum(S_IFBLK, devno, &node);
if (r < 0)
return log_debug_errno(r, "Failed to determine canonical path for '%s': %m", p);
/* Only if we still look at the same block device we can reuse the fd. Otherwise return an
* invalidated fd. */
- *ret_fd = fd_devno != MODE_INVALID && fd_devno == devno ? TAKE_FD(fd) : -1;
+ if (fd_devno != MODE_INVALID && fd_devno == devno) {
+ /* Tell udev not to interfere while we are processing the device */
+ if (flock(fd, arg_dry_run ? LOCK_SH : LOCK_EX) < 0)
+ return log_error_errno(errno, "Failed to lock device '%s': %m", node);
+
+ *ret_fd = TAKE_FD(fd);
+ } else
+ *ret_fd = -EBADF;
+
+ *ret = TAKE_PTR(node);
return 0;
}