From 9fb5d912f5b799acb99a79cd5f8a0e867212f2d3 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Wed, 26 Jun 2024 20:32:13 +0200 Subject: [PATCH 1/4] repart: Use loop_device_error_is_fatal() in one more place --- src/partition/repart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/partition/repart.c b/src/partition/repart.c index 7db493cafc..860e69dc19 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -6864,7 +6864,7 @@ static int context_minimize(Context *context) { if (arg_offline <= 0) { r = loop_device_make(fd, O_RDWR, 0, UINT64_MAX, context->sector_size, 0, LOCK_EX, &d); - if (r < 0 && (arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !strv_isempty(p->subvolumes))) + if (r < 0 && loop_device_error_is_fatal(p, r)) return log_error_errno(r, "Failed to make loopback device of %s: %m", temp); } From 531c6506c2254fa2742e52266cb77ede3f99287a Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Thu, 8 Aug 2024 20:16:55 +0200 Subject: [PATCH 2/4] repart: Constify partition_needs_populate() --- src/partition/repart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/partition/repart.c b/src/partition/repart.c index 860e69dc19..d05bb88db8 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -5063,7 +5063,7 @@ static int set_default_subvolume(Partition *p, const char *root) { return 0; } -static bool partition_needs_populate(Partition *p) { +static bool partition_needs_populate(const Partition *p) { assert(p); return !strv_isempty(p->copy_files) || !strv_isempty(p->make_directories); } From f75641b772cf824d206163e26547ea00e299106e Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Wed, 14 Aug 2024 17:31:30 +0200 Subject: [PATCH 3/4] repart: Don't add same dir to MakeDirectories= or Subvolumes= twice --- src/partition/repart.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/partition/repart.c b/src/partition/repart.c index d05bb88db8..967059dbea 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -1668,6 +1668,9 @@ static int config_parse_make_dirs( if (r < 0) continue; + if (strv_contains(*sv, d)) + continue; + r = strv_consume(sv, TAKE_PTR(d)); if (r < 0) return log_oom(); From eca3d07dd1a0d3dc0e18a5fe203f2cccfbd4cc4d Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Wed, 26 Jun 2024 20:33:06 +0200 Subject: [PATCH 4/4] repart: Allow Subvolumes= and DefaultSubvolume= when running offline mkfs.btrfs has recently learned new options --subvol and --default-subvol so let's stop failing when Subvolumes= and DefaultSubvolume= are used offline and use the new --subvol and --default-subvol options instead to create subvolumes in the generated root filesystem without root privileges or loop devices. --- man/repart.d.xml | 8 +++--- src/partition/repart.c | 56 +++++++++++++++++++++++++++++------------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/man/repart.d.xml b/man/repart.d.xml index ecf14e3099..4ad2764933 100644 --- a/man/repart.d.xml +++ b/man/repart.d.xml @@ -548,8 +548,8 @@ Note that this option only takes effect if the target filesystem supports subvolumes, such as btrfs. - Note that due to limitations of mkfs.btrfs, this option is only supported - when running with . + Note that this option is only supported in combination with + since btrfs-progs 6.11 or newer. @@ -564,8 +564,8 @@ Note that this option only takes effect if the target filesystem supports subvolumes, such as btrfs. - Note that due to limitations of mkfs.btrfs, this option is only supported - when running with . + Note that this option is only supported in combination with + since btrfs-progs 6.11 or newer. diff --git a/src/partition/repart.c b/src/partition/repart.c index 967059dbea..222c0958ef 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -2087,14 +2087,6 @@ static int partition_read_definition(Partition *p, const char *path, const char "SizeMinBytes=/SizeMaxBytes= cannot be used with Verity=%s.", verity_mode_to_string(p->verity)); - if (!strv_isempty(p->subvolumes) && arg_offline > 0) - return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EOPNOTSUPP), - "Subvolumes= cannot be used with --offline=yes."); - - if (p->default_subvolume && arg_offline > 0) - return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EOPNOTSUPP), - "DefaultSubvolume= cannot be used with --offline=yes."); - if (p->default_subvolume && !path_strv_contains(p->subvolumes, p->default_subvolume)) return log_syntax(NULL, LOG_ERR, path, 1, SYNTHETIC_ERRNO(EINVAL), "DefaultSubvolume= must be one of the paths in Subvolumes=."); @@ -3840,7 +3832,7 @@ static int prepare_temporary_file(Context *context, PartitionTarget *t, uint64_t static bool loop_device_error_is_fatal(const Partition *p, int r) { assert(p); - return arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) || !strv_isempty(p->subvolumes) || p->default_subvolume; + return arg_offline == 0 || (r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)); } static int partition_target_prepare( @@ -5156,6 +5148,40 @@ static int partition_populate_filesystem(Context *context, Partition *p, const c return 0; } +static int finalize_extra_mkfs_options(const Partition *p, const char *root, char ***ret) { + int r; + _cleanup_strv_free_ char **sv = NULL; + + assert(p); + assert(ret); + + r = mkfs_options_from_env("REPART", p->format, &sv); + if (r < 0) + return log_error_errno(r, + "Failed to determine mkfs command line options for '%s': %m", + p->format); + + if (partition_needs_populate(p) && root && streq(p->format, "btrfs")) { + STRV_FOREACH(subvol, p->subvolumes) { + if (p->default_subvolume && streq(*subvol, p->default_subvolume)) + continue; + + r = strv_extend_many(&sv, "--subvol", *subvol); + if (r < 0) + return log_oom(); + } + + if (p->default_subvolume) { + r = strv_extend_many(&sv, "--default-subvol", p->default_subvolume); + if (r < 0) + return log_oom(); + } + } + + *ret = TAKE_PTR(sv); + return 0; +} + static int context_mkfs(Context *context) { int r; @@ -5224,11 +5250,9 @@ static int context_mkfs(Context *context) { return r; } - r = mkfs_options_from_env("REPART", p->format, &extra_mkfs_options); + r = finalize_extra_mkfs_options(p, root, &extra_mkfs_options); if (r < 0) - return log_error_errno(r, - "Failed to determine mkfs command line options for '%s': %m", - p->format); + return r; r = make_filesystem(partition_target_path(t), p->format, strempty(p->new_label), root, p->fs_uuid, arg_discard, /* quiet = */ false, @@ -6785,11 +6809,9 @@ static int context_minimize(Context *context) { return r; } - r = mkfs_options_from_env("REPART", p->format, &extra_mkfs_options); + r = finalize_extra_mkfs_options(p, root, &extra_mkfs_options); if (r < 0) - return log_error_errno(r, - "Failed to determine mkfs command line options for '%s': %m", - p->format); + return r; r = make_filesystem(d ? d->node : temp, p->format,