From fc10b158ef147c30f4789313e3246b628dd7f865 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Mon, 5 Jun 2023 13:56:49 +0200 Subject: [PATCH] repart: Add --offline argument This allows the user to explicit configure whether loop devices should be used to build the image or not. --- man/systemd-repart.xml | 12 ++++++++++++ src/partition/repart.c | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/man/systemd-repart.xml b/man/systemd-repart.xml index 66c86e701e3..4892236f6a5 100644 --- a/man/systemd-repart.xml +++ b/man/systemd-repart.xml @@ -428,6 +428,18 @@ x86-64. + + BOOL + + Instructs systemd-repart to build the image offline. Takes a + boolean or auto. Defaults to auto. If enabled, the image is + built without using loop devices. This is useful to build images unprivileged or when loop devices + are not available. If disabled, the image is always built using loop devices. If + auto, systemd-repart will build the image online if possible + and fall back to building the image offline if loop devices are not available or cannot be accessed + due to missing permissions. + + diff --git a/src/partition/repart.c b/src/partition/repart.c index 89f7211bfd5..78bd06a537f 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -152,6 +152,7 @@ static size_t arg_n_defer_partitions = 0; static uint64_t arg_sector_size = 0; static ImagePolicy *arg_image_policy = NULL; static Architecture arg_architecture = _ARCHITECTURE_INVALID; +static int arg_offline = -1; STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep); @@ -3253,13 +3254,17 @@ static int partition_target_prepare( /* Loopback block devices are not only useful to turn regular files into block devices, but * also to cut out sections of block devices into new block devices. */ - r = loop_device_make(whole_fd, O_RDWR, p->offset, size, 0, 0, LOCK_EX, &d); - if (r < 0 && r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) - return log_error_errno(r, "Failed to make loopback device of future partition %" PRIu64 ": %m", p->partno); - if (r >= 0) { - t->loop = TAKE_PTR(d); - *ret = TAKE_PTR(t); - return 0; + if (arg_offline <= 0) { + r = loop_device_make(whole_fd, O_RDWR, p->offset, size, 0, 0, LOCK_EX, &d); + if (r < 0 && (arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)))) + return log_error_errno(r, "Failed to make loopback device of future partition %" PRIu64 ": %m", p->partno); + if (r >= 0) { + t->loop = TAKE_PTR(d); + *ret = TAKE_PTR(t); + return 0; + } + + log_debug_errno(r, "No access to loop devices, falling back to a regular file"); } /* If we can't allocate a loop device, let's write to a regular file that we copy into the final @@ -3267,8 +3272,6 @@ static int partition_target_prepare( * reflinking support, we can take advantage of this and just reflink the result into the image. */ - log_debug_errno(r, "No access to loop devices, falling back to a regular file"); - r = prepare_temporary_file(t, size); if (r < 0) return r; @@ -5852,6 +5855,7 @@ static int help(void) { " but don't populate them yet\n" " --sector-size=SIZE Set the logical sector size for the image\n" " --architecture=ARCH Set the generic architecture for the image\n" + " --offline=BOOL Whether to build the image offline\n" "\nSee the %s for details.\n", program_invocation_short_name, ansi_highlight(), @@ -5894,6 +5898,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_SECTOR_SIZE, ARG_SKIP_PARTITIONS, ARG_ARCHITECTURE, + ARG_OFFLINE, }; static const struct option options[] = { @@ -5927,6 +5932,7 @@ static int parse_argv(int argc, char *argv[]) { { "defer-partitions", required_argument, NULL, ARG_DEFER_PARTITIONS }, { "sector-size", required_argument, NULL, ARG_SECTOR_SIZE }, { "architecture", required_argument, NULL, ARG_ARCHITECTURE }, + { "offline", required_argument, NULL, ARG_OFFLINE }, {} }; @@ -6235,6 +6241,19 @@ static int parse_argv(int argc, char *argv[]) { arg_architecture = r; break; + case ARG_OFFLINE: + if (streq(optarg, "auto")) + arg_offline = -1; + else { + r = parse_boolean_argument("--offline=", optarg, NULL); + if (r < 0) + return r; + + arg_offline = r; + } + + break; + case '?': return -EINVAL;