diff options
author | Daan De Meyer <daan.j.demeyer@gmail.com> | 2023-01-12 22:42:30 +0100 |
---|---|---|
committer | Daan De Meyer <daan.j.demeyer@gmail.com> | 2023-01-17 20:09:22 +0100 |
commit | e1878ef72a2f88652b13a320bb57275c54128aca (patch) | |
tree | 6344a55413f7ff768c06f6d83d8e9779436363f3 | |
parent | 065bdb6f0fd0a77decd461db0c040d91bd80c642 (diff) | |
download | systemd-e1878ef72a2f88652b13a320bb57275c54128aca.tar.gz |
repart: Allow configuring sector size
Let's allow users to configure the (logical) sector size of their
image. This is required when building images for a 4k sector size
disk on a 512b sector size host or vice-versa.
-rw-r--r-- | man/systemd-repart.xml | 9 | ||||
-rw-r--r-- | src/basic/parse-util.c | 20 | ||||
-rw-r--r-- | src/basic/parse-util.h | 1 | ||||
-rw-r--r-- | src/home/homectl.c | 20 | ||||
-rw-r--r-- | src/home/homework-luks.c | 2 | ||||
-rw-r--r-- | src/partition/makefs.c | 2 | ||||
-rw-r--r-- | src/partition/repart.c | 43 | ||||
-rw-r--r-- | src/shared/mkfs-util.c | 23 | ||||
-rw-r--r-- | src/shared/mkfs-util.h | 10 | ||||
-rw-r--r-- | src/test/test-loop-block.c | 8 |
10 files changed, 97 insertions, 41 deletions
diff --git a/man/systemd-repart.xml b/man/systemd-repart.xml index be7abdbcd6..9033ef76d6 100644 --- a/man/systemd-repart.xml +++ b/man/systemd-repart.xml @@ -387,6 +387,15 @@ <command>systemd-repart</command> was executed.</para></listitem> </varlistentry> + <varlistentry> + <term><option>--sector-size=</option><arg>BYTES</arg></term> + + <listitem><para>This option allows configuring the sector size of the image produced by + <command>systemd-repart</command>. It takes a value that is a power of <literal>2</literal> between + <literal>512</literal> and <literal>4096</literal>. This option is useful when building images for + disks that use a different sector size as the disk on which the image is produced.</para></listitem>. + </varlistentry> + <xi:include href="standard-options.xml" xpointer="help" /> <xi:include href="standard-options.xml" xpointer="version" /> <xi:include href="standard-options.xml" xpointer="no-pager" /> diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c index 3b3efb0ab8..3445d31307 100644 --- a/src/basic/parse-util.c +++ b/src/basic/parse-util.c @@ -256,6 +256,26 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) { return 0; } +int parse_sector_size(const char *t, uint64_t *ret) { + int r; + + assert(t); + assert(ret); + + uint64_t ss; + + r = safe_atou64(t, &ss); + if (r < 0) + return log_error_errno(r, "Failed to parse sector size parameter %s", t); + if (ss < 512 || ss > 4096) /* Allow up to 4K due to dm-crypt support and 4K alignment by the homed LUKS backend */ + return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Sector size not between 512 and 4096: %s", t); + if (!ISPOWEROF2(ss)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Sector size not power of 2: %s", t); + + *ret = ss; + return 0; +} + int parse_range(const char *t, unsigned *lower, unsigned *upper) { _cleanup_free_ char *word = NULL; unsigned l, u; diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h index 8d8d52327b..877199529d 100644 --- a/src/basic/parse-util.h +++ b/src/basic/parse-util.h @@ -18,6 +18,7 @@ int parse_ifindex(const char *s); int parse_mtu(int family, const char *s, uint32_t *ret); int parse_size(const char *t, uint64_t base, uint64_t *size); +int parse_sector_size(const char *t, uint64_t *ret); int parse_range(const char *t, unsigned *lower, unsigned *upper); int parse_errno(const char *t); diff --git a/src/home/homectl.c b/src/home/homectl.c index 0a4c01834a..fd71e98eef 100644 --- a/src/home/homectl.c +++ b/src/home/homectl.c @@ -1798,26 +1798,6 @@ static int parse_disk_size(const char *t, uint64_t *ret) { return 0; } -static int parse_sector_size(const char *t, uint64_t *ret) { - int r; - - assert(t); - assert(ret); - - uint64_t ss; - - r = safe_atou64(t, &ss); - if (r < 0) - return log_error_errno(r, "Failed to parse sector size parameter %s", t); - if (ss < 512 || ss > 4096) /* Allow up to 4K due to dm-crypt support and 4K alignment by the homed LUKS backend */ - return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Sector size not between 512 and 4096: %s", t); - if (!ISPOWEROF2(ss)) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Sector size not power of 2: %s", t); - - *ret = ss; - return 0; -} - static int resize_home(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_(user_record_unrefp) UserRecord *secret = NULL; diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index f215558ae0..3433cf7d40 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -2356,7 +2356,7 @@ int home_create_luks( r = mkfs_options_for_fstype(fstype, &extra_mkfs_options); if (r < 0) return log_error_errno(r, "Failed to determine mkfs command line options for '%s': %m", fstype); - r = make_filesystem(setup->dm_node, fstype, user_record_user_name_and_realm(h), NULL, fs_uuid, user_record_luks_discard(h), extra_mkfs_options); + r = make_filesystem(setup->dm_node, fstype, user_record_user_name_and_realm(h), NULL, fs_uuid, user_record_luks_discard(h), 0, extra_mkfs_options); if (r < 0) return r; diff --git a/src/partition/makefs.c b/src/partition/makefs.c index 2733763eb2..b37a3b9008 100644 --- a/src/partition/makefs.c +++ b/src/partition/makefs.c @@ -70,7 +70,7 @@ static int run(int argc, char *argv[]) { if (r < 0) return log_error_errno(r, "Failed to extract file name from '%s': %m", device); - return make_filesystem(device, fstype, label, NULL, uuid, true, NULL); + return make_filesystem(device, fstype, label, NULL, uuid, true, 0, NULL); } DEFINE_MAIN_FUNCTION(run); diff --git a/src/partition/repart.c b/src/partition/repart.c index 674bb08015..9698f1be07 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -147,6 +147,7 @@ static size_t arg_n_filter_partitions = 0; static FilterPartitionsType arg_filter_partitions_type = FILTER_PARTITIONS_NONE; static sd_id128_t *arg_defer_partitions = NULL; static size_t arg_n_defer_partitions = 0; +static uint64_t arg_sector_size = 0; STATIC_DESTRUCTOR_REGISTER(arg_root, freep); STATIC_DESTRUCTOR_REGISTER(arg_image, freep); @@ -1973,16 +1974,22 @@ static int context_load_partition_table(Context *context) { assert(context->end == UINT64_MAX); assert(context->total == UINT64_MAX); + c = fdisk_new_context(); + if (!c) + return log_oom(); + + if (arg_sector_size > 0) { + r = fdisk_save_user_sector_size(c, /* phy= */ 0, arg_sector_size); + if (r < 0) + return log_error_errno(r, "Failed to set sector size: %m"); + } + /* libfdisk doesn't have an API to operate on arbitrary fds, hence reopen the fd going via the * /proc/self/fd/ magic path if we have an existing fd. Open the original file otherwise. */ - if (context->backing_fd < 0) { - c = fdisk_new_context(); - if (!c) - return log_oom(); - - r = fdisk_assign_device(c, context->node, arg_dry_run); - } else - r = fdisk_new_context_fd(context->backing_fd, arg_dry_run, &c); + r = fdisk_assign_device( + c, + context->backing_fd >= 0 ? FORMAT_PROC_FD_PATH(context->backing_fd) : context->node, + arg_dry_run); if (r == -EINVAL && arg_size_auto) { struct stat st; @@ -1999,7 +2006,7 @@ static int context_load_partition_table(Context *context) { if (S_ISREG(st.st_mode) && st.st_size == 0) { /* User the fallback values if we have no better idea */ - context->sector_size = 512; + context->sector_size = arg_sector_size ?: 512; context->grain_size = 4096; return /* from_scratch = */ true; } @@ -4031,7 +4038,7 @@ static int context_mkfs(Context *context) { } r = make_filesystem(partition_target_path(t), p->format, strempty(p->new_label), root, - p->fs_uuid, arg_discard, NULL); + p->fs_uuid, arg_discard, context->sector_size, NULL); if (r < 0) return r; @@ -5361,7 +5368,8 @@ static int context_minimize(Context *context) { return r; } - r = make_filesystem(d ? d->node : temp, p->format, strempty(p->new_label), root, fs_uuid, arg_discard, NULL); + r = make_filesystem(d ? d->node : temp, p->format, strempty(p->new_label), root, fs_uuid, + arg_discard, context->sector_size, NULL); if (r < 0) return r; @@ -5414,7 +5422,8 @@ static int context_minimize(Context *context) { if (r < 0 && r != -ENOENT && !ERRNO_IS_PRIVILEGE(r)) return log_error_errno(r, "Failed to make loopback device of %s: %m", temp); - r = make_filesystem(d ? d->node : temp, p->format, strempty(p->new_label), root, p->fs_uuid, arg_discard, NULL); + r = make_filesystem(d ? d->node : temp, p->format, strempty(p->new_label), root, p->fs_uuid, + arg_discard, context->sector_size, NULL); if (r < 0) return r; @@ -5511,6 +5520,7 @@ static int help(void) { " --defer-partitions=PARTITION1,PARTITION2,PARTITION3,…\n" " Take partitions of the specified types into account\n" " but don't populate them yet\n" + " --sector-size=SIZE Set the logical sector size for the image\n" "\nSee the %s for details.\n", program_invocation_short_name, ansi_highlight(), @@ -5549,6 +5559,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_INCLUDE_PARTITIONS, ARG_EXCLUDE_PARTITIONS, ARG_DEFER_PARTITIONS, + ARG_SECTOR_SIZE, }; static const struct option options[] = { @@ -5579,6 +5590,7 @@ static int parse_argv(int argc, char *argv[]) { { "include-partitions", required_argument, NULL, ARG_INCLUDE_PARTITIONS }, { "exclude-partitions", required_argument, NULL, ARG_EXCLUDE_PARTITIONS }, { "defer-partitions", required_argument, NULL, ARG_DEFER_PARTITIONS }, + { "sector-size", required_argument, NULL, ARG_SECTOR_SIZE }, {} }; @@ -5866,6 +5878,13 @@ static int parse_argv(int argc, char *argv[]) { break; + case ARG_SECTOR_SIZE: + r = parse_sector_size(optarg, &arg_sector_size); + if (r < 0) + return r; + + break; + case '?': return -EINVAL; diff --git a/src/shared/mkfs-util.c b/src/shared/mkfs-util.c index bd3065645f..11ae92290d 100644 --- a/src/shared/mkfs-util.c +++ b/src/shared/mkfs-util.c @@ -301,6 +301,7 @@ int make_filesystem( const char *root, sd_id128_t uuid, bool discard, + uint64_t sector_size, char * const *extra_mkfs_args) { _cleanup_free_ char *mkfs = NULL, *mangled_label = NULL; @@ -397,6 +398,7 @@ int make_filesystem( "-I", "256", "-m", "0", "-E", discard ? "discard,lazy_itable_init=1" : "nodiscard,lazy_itable_init=1", + "-b", "4096", node); if (!argv) return log_oom(); @@ -413,6 +415,7 @@ int make_filesystem( "-O", "has_journal", "-m", "0", "-E", discard ? "discard,lazy_itable_init=1" : "nodiscard,lazy_itable_init=1", + "-b", "4096", node); if (root && strv_extend_strv(&argv, STRV_MAKE("-d", root), false) < 0) @@ -469,7 +472,15 @@ int make_filesystem( return log_oom(); } - } else if (streq(fstype, "vfat")) + if (sector_size > 0) { + if (strv_extend(&argv, "-s") < 0) + return log_oom(); + + if (strv_extendf(&argv, "size=%"PRIu64, sector_size) < 0) + return log_oom(); + } + + } else if (streq(fstype, "vfat")) { argv = strv_new(mkfs, "-i", vol_id, @@ -477,7 +488,15 @@ int make_filesystem( "-F", "32", /* yes, we force FAT32 here */ node); - else if (streq(fstype, "swap")) + if (sector_size > 0) { + if (strv_extend(&argv, "-S") < 0) + return log_oom(); + + if (strv_extendf(&argv, "%"PRIu64, sector_size) < 0) + return log_oom(); + } + + } else if (streq(fstype, "swap")) /* TODO: add --quiet here if * https://github.com/util-linux/util-linux/issues/1499 resolved. */ diff --git a/src/shared/mkfs-util.h b/src/shared/mkfs-util.h index 7f72016cca..b99ec3c0ad 100644 --- a/src/shared/mkfs-util.h +++ b/src/shared/mkfs-util.h @@ -11,4 +11,12 @@ int mkfs_exists(const char *fstype); int mkfs_supports_root_option(const char *fstype); -int make_filesystem(const char *node, const char *fstype, const char *label, const char *root, sd_id128_t uuid, bool discard, char * const *extra_mkfs_args); +int make_filesystem( + const char *node, + const char *fstype, + const char *label, + const char *root, + sd_id128_t uuid, + bool discard, + uint64_t sector_size, + char * const *extra_mkfs_args); diff --git a/src/test/test-loop-block.c b/src/test/test-loop-block.c index bfc3272643..97c2f66ac9 100644 --- a/src/test/test-loop-block.c +++ b/src/test/test-loop-block.c @@ -245,16 +245,16 @@ static int run(int argc, char *argv[]) { assert_se(r >= 0); assert_se(sd_id128_randomize(&id) >= 0); - assert_se(make_filesystem(dissected->partitions[PARTITION_ESP].node, "vfat", "EFI", NULL, id, true, NULL) >= 0); + assert_se(make_filesystem(dissected->partitions[PARTITION_ESP].node, "vfat", "EFI", NULL, id, true, 0, NULL) >= 0); assert_se(sd_id128_randomize(&id) >= 0); - assert_se(make_filesystem(dissected->partitions[PARTITION_XBOOTLDR].node, "vfat", "xbootldr", NULL, id, true, NULL) >= 0); + assert_se(make_filesystem(dissected->partitions[PARTITION_XBOOTLDR].node, "vfat", "xbootldr", NULL, id, true, 0, NULL) >= 0); assert_se(sd_id128_randomize(&id) >= 0); - assert_se(make_filesystem(dissected->partitions[PARTITION_ROOT].node, "ext4", "root", NULL, id, true, NULL) >= 0); + assert_se(make_filesystem(dissected->partitions[PARTITION_ROOT].node, "ext4", "root", NULL, id, true, 0, NULL) >= 0); assert_se(sd_id128_randomize(&id) >= 0); - assert_se(make_filesystem(dissected->partitions[PARTITION_HOME].node, "ext4", "home", NULL, id, true, NULL) >= 0); + assert_se(make_filesystem(dissected->partitions[PARTITION_HOME].node, "ext4", "home", NULL, id, true, 0, NULL) >= 0); dissected = dissected_image_unref(dissected); |