From 6cba41ab0dbe5eb817f37bd43caff4754d801d3b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 18 May 2020 18:29:57 +0200 Subject: [PATCH 1/7] blockdev: propagate one more unexpected error --- src/basic/blockdev-util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/basic/blockdev-util.c b/src/basic/blockdev-util.c index 7d94c55a6d..54431f5d0f 100644 --- a/src/basic/blockdev-util.c +++ b/src/basic/blockdev-util.c @@ -29,6 +29,8 @@ int block_get_whole_disk(dev_t d, dev_t *ret) { *ret = d; return 0; } + if (errno != ENOENT) + return -errno; /* If it is a partition find the originating device */ xsprintf_sys_block_path(p, "/partition", d); From 700e0d3d87705a6ba01793d7130bbb8e6edbee16 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 18 May 2020 18:30:18 +0200 Subject: [PATCH 2/7] makefs: log about OOM condition --- src/partition/makefs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/partition/makefs.c b/src/partition/makefs.c index d73d67c4e8..df08a5fea6 100644 --- a/src/partition/makefs.c +++ b/src/partition/makefs.c @@ -54,11 +54,11 @@ static int run(int argc, char *argv[]) { /* type and device must be copied because makefs calls safe_fork, which clears argv[] */ type = strdup(argv[1]); if (!type) - return -ENOMEM; + return log_oom(); device = strdup(argv[2]); if (!device) - return -ENOMEM; + return log_oom(); if (stat(device, &st) < 0) return log_error_errno(errno, "Failed to stat \"%s\": %m", device); From 58dfbfbdd6138de49c6f59a763c4cfc7acb8c9a9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 18 May 2020 18:30:49 +0200 Subject: [PATCH 3/7] dissect: use log_debug_errno() where appropriate --- src/shared/dissect-image.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 23ad6b06cf..8decac94b2 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -75,10 +75,9 @@ int probe_filesystem(const char *node, char **ret_fstype) { log_debug("No type detected on partition %s", node); goto not_found; } - if (r == -2) { - log_debug("Results ambiguous for partition %s", node); - return -EUCLEAN; - } + if (r == -2) + return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN), + "Results ambiguous for partition %s", node); if (r != 0) return errno_or_else(EIO); From ac83e5aeca7ca4eff3de6ef6d9a55b71b6eb10b1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 18 May 2020 18:31:04 +0200 Subject: [PATCH 4/7] blockdev: add helper for locking whole block device --- src/basic/blockdev-util.c | 27 +++++++++++++++++++++++++++ src/basic/blockdev-util.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/src/basic/blockdev-util.c b/src/basic/blockdev-util.c index 54431f5d0f..5f8212685b 100644 --- a/src/basic/blockdev-util.c +++ b/src/basic/blockdev-util.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ +#include #include #include "alloc-util.h" @@ -187,3 +188,29 @@ int get_block_device_harder(const char *path, dev_t *ret) { return 1; } + +int lock_whole_block_device(dev_t devt, int operation) { + _cleanup_free_ char *whole_node = NULL; + _cleanup_close_ int lock_fd = -1; + dev_t whole_devt; + int r; + + /* Let's get a BSD file lock on the whole block device, as per: https://systemd.io/BLOCK_DEVICE_LOCKING */ + + r = block_get_whole_disk(devt, &whole_devt); + if (r < 0) + return r; + + r = device_path_make_major_minor(S_IFBLK, whole_devt, &whole_node); + if (r < 0) + return r; + + lock_fd = open(whole_node, O_RDONLY|O_CLOEXEC|O_NONBLOCK); + if (lock_fd < 0) + return -errno; + + if (flock(lock_fd, operation) < 0) + return -errno; + + return TAKE_FD(lock_fd); +} diff --git a/src/basic/blockdev-util.h b/src/basic/blockdev-util.h index 6d8a796568..1e7588f71c 100644 --- a/src/basic/blockdev-util.h +++ b/src/basic/blockdev-util.h @@ -18,3 +18,5 @@ int block_get_originating(dev_t d, dev_t *ret); int get_block_device(const char *path, dev_t *dev); int get_block_device_harder(const char *path, dev_t *dev); + +int lock_whole_block_device(dev_t devt, int operation); From 0181ad85b37d37785787b4eb8aa8c72d2e4c76b4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 18 May 2020 18:31:45 +0200 Subject: [PATCH 5/7] makefs: lock device while we operate Let's implement our own specs, i.e. https://systemd.io/BLOCK_DEVICE_LOCKING/ This should address issues like this: #13162 --- src/partition/makefs.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/partition/makefs.c b/src/partition/makefs.c index df08a5fea6..128aa41044 100644 --- a/src/partition/makefs.c +++ b/src/partition/makefs.c @@ -7,7 +7,9 @@ #include #include "alloc-util.h" +#include "blockdev-util.h" #include "dissect-image.h" +#include "fd-util.h" #include "main-func.h" #include "process-util.h" #include "signal-util.h" @@ -42,6 +44,7 @@ static int makefs(const char *type, const char *device) { static int run(int argc, char *argv[]) { _cleanup_free_ char *device = NULL, *type = NULL, *detected = NULL; + _cleanup_close_ int lock_fd = -1; struct stat st; int r; @@ -63,7 +66,13 @@ static int run(int argc, char *argv[]) { if (stat(device, &st) < 0) return log_error_errno(errno, "Failed to stat \"%s\": %m", device); - if (!S_ISBLK(st.st_mode)) + if (S_ISBLK(st.st_mode)) { + /* Lock the device so that udev doesn't interfere with our work */ + + lock_fd = lock_whole_block_device(st.st_rdev, LOCK_EX); + if (lock_fd < 0) + return log_error_errno(lock_fd, "Failed to lock whole block device of \"%s\": %m", device); + } else log_info("%s is not a block device.", device); r = probe_filesystem(device, &detected); From a5a8fe2e8dbb9bc1981064d273b626d4aa187152 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 18 May 2020 18:32:17 +0200 Subject: [PATCH 6/7] makefs: normalize logging a bit --- src/partition/makefs.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/partition/makefs.c b/src/partition/makefs.c index 128aa41044..97f50c9033 100644 --- a/src/partition/makefs.c +++ b/src/partition/makefs.c @@ -76,15 +76,12 @@ static int run(int argc, char *argv[]) { log_info("%s is not a block device.", device); r = probe_filesystem(device, &detected); + if (r == -EUCLEAN) + return log_error_errno(r, "Ambiguous results of probing for file system on \"%s\", refusing to proceed.", device); if (r < 0) - return log_warning_errno(r, - r == -EUCLEAN ? - "Cannot reliably determine probe \"%s\", refusing to proceed." : - "Failed to probe \"%s\": %m", - device); - + return log_error_errno(r, "Failed to probe \"%s\": %m", device); if (detected) { - log_info("%s is not empty (type %s), exiting", device, detected); + log_info("'%s' is not empty (contains file system of type %s), exiting.", device, detected); return 0; } From db2c56b0dd28f271dd3fe53691b21484f72586e4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 18 May 2020 18:37:02 +0200 Subject: [PATCH 7/7] cryptsetup-generator: use systemd-makefs for implementation of "swap" and "tmp" options This way we can take benefit of the correct block device locking we just added. I was thinking whether to instead pull in a regular systemd-makefs@.service instance, but I couldn't come up with a reason to, and thus opted for just doing the minimal patch and just replacing the simply mkfs calls. Fixes: #10179 Replaces: #13162 --- src/cryptsetup/cryptsetup-generator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 20c752d88d..5724f88d0a 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -367,12 +367,12 @@ static int create_disk( if (tmp) fprintf(f, - "ExecStartPost=/sbin/mke2fs '/dev/mapper/%s'\n", + "ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs ext2 '/dev/mapper/%s'\n", name_escaped); if (swap) fprintf(f, - "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n", + "ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs swap '/dev/mapper/%s'\n", name_escaped); if (keydev)