Zbigniew Jędrzejewski-Szmek 6384ab
From f9b3afae96c72564cd4cd766555845f17e3c12a9 Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 6384ab
From: Lennart Poettering <lennart@poettering.net>
Zbigniew Jędrzejewski-Szmek 6384ab
Date: Fri, 19 Mar 2021 10:36:48 +0100
Zbigniew Jędrzejewski-Szmek 6384ab
Subject: [PATCH] repart: make sure to grow partition table after growing
Zbigniew Jędrzejewski-Szmek 6384ab
 backing loopback file
Zbigniew Jędrzejewski-Szmek 6384ab
Zbigniew Jędrzejewski-Szmek 6384ab
This fixes the --size= switch, i.e. where we grow a disk image: after
Zbigniew Jędrzejewski-Szmek 6384ab
growing it we need to expand the partition table so that its idea of the
Zbigniew Jędrzejewski-Szmek 6384ab
the medium size matches the new reality. Otherwise our disk size
Zbigniew Jędrzejewski-Szmek 6384ab
calculations in the subsequent steps might still use the original
Zbigniew Jędrzejewski-Szmek 6384ab
ungrown size.
Zbigniew Jędrzejewski-Szmek 6384ab
Zbigniew Jędrzejewski-Szmek 6384ab
(This used to work, I guess this was borked when libfdisk learnt the
Zbigniew Jędrzejewski-Szmek 6384ab
concept of "minimized" partition tables)
Zbigniew Jędrzejewski-Szmek 6384ab
---
Zbigniew Jędrzejewski-Szmek 6384ab
 src/partition/repart.c | 42 ++++++++++++++++++++++++++++++++++++++++++
Zbigniew Jędrzejewski-Szmek 6384ab
 1 file changed, 42 insertions(+)
Zbigniew Jędrzejewski-Szmek 6384ab
Zbigniew Jędrzejewski-Szmek 6384ab
diff --git a/src/partition/repart.c b/src/partition/repart.c
Zbigniew Jędrzejewski-Szmek 6384ab
index be16f5a067b..7b6201efa83 100644
Zbigniew Jędrzejewski-Szmek 6384ab
--- a/src/partition/repart.c
Zbigniew Jędrzejewski-Szmek 6384ab
+++ b/src/partition/repart.c
Zbigniew Jędrzejewski-Szmek 6384ab
@@ -3977,6 +3977,40 @@ static int find_root(char **ret, int *ret_fd) {
Zbigniew Jędrzejewski-Szmek 6384ab
         return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "Failed to discover root block device.");
Zbigniew Jędrzejewski-Szmek 6384ab
 }
Zbigniew Jędrzejewski-Szmek 6384ab
 
Zbigniew Jędrzejewski-Szmek 6384ab
+static int resize_pt(int fd) {
Zbigniew Jędrzejewski-Szmek 6384ab
+        char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
Zbigniew Jędrzejewski-Szmek 6384ab
+        _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
Zbigniew Jędrzejewski-Szmek 6384ab
+        int r;
Zbigniew Jędrzejewski-Szmek 6384ab
+
Zbigniew Jędrzejewski-Szmek 6384ab
+        /* After resizing the backing file we need to resize the partition table itself too, so that it takes
Zbigniew Jędrzejewski-Szmek 6384ab
+         * possession of the enlarged backing file. For this it suffices to open the device with libfdisk and
Zbigniew Jędrzejewski-Szmek 6384ab
+         * immediately write it again, with no changes. */
Zbigniew Jędrzejewski-Szmek 6384ab
+
Zbigniew Jędrzejewski-Szmek 6384ab
+        c = fdisk_new_context();
Zbigniew Jędrzejewski-Szmek 6384ab
+        if (!c)
Zbigniew Jędrzejewski-Szmek 6384ab
+                return log_oom();
Zbigniew Jędrzejewski-Szmek 6384ab
+
Zbigniew Jędrzejewski-Szmek 6384ab
+        xsprintf(procfs_path, "/proc/self/fd/%i", fd);
Zbigniew Jędrzejewski-Szmek 6384ab
+        r = fdisk_assign_device(c, procfs_path, 0);
Zbigniew Jędrzejewski-Szmek 6384ab
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 6384ab
+                return log_error_errno(r, "Failed to open device '%s': %m", procfs_path);
Zbigniew Jędrzejewski-Szmek 6384ab
+
Zbigniew Jędrzejewski-Szmek 6384ab
+        r = fdisk_has_label(c);
Zbigniew Jędrzejewski-Szmek 6384ab
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 6384ab
+                return log_error_errno(r, "Failed to determine whether disk '%s' has a disk label: %m", procfs_path);
Zbigniew Jędrzejewski-Szmek 6384ab
+        if (r == 0) {
Zbigniew Jędrzejewski-Szmek 6384ab
+                log_debug("Not resizing partition table, as there currently is none.");
Zbigniew Jędrzejewski-Szmek 6384ab
+                return 0;
Zbigniew Jędrzejewski-Szmek 6384ab
+        }
Zbigniew Jędrzejewski-Szmek 6384ab
+
Zbigniew Jędrzejewski-Szmek 6384ab
+        r = fdisk_write_disklabel(c);
Zbigniew Jędrzejewski-Szmek 6384ab
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 6384ab
+                return log_error_errno(r, "Failed to write resized partition table: %m");
Zbigniew Jędrzejewski-Szmek 6384ab
+
Zbigniew Jędrzejewski-Szmek 6384ab
+        log_info("Resized partition table.");
Zbigniew Jędrzejewski-Szmek 6384ab
+        return 1;
Zbigniew Jędrzejewski-Szmek 6384ab
+}
Zbigniew Jędrzejewski-Szmek 6384ab
+
Zbigniew Jędrzejewski-Szmek 6384ab
 static int resize_backing_fd(const char *node, int *fd) {
Zbigniew Jędrzejewski-Szmek 6384ab
         char buf1[FORMAT_BYTES_MAX], buf2[FORMAT_BYTES_MAX];
Zbigniew Jędrzejewski-Szmek 6384ab
         _cleanup_close_ int writable_fd = -1;
Zbigniew Jędrzejewski-Szmek 6384ab
@@ -4029,6 +4063,10 @@ static int resize_backing_fd(const char *node, int *fd) {
Zbigniew Jędrzejewski-Szmek 6384ab
                         /* Fallback to truncation, if fallocate() is not supported. */
Zbigniew Jędrzejewski-Szmek 6384ab
                         log_debug("Backing file system does not support fallocate(), falling back to ftruncate().");
Zbigniew Jędrzejewski-Szmek 6384ab
                 } else {
Zbigniew Jędrzejewski-Szmek 6384ab
+                        r = resize_pt(writable_fd);
Zbigniew Jędrzejewski-Szmek 6384ab
+                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 6384ab
+                                return r;
Zbigniew Jędrzejewski-Szmek 6384ab
+
Zbigniew Jędrzejewski-Szmek 6384ab
                         if (st.st_size == 0) /* Likely regular file just created by us */
Zbigniew Jędrzejewski-Szmek 6384ab
                                 log_info("Allocated %s for '%s'.", buf2, node);
Zbigniew Jędrzejewski-Szmek 6384ab
                         else
Zbigniew Jędrzejewski-Szmek 6384ab
@@ -4042,6 +4080,10 @@ static int resize_backing_fd(const char *node, int *fd) {
Zbigniew Jędrzejewski-Szmek 6384ab
                 return log_error_errno(errno, "Failed to grow '%s' from %s to %s by truncation: %m",
Zbigniew Jędrzejewski-Szmek 6384ab
                                        node, buf1, buf2);
Zbigniew Jędrzejewski-Szmek 6384ab
 
Zbigniew Jędrzejewski-Szmek 6384ab
+        r = resize_pt(writable_fd);
Zbigniew Jędrzejewski-Szmek 6384ab
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 6384ab
+                return r;
Zbigniew Jędrzejewski-Szmek 6384ab
+
Zbigniew Jędrzejewski-Szmek 6384ab
         if (st.st_size == 0) /* Likely regular file just created by us */
Zbigniew Jędrzejewski-Szmek 6384ab
                 log_info("Sized '%s' to %s.", node, buf2);
Zbigniew Jędrzejewski-Szmek 6384ab
         else