]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
repart: Allow configuring sector size 26044/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 12 Jan 2023 21:42:30 +0000 (22:42 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 17 Jan 2023 19:09:22 +0000 (20:09 +0100)
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.

man/systemd-repart.xml
src/basic/parse-util.c
src/basic/parse-util.h
src/home/homectl.c
src/home/homework-luks.c
src/partition/makefs.c
src/partition/repart.c
src/shared/mkfs-util.c
src/shared/mkfs-util.h
src/test/test-loop-block.c

index be7abdbcd688dc286fdc37639c0503b6128b6d4b..9033ef76d6923a2533316b9914ff3d00766c1d93 100644 (file)
         <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" />
index 3b3efb0ab8c561fe0772711f4af540878b0f4bd3..3445d3130761c708c595cc8ec242b8af7e62080d 100644 (file)
@@ -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;
index 8d8d52327b751bf3fc5fc5f91c63d5fe8a506e60..877199529ddc607adc0843b0a734bbfeba5130d6 100644 (file)
@@ -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);
 
index 0a4c01834aa3465c7d1a0da15e5f9048fab1b532..fd71e98eef6dab4d5bc9face0508dc17b9eeb680 100644 (file)
@@ -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;
index f215558ae04b0a4d1779aa1b40568201398d57fd..3433cf7d40f4598e3f1473811340f31ffdddf29e 100644 (file)
@@ -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;
 
index 2733763eb2fa43346a9530bd0a54724bb0f355ab..b37a3b90081e8209e2946397f5ecda13c1b379a5 100644 (file)
@@ -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);
index 674bb08015f3b88d930b18ef9aaf5967bd9ce34d..9698f1be076cf04cc419e72368b41c9db4bb852c 100644 (file)
@@ -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;
 
index bd3065645f9ccb0185feb339c1a1eda16b7618ea..11ae92290d71eeca9a514f5712ca0205fac2a3b4 100644 (file)
@@ -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. */
 
index 7f72016cca08e6615a254336d6ddb8beadf34de1..b99ec3c0ad3a5cf8338defb3a6221d8f4d2f4537 100644 (file)
@@ -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);
index bfc327264368d010e186b03905df1a13d50cc217..97c2f66ac99f5fed4ef7ee2f242ecb7312190a82 100644 (file)
@@ -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);