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