From: Lennart Poettering Date: Thu, 19 Jun 2025 12:14:31 +0000 (+0200) Subject: repart: make file system sector size configurable X-Git-Tag: v258-rc1~244^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e7b4b2968e0e3752cdde290c57fe208eab9f6265;p=thirdparty%2Fsystemd.git repart: make file system sector size configurable Let's make the fs sector size configurable. This also adds infrastructure so that we can pick different sector sizes as defaults eventually, but doesn't actually do that. (Background: I think we should probably default to native sector size for the ESP, but Daan disagrees, so I'll leave this out for now). --- diff --git a/man/repart.d.xml b/man/repart.d.xml index a53057ffa1a..eb628ffc169 100644 --- a/man/repart.d.xml +++ b/man/repart.d.xml @@ -1007,6 +1007,25 @@ + + FileSystemSectorSize= + + Controls the sector size for any file system, LUKS volume or Verity volume formatted + on this partition. Expects a power of 2 as value, and must be equal or larger than 512. Typically + it's recommended to set the file system sector size to 4096, even on 512 sector disks (and in + particular for images that are only ever intended to be stored as file on disks), in order to + optimize performance. However, for compatibility with foreign operating systems or firmware it might + be advisable to use the native sector size of the backing disk. + + If unspecified and operating on a block device, defaults to the native sector size of the + device. If unspecified and operating on a disk image file defaults to 4096. + + Regardless of what is configured here, or which default is picked, the file system sector size + is always increased to be equal or larger than the disk sector size. + + + + diff --git a/src/repart/repart.c b/src/repart/repart.c index de138c15d33..0dc9b7eb0e2 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -409,6 +409,7 @@ typedef struct Partition { uint64_t verity_hash_block_size; char *compression; char *compression_level; + uint64_t fs_sector_size; int add_validatefs; CopyFiles *copy_files; @@ -461,7 +462,7 @@ typedef struct Context { uint64_t start, end, total; struct fdisk_context *fdisk_context; - uint64_t sector_size, grain_size, fs_sector_size; + uint64_t sector_size, grain_size, default_fs_sector_size; sd_id128_t seed; @@ -609,6 +610,7 @@ static Partition *partition_new(void) { .add_validatefs = -1, .last_percent = UINT_MAX, .progress_ratelimit = { 100 * USEC_PER_MSEC, 1 }, + .fs_sector_size = UINT64_MAX, }; return p; @@ -724,6 +726,7 @@ static void partition_foreignize(Partition *p) { p->growfs = -1; p->verity = VERITY_OFF; p->add_validatefs = false; + p->fs_sector_size = UINT64_MAX; partition_mountpoint_free_many(p->mountpoints, p->n_mountpoints); p->mountpoints = NULL; @@ -909,6 +912,23 @@ static bool context_drop_or_foreignize_one_priority(Context *context) { return true; } +static uint64_t partition_fs_sector_size(const Context *c, const Partition *p) { + assert(c); + assert(p); + + uint64_t ss; + + if (p->fs_sector_size != UINT64_MAX) + /* Prefer explicitly configured value */ + ss = p->fs_sector_size; + else + /* Otherwise follow the default sector size */ + ss = c->default_fs_sector_size; + + /* never allow the fs sector size to be picked smaller than the physical sector size */ + return MAX(ss, c->sector_size); +} + static uint64_t partition_min_size(const Context *context, const Partition *p) { uint64_t sz, override_min; @@ -1731,6 +1751,45 @@ static int config_parse_block_size( return 0; } +static int config_parse_fs_sector_size( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + uint64_t *fssecsz = ASSERT_PTR(data), parsed; + int r; + + assert(rvalue); + + if (isempty(rvalue)) { + *fssecsz = UINT64_MAX; + return 0; + } + + r = parse_size(rvalue, 1024, &parsed); + if (r < 0) + return log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse size value: %s", rvalue); + + if (!ISPOWEROF2(parsed)) + return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), + "Value not a power of 2: %s", rvalue); + + /* NB: we make no upper restriction here, since the maximum logical sector sizes file systems support + * vary greatly, and can be much larger than 4K. (That's also the reason we dont't use + * parse_sector_size() here.) */ + + *fssecsz = parsed; + return 0; +} + static int config_parse_fstype( const char *unit, const char *filename, @@ -2483,6 +2542,7 @@ static int partition_read_definition(Partition *p, const char *path, const char { "Partition", "CompressionLevel", config_parse_string, CONFIG_PARSE_STRING_SAFE_AND_ASCII, &p->compression_level }, { "Partition", "SupplementFor", config_parse_string, 0, &p->supplement_for_name }, { "Partition", "AddValidateFS", config_parse_tristate, 0, &p->add_validatefs }, + { "Partition", "FileSystemSectorSize", config_parse_fs_sector_size, 0, &p->fs_sector_size }, {} }; _cleanup_free_ char *filename = NULL; @@ -3256,7 +3316,7 @@ static int context_load_partition_table(Context *context) { if (S_ISREG(st.st_mode) && st.st_size == 0) { /* Use the fallback values if we have no better idea */ context->sector_size = fdisk_get_sector_size(c); - context->fs_sector_size = fs_secsz; + context->default_fs_sector_size = fs_secsz; context->grain_size = 4096; return /* from_scratch = */ true; } @@ -3290,7 +3350,7 @@ static int context_load_partition_table(Context *context) { * larger */ grainsz = secsz < 4096 ? 4096 : secsz; - log_debug("Sector size of device is %lu bytes. Using filesystem sector size of %" PRIu64 " and grain size of %" PRIu64 ".", secsz, fs_secsz, grainsz); + log_debug("Sector size of device is %lu bytes. Using default filesystem sector size of %" PRIu64 " and grain size of %" PRIu64 ".", secsz, fs_secsz, grainsz); switch (arg_empty) { @@ -3539,7 +3599,7 @@ add_initial_free_area: context->end = last_lba; context->total = nsectors; context->sector_size = secsz; - context->fs_sector_size = fs_secsz; + context->default_fs_sector_size = fs_secsz; context->grain_size = grainsz; context->fdisk_context = TAKE_PTR(c); @@ -4597,7 +4657,7 @@ static int partition_encrypt(Context *context, Partition *p, PartitionTarget *ta const char *node = partition_target_path(target); struct crypt_params_luks2 luks_params = { .label = strempty(ASSERT_PTR(p)->new_label), - .sector_size = ASSERT_PTR(context)->fs_sector_size, + .sector_size = partition_fs_sector_size(context, p), .data_device = offline ? node : NULL, }; struct crypt_params_reencrypt reencrypt_params = { @@ -6347,10 +6407,17 @@ static int context_mkfs(Context *context) { if (r < 0) return r; - r = make_filesystem(partition_target_path(t), p->format, strempty(p->new_label), root, - p->fs_uuid, partition_mkfs_flags(p), - context->fs_sector_size, p->compression, p->compression_level, - extra_mkfs_options); + r = make_filesystem( + partition_target_path(t), + p->format, + strempty(p->new_label), + root, + p->fs_uuid, + partition_mkfs_flags(p), + partition_fs_sector_size(context, p), + p->compression, + p->compression_level, + extra_mkfs_options); if (r < 0) return r; @@ -7925,10 +7992,10 @@ static int context_update_verity_size(Context *context) { assert_se(dp = p->siblings[VERITY_DATA]); if (p->verity_data_block_size == UINT64_MAX) - p->verity_data_block_size = context->fs_sector_size; + p->verity_data_block_size = partition_fs_sector_size(context, p); if (p->verity_hash_block_size == UINT64_MAX) - p->verity_hash_block_size = context->fs_sector_size; + p->verity_hash_block_size = partition_fs_sector_size(context, p); uint64_t sz; if (dp->size_max != UINT64_MAX) { @@ -8061,16 +8128,17 @@ static int context_minimize(Context *context) { if (r < 0) return r; - r = make_filesystem(d ? d->node : temp, - p->format, - strempty(p->new_label), - root, - fs_uuid, - partition_mkfs_flags(p), - context->fs_sector_size, - p->compression, - p->compression_level, - extra_mkfs_options); + r = make_filesystem( + d ? d->node : temp, + p->format, + strempty(p->new_label), + root, + fs_uuid, + partition_mkfs_flags(p), + partition_fs_sector_size(context, p), + p->compression, + p->compression_level, + extra_mkfs_options); if (r < 0) return r; @@ -8152,16 +8220,17 @@ static int context_minimize(Context *context) { 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, - partition_mkfs_flags(p), - context->fs_sector_size, - p->compression, - p->compression_level, - extra_mkfs_options); + r = make_filesystem( + d ? d->node : temp, + p->format, + strempty(p->new_label), + root, + p->fs_uuid, + partition_mkfs_flags(p), + partition_fs_sector_size(context, p), + p->compression, + p->compression_level, + extra_mkfs_options); if (r < 0) return r;