]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
homework: when creating/resizing GPT partitions, also set sector size explicitly
authorLennart Poettering <lennart@poettering.net>
Tue, 17 Jan 2023 20:42:02 +0000 (21:42 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 18 Jan 2023 09:47:17 +0000 (10:47 +0100)
src/home/homework-luks.c
src/partition/repart.c
src/shared/dissect-image.c
src/shared/dissect-image.h
src/shared/fdisk-util.c
src/shared/fdisk-util.h

index 5ad7706636d47bc8354ed6e6826077984cd25845..2ea9887853737b052b09df193dfe53f092c5be6b 100644 (file)
@@ -1840,6 +1840,7 @@ static int luks_format(
 
 static int make_partition_table(
                 int fd,
+                uint32_t sector_size,
                 const char *label,
                 sd_id128_t uuid,
                 uint64_t *ret_offset,
@@ -1867,7 +1868,7 @@ static int make_partition_table(
         if (r < 0)
                 return log_error_errno(r, "Failed to initialize partition type: %m");
 
-        r = fdisk_new_context_fd(fd, /* read_only= */ false, &c);
+        r = fdisk_new_context_fd(fd, /* read_only= */ false, sector_size, &c);
         if (r < 0)
                 return log_error_errno(r, "Failed to open device: %m");
 
@@ -2317,6 +2318,7 @@ int home_create_luks(
 
         r = make_partition_table(
                         setup->image_fd,
+                        user_record_luks_sector_size(h),
                         user_record_user_name_and_realm(h),
                         partition_uuid,
                         &partition_offset,
@@ -2704,7 +2706,7 @@ static int prepare_resize_partition(
                 return 0;
         }
 
-        r = fdisk_new_context_fd(fd, /* read_only= */ false, &c);
+        r = fdisk_new_context_fd(fd, /* read_only= */ false, UINT32_MAX, &c);
         if (r < 0)
                 return log_error_errno(r, "Failed to open device: %m");
 
@@ -2788,6 +2790,7 @@ static int apply_resize_partition(
 
         _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
         _cleanup_free_ void *two_zero_lbas = NULL;
+        uint32_t ssz;
         ssize_t n;
         int r;
 
@@ -2808,18 +2811,22 @@ static int apply_resize_partition(
         if (r < 0)
                 return log_error_errno(r, "Failed to change partition size: %m");
 
-        two_zero_lbas = malloc0(1024U);
+        r = probe_sector_size(fd, &ssz);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine current sector size: %m");
+
+        two_zero_lbas = malloc0(ssz * 2);
         if (!two_zero_lbas)
                 return log_oom();
 
         /* libfdisk appears to get confused by the existing PMBR. Let's explicitly flush it out. */
-        n = pwrite(fd, two_zero_lbas, 1024U, 0);
+        n = pwrite(fd, two_zero_lbas, ssz * 2, 0);
         if (n < 0)
                 return log_error_errno(errno, "Failed to wipe partition table: %m");
-        if (n != 1024)
+        if ((size_t) n != ssz * 2)
                 return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write while wiping partition table.");
 
-        r = fdisk_new_context_fd(fd, /* read_only= */ false, &c);
+        r = fdisk_new_context_fd(fd, /* read_only= */ false, ssz, &c);
         if (r < 0)
                 return log_error_errno(r, "Failed to open device: %m");
 
index 9698f1be076cf04cc419e72368b41c9db4bb852c..1fe1c06a3c43ec253760d00af9db1338bba93a80 100644 (file)
@@ -6160,7 +6160,7 @@ static int find_root(Context *context) {
         return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "Failed to discover root block device.");
 }
 
-static int resize_pt(int fd) {
+static int resize_pt(int fd, uint64_t sector_size) {
         _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
         int r;
 
@@ -6168,7 +6168,7 @@ static int resize_pt(int fd) {
          * possession of the enlarged backing file. For this it suffices to open the device with libfdisk and
          * immediately write it again, with no changes. */
 
-        r = fdisk_new_context_fd(fd, /* read_only= */ false, &c);
+        r = fdisk_new_context_fd(fd, /* read_only= */ false, sector_size, &c);
         if (r < 0)
                 return log_error_errno(r, "Failed to open device '%s': %m", FORMAT_PROC_FD_PATH(fd));
 
@@ -6192,7 +6192,8 @@ static int resize_backing_fd(
                 const char *node,           /* The primary way we access the disk image to operate on */
                 int *fd,                    /* An O_RDONLY fd referring to that inode */
                 const char *backing_file,   /* If the above refers to a loopback device, the backing regular file for that, which we can grow */
-                LoopDevice *loop_device) {
+                LoopDevice *loop_device,
+                uint64_t sector_size) {
 
         _cleanup_close_ int writable_fd = -EBADF;
         uint64_t current_size;
@@ -6304,7 +6305,7 @@ static int resize_backing_fd(
                          node, FORMAT_BYTES(current_size), FORMAT_BYTES(arg_size));
 
 done:
-        r = resize_pt(writable_fd);
+        r = resize_pt(writable_fd, sector_size);
         if (r < 0)
                 return r;
 
@@ -6429,7 +6430,8 @@ static int run(int argc, char *argv[]) {
                                 context->node,
                                 &context->backing_fd,
                                 node_is_our_loop ? arg_image : NULL,
-                                node_is_our_loop ? loop_device : NULL);
+                                node_is_our_loop ? loop_device : NULL,
+                                context->sector_size);
                 if (r < 0)
                         return r;
         }
@@ -6503,7 +6505,8 @@ static int run(int argc, char *argv[]) {
                                 context->node,
                                 &context->backing_fd,
                                 node_is_our_loop ? arg_image : NULL,
-                                node_is_our_loop ? loop_device : NULL);
+                                node_is_our_loop ? loop_device : NULL,
+                                context->sector_size);
                 if (r < 0)
                         return r;
 
index da8eba83deab4f0b35870605fa8093ce12df8e70..c0d052e0ea36dd9da9363593491f0a6a05e9c659 100644 (file)
@@ -189,6 +189,24 @@ not_found:
         return 0;   /* indicate we didn't find it */
 }
 
+int probe_sector_size_prefer_ioctl(int fd, uint32_t *ret) {
+        struct stat st;
+
+        assert(fd >= 0);
+        assert(ret);
+
+        /* Just like probe_sector_size(), but if we are looking at a block device, will use the already
+         * configured sector size rather than probing by contents */
+
+        if (fstat(fd, &st) < 0)
+                return -errno;
+
+        if (S_ISBLK(st.st_mode))
+                return blockdev_get_sector_size(fd, ret);
+
+        return probe_sector_size(fd, ret);
+}
+
 int probe_filesystem_full(
                 int fd,
                 const char *path,
index a69482d237147c7d7548d7b2975b11280ebdf6d1..143d6ff501e386ed3ccf3303ba0ad662d55569d7 100644 (file)
@@ -190,3 +190,4 @@ int verity_dissect_and_mount(int src_fd, const char *src, const char *dest, cons
 int dissect_fstype_ok(const char *fstype);
 
 int probe_sector_size(int fd, uint32_t *ret);
+int probe_sector_size_prefer_ioctl(int fd, uint32_t *ret);
index eeed1840aab93dd09edcb1a0522a0725f819460e..e88adb2d4338e07f239fb277e16f5e924b6d3a3b 100644 (file)
@@ -1,11 +1,17 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include "dissect-image.h"
 #include "fd-util.h"
 #include "fdisk-util.h"
 
 #if HAVE_LIBFDISK
 
-int fdisk_new_context_fd(int fd, bool read_only, struct fdisk_context **ret) {
+int fdisk_new_context_fd(
+                int fd,
+                bool read_only,
+                uint32_t sector_size,
+                struct fdisk_context **ret) {
+
         _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
         int r;
 
@@ -18,6 +24,18 @@ int fdisk_new_context_fd(int fd, bool read_only, struct fdisk_context **ret) {
         if (!c)
                 return -ENOMEM;
 
+        if (sector_size == UINT32_MAX) {
+                r = probe_sector_size_prefer_ioctl(fd, &sector_size);
+                if (r < 0)
+                        return r;
+        }
+
+        if (sector_size != 0) {
+                r = fdisk_save_user_sector_size(c, /* phy= */ 0, sector_size);
+                if (r < 0)
+                        return r;
+        }
+
         r = fdisk_assign_device(c, FORMAT_PROC_FD_PATH(fd), read_only);
         if (r < 0)
                 return r;
index 7f34a042ec52fe12062569e3367e5a1a44ea6ff4..48451329275bdf39e5da42d158aba09a15c13f6e 100644 (file)
@@ -14,7 +14,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_partition*, fdisk_unref_partition,
 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_parttype*, fdisk_unref_parttype, NULL);
 DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct fdisk_table*, fdisk_unref_table, NULL);
 
-int fdisk_new_context_fd(int fd, bool read_only, struct fdisk_context **ret);
+int fdisk_new_context_fd(int fd, bool read_only, uint32_t sector_size, struct fdisk_context **ret);
 
 int fdisk_partition_get_uuid_as_id128(struct fdisk_partition *p, sd_id128_t *ret);
 int fdisk_partition_get_type_as_id128(struct fdisk_partition *p, sd_id128_t *ret);