From: Lennart Poettering Date: Fri, 19 Mar 2021 09:36:48 +0000 (+0100) Subject: repart: make sure to grow partition table after growing backing loopback file X-Git-Tag: v248-2~48 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f9b3afae96c72564cd4cd766555845f17e3c12a9;p=thirdparty%2Fsystemd.git 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) --- 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