cc71a1
From 28008eb0bafcb3765e0ece7cb78710066f0ac2b8 Mon Sep 17 00:00:00 2001
cc71a1
From: Daan De Meyer <daan.j.demeyer@gmail.com>
cc71a1
Date: Sat, 12 Aug 2023 13:28:10 +0200
cc71a1
Subject: [PATCH 1/3] mkfs-util: Set sector size environment variables when
cc71a1
 invoking mkfs.ext4
cc71a1
cc71a1
Let's inform mkfs.ext4 about the sector size we're using.
cc71a1
---
cc71a1
 src/shared/mkfs-util.c | 16 +++++++++++++++-
cc71a1
 1 file changed, 15 insertions(+), 1 deletion(-)
cc71a1
cc71a1
diff --git a/src/shared/mkfs-util.c b/src/shared/mkfs-util.c
cc71a1
index 179bce6af6..8038abb945 100644
cc71a1
--- a/src/shared/mkfs-util.c
cc71a1
+++ b/src/shared/mkfs-util.c
cc71a1
@@ -268,7 +268,7 @@ int make_filesystem(
cc71a1
                 char * const *extra_mkfs_args) {
cc71a1
 
cc71a1
         _cleanup_free_ char *mkfs = NULL, *mangled_label = NULL;
cc71a1
-        _cleanup_strv_free_ char **argv = NULL;
cc71a1
+        _cleanup_strv_free_ char **argv = NULL, **env = NULL;
cc71a1
         _cleanup_(unlink_and_freep) char *protofile = NULL;
cc71a1
         char vol_id[CONST_MAX(SD_ID128_UUID_STRING_MAX, 8U + 1U)] = {};
cc71a1
         int r;
cc71a1
@@ -385,6 +385,15 @@ int make_filesystem(
cc71a1
                 if (root && strv_extend_strv(&argv, STRV_MAKE("-d", root), false) < 0)
cc71a1
                         return log_oom();
cc71a1
 
cc71a1
+                if (sector_size > 0)
cc71a1
+                        FOREACH_STRING(s, "MKE2FS_DEVICE_SECTSIZE", "MKE2FS_DEVICE_PHYS_SECTSIZE") {
cc71a1
+                                if (strv_extend(&env, s) < 0)
cc71a1
+                                        return log_oom();
cc71a1
+
cc71a1
+                                if (strv_extendf(&env, "%"PRIu64, sector_size) < 0)
cc71a1
+                                        return log_oom();
cc71a1
+                        }
cc71a1
+
cc71a1
         } else if (streq(fstype, "btrfs")) {
cc71a1
                 argv = strv_new(mkfs,
cc71a1
                                 "-q",
cc71a1
@@ -496,6 +505,11 @@ int make_filesystem(
cc71a1
         if (r == 0) {
cc71a1
                 /* Child */
cc71a1
 
cc71a1
+                STRV_FOREACH_PAIR(k, v, env)
cc71a1
+                        if (setenv(*k, *v, /* replace = */ true) < 0) {
cc71a1
+                                log_error_errno(r, "Failed to set %s=%s environment variable: %m", *k, *v);
cc71a1
+                                _exit(EXIT_FAILURE);
cc71a1
+                        }
cc71a1
                 execvp(mkfs, argv);
cc71a1
 
cc71a1
                 log_error_errno(errno, "Failed to execute %s: %m", mkfs);
cc71a1
-- 
cc71a1
2.41.0
cc71a1
cc71a1
cc71a1
From 8a2ee7ec8c200464302693456561f99bf92f0df4 Mon Sep 17 00:00:00 2001
cc71a1
From: Daan De Meyer <daan.j.demeyer@gmail.com>
cc71a1
Date: Sat, 12 Aug 2023 13:29:50 +0200
cc71a1
Subject: [PATCH 2/3] mkfs-util: Pass sector size to mkfs.f2fs
cc71a1
cc71a1
Let's pass the sector size to mkfs.f2fs as well.
cc71a1
---
cc71a1
 src/shared/mkfs-util.c | 8 ++++++++
cc71a1
 1 file changed, 8 insertions(+)
cc71a1
cc71a1
diff --git a/src/shared/mkfs-util.c b/src/shared/mkfs-util.c
cc71a1
index 8038abb945..1f73ff3742 100644
cc71a1
--- a/src/shared/mkfs-util.c
cc71a1
+++ b/src/shared/mkfs-util.c
cc71a1
@@ -419,6 +419,14 @@ int make_filesystem(
cc71a1
                                 "-t", one_zero(discard),
cc71a1
                                 node);
cc71a1
 
cc71a1
+                if (sector_size > 0) {
cc71a1
+                        if (strv_extend(&argv, "-w") < 0)
cc71a1
+                                return log_oom();
cc71a1
+
cc71a1
+                        if (strv_extendf(&argv, "%"PRIu64, sector_size) < 0)
cc71a1
+                                return log_oom();
cc71a1
+                }
cc71a1
+
cc71a1
         } else if (streq(fstype, "xfs")) {
cc71a1
                 const char *j;
cc71a1
 
cc71a1
-- 
cc71a1
2.41.0
cc71a1
cc71a1
cc71a1
From 8ecfc1f65ae27c0a44afd2e28a30a9fa03377cdc Mon Sep 17 00:00:00 2001
cc71a1
From: Daan De Meyer <daan.j.demeyer@gmail.com>
cc71a1
Date: Sat, 12 Aug 2023 13:30:46 +0200
cc71a1
Subject: [PATCH 3/3] repart: Use 4096 as the fallback sector size for
cc71a1
 verity/luks/filesystems
cc71a1
cc71a1
When we don't know the sector size of the actual block device, because
cc71a1
we're building an image in a loopback file and no sector size was specified
cc71a1
explicitly, let's use 4096 as the sector size for filesystems, verity and
cc71a1
LUKS. This should be the most compatible option, since 4096 will also work
cc71a1
on devices with sector size 512 or 2048.
cc71a1
cc71a1
For the actual GPT partition table size, we stick with 512 as the default
cc71a1
value since UEFI firmware and the kernel will only try to read the GPT
cc71a1
partition table from the first LBA on the device and the sector size for
cc71a1
most devices is still 512. It can also be trivially modified when copying
cc71a1
the image to another device using --copy-from + --sector-size.
cc71a1
---
cc71a1
 src/partition/repart.c | 60 +++++++++++++++++++++++++++++++-----------
cc71a1
 1 file changed, 44 insertions(+), 16 deletions(-)
cc71a1
cc71a1
diff --git a/src/partition/repart.c b/src/partition/repart.c
cc71a1
index 0431c6a86b..1796b9ed35 100644
cc71a1
--- a/src/partition/repart.c
cc71a1
+++ b/src/partition/repart.c
cc71a1
@@ -96,6 +96,10 @@
cc71a1
 /* LUKS2 volume key size. */
cc71a1
 #define VOLUME_KEY_SIZE (512ULL/8ULL)
cc71a1
 
cc71a1
+/* Use 4K as the default filesystem sector size because as long as the partitions are aligned to 4K, the
cc71a1
+ * filesystems will then also be compatible with sector sizes 512, 1024 and 2048. */
cc71a1
+#define DEFAULT_FILESYSTEM_SECTOR_SIZE 4096ULL
cc71a1
+
cc71a1
 /* Note: When growing and placing new partitions we always align to 4K sector size. It's how newer hard disks
cc71a1
  * are designed, and if everything is aligned to that performance is best. And for older hard disks with 512B
cc71a1
  * sector size devices were generally assumed to have an even number of sectors, hence at the worst we'll
cc71a1
@@ -267,8 +271,7 @@ typedef struct Context {
cc71a1
         uint64_t start, end, total;
cc71a1
 
cc71a1
         struct fdisk_context *fdisk_context;
cc71a1
-        uint64_t sector_size;
cc71a1
-        uint64_t grain_size;
cc71a1
+        uint64_t sector_size, grain_size, fs_sector_size;
cc71a1
 
cc71a1
         sd_id128_t seed;
cc71a1
 
cc71a1
@@ -1988,7 +1991,7 @@ static int context_load_partition_table(Context *context) {
cc71a1
         sd_id128_t disk_uuid;
cc71a1
         size_t n_partitions;
cc71a1
         unsigned long secsz;
cc71a1
-        uint64_t grainsz;
cc71a1
+        uint64_t grainsz, fs_secsz = DEFAULT_FILESYSTEM_SECTOR_SIZE;
cc71a1
         int r;
cc71a1
 
cc71a1
         assert(context);
cc71a1
@@ -2002,20 +2005,31 @@ static int context_load_partition_table(Context *context) {
cc71a1
         if (!c)
cc71a1
                 return log_oom();
cc71a1
 
cc71a1
-        if (arg_sector_size > 0)
cc71a1
+        if (arg_sector_size > 0) {
cc71a1
                 r = fdisk_save_user_sector_size(c, /* phy= */ 0, arg_sector_size);
cc71a1
-        else {
cc71a1
+                fs_secsz = arg_sector_size;
cc71a1
+        } else {
cc71a1
                 uint32_t ssz;
cc71a1
+                struct stat st;
cc71a1
 
cc71a1
                 r = context_open_and_lock_backing_fd(context, context->node);
cc71a1
                 if (r < 0)
cc71a1
                         return r;
cc71a1
 
cc71a1
+                if (fstat(context->backing_fd, &st) < 0)
cc71a1
+                        return log_error_errno(r, "Failed to stat %s: %m", context->node);
cc71a1
+
cc71a1
                 /* Auto-detect sector size if not specified. */
cc71a1
                 r = probe_sector_size_prefer_ioctl(context->backing_fd, &ssz;;
cc71a1
                 if (r < 0)
cc71a1
                         return log_error_errno(r, "Failed to probe sector size of '%s': %m", context->node);
cc71a1
 
cc71a1
+                /* If we found the sector size and we're operating on a block device, use it as the file
cc71a1
+                 * system sector size as well, as we know its the sector size of the actual block device and
cc71a1
+                 * not just the offset at which we found the GPT header. */
cc71a1
+                if (r > 0 && S_ISBLK(st.st_mode))
cc71a1
+                        fs_secsz = ssz;
cc71a1
+
cc71a1
                 r = fdisk_save_user_sector_size(c, /* phy= */ 0, ssz);
cc71a1
         }
cc71a1
         if (r < 0)
cc71a1
@@ -2041,8 +2055,9 @@ static int context_load_partition_table(Context *context) {
cc71a1
                         return log_error_errno(errno, "Failed to stat block device '%s': %m", context->node);
cc71a1
 
cc71a1
                 if (S_ISREG(st.st_mode) && st.st_size == 0) {
cc71a1
-                        /* User the fallback values if we have no better idea */
cc71a1
-                        context->sector_size = arg_sector_size ?: 512;
cc71a1
+                        /* Use the fallback values if we have no better idea */
cc71a1
+                        context->sector_size = fdisk_get_sector_size(c);
cc71a1
+                        context->fs_sector_size = fs_secsz;
cc71a1
                         context->grain_size = 4096;
cc71a1
                         return /* from_scratch = */ true;
cc71a1
                 }
cc71a1
@@ -2318,6 +2333,7 @@ add_initial_free_area:
cc71a1
         context->end = last_lba;
cc71a1
         context->total = nsectors;
cc71a1
         context->sector_size = secsz;
cc71a1
+        context->fs_sector_size = fs_secsz;
cc71a1
         context->grain_size = grainsz;
cc71a1
         context->fdisk_context = TAKE_PTR(c);
cc71a1
 
cc71a1
@@ -3271,7 +3287,7 @@ static int partition_encrypt(Context *context, Partition *p, const char *node) {
cc71a1
 #if HAVE_LIBCRYPTSETUP && HAVE_CRYPT_SET_DATA_OFFSET && HAVE_CRYPT_REENCRYPT_INIT_BY_PASSPHRASE && HAVE_CRYPT_REENCRYPT
cc71a1
         struct crypt_params_luks2 luks_params = {
cc71a1
                 .label = strempty(ASSERT_PTR(p)->new_label),
cc71a1
-                .sector_size = ASSERT_PTR(context)->sector_size,
cc71a1
+                .sector_size = ASSERT_PTR(context)->fs_sector_size,
cc71a1
                 .data_device = node,
cc71a1
         };
cc71a1
         struct crypt_params_reencrypt reencrypt_params = {
cc71a1
@@ -3310,7 +3326,7 @@ static int partition_encrypt(Context *context, Partition *p, const char *node) {
cc71a1
                 return log_error_errno(r, "Failed to create temporary LUKS header file: %m");
cc71a1
 
cc71a1
         /* Weird cryptsetup requirement which requires the header file to be the size of at least one sector. */
cc71a1
-        r = ftruncate(fileno(h), context->sector_size);
cc71a1
+        r = ftruncate(fileno(h), luks_params.sector_size);
cc71a1
         if (r < 0)
cc71a1
                 return log_error_errno(r, "Failed to grow temporary LUKS header file: %m");
cc71a1
 
cc71a1
@@ -3549,8 +3565,8 @@ static int partition_format_verity_hash(
cc71a1
                                 .flags = CRYPT_VERITY_CREATE_HASH,
cc71a1
                                 .hash_name = "sha256",
cc71a1
                                 .hash_type = 1,
cc71a1
-                                .data_block_size = context->sector_size,
cc71a1
-                                .hash_block_size = context->sector_size,
cc71a1
+                                .data_block_size = context->fs_sector_size,
cc71a1
+                                .hash_block_size = context->fs_sector_size,
cc71a1
                                 .salt_size = 32,
cc71a1
                         });
cc71a1
         if (r < 0) {
cc71a1
@@ -4090,7 +4106,7 @@ static int context_mkfs(Context *context) {
cc71a1
                 }
cc71a1
 
cc71a1
                 r = make_filesystem(partition_target_path(t), p->format, strempty(p->new_label), root,
cc71a1
-                                    p->fs_uuid, arg_discard, context->sector_size, NULL);
cc71a1
+                                    p->fs_uuid, arg_discard, context->fs_sector_size, NULL);
cc71a1
                 if (r < 0)
cc71a1
                         return r;
cc71a1
 
cc71a1
@@ -5423,8 +5439,14 @@ static int context_minimize(Context *context) {
cc71a1
                                 return r;
cc71a1
                 }
cc71a1
 
cc71a1
-                r = make_filesystem(d ? d->node : temp, p->format, strempty(p->new_label), root, fs_uuid,
cc71a1
-                                    arg_discard, context->sector_size, NULL);
cc71a1
+                r = make_filesystem(d ? d->node : temp,
cc71a1
+                                    p->format,
cc71a1
+                                    strempty(p->new_label),
cc71a1
+                                    root,
cc71a1
+                                    fs_uuid,
cc71a1
+                                    arg_discard,
cc71a1
+                                    context->fs_sector_size,
cc71a1
+                                    NULL);
cc71a1
                 if (r < 0)
cc71a1
                         return r;
cc71a1
 
cc71a1
@@ -5477,8 +5499,14 @@ static int context_minimize(Context *context) {
cc71a1
                 if (r < 0 && r != -ENOENT && !ERRNO_IS_PRIVILEGE(r))
cc71a1
                         return log_error_errno(r, "Failed to make loopback device of %s: %m", temp);
cc71a1
 
cc71a1
-                r = make_filesystem(d ? d->node : temp, p->format, strempty(p->new_label), root, p->fs_uuid,
cc71a1
-                                    arg_discard, context->sector_size, NULL);
cc71a1
+                r = make_filesystem(d ? d->node : temp,
cc71a1
+                                    p->format,
cc71a1
+                                    strempty(p->new_label),
cc71a1
+                                    root,
cc71a1
+                                    p->fs_uuid,
cc71a1
+                                    arg_discard,
cc71a1
+                                    context->fs_sector_size,
cc71a1
+                                    NULL);
cc71a1
                 if (r < 0)
cc71a1
                         return r;
cc71a1
 
cc71a1
-- 
cc71a1
2.41.0
cc71a1