diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-03-19 10:36:48 +0100 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-03-23 01:35:30 +0100 |
commit | b132bca9f6dc6ed4965c0ac48bac90e9fc443a9e (patch) | |
tree | 30ace7ab16967066cf0a29ba1354e68e09ab22cb | |
parent | 85e45e8722cd2732c4a26f535ddc6472dd1fb0a6 (diff) | |
download | systemd-b132bca9f6dc6ed4965c0ac48bac90e9fc443a9e.tar.gz |
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)
(cherry picked from commit f9b3afae96c72564cd4cd766555845f17e3c12a9)
-rw-r--r-- | src/partition/repart.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/partition/repart.c b/src/partition/repart.c index 6db413ed5e..6d7e51938a 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -3860,6 +3860,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; @@ -3912,6 +3946,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 @@ -3925,6 +3963,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 |