From: Gibeom Gwon Date: Wed, 19 Oct 2022 09:12:29 +0000 (+0900) Subject: homework: resize to maximum disk space if disk size is not specified X-Git-Tag: v254-rc1~177 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5bfc4de6343905743d973834554b49cb60183481;p=thirdparty%2Fsystemd.git homework: resize to maximum disk space if disk size is not specified If the backing storage is LUKS2 on a block device, auto resize mode is enabled, and disk size is not specified, resize the partition to the maximum expandable size. Fixes: #22255, #23967 --- diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index 23596998013..659a4826ee4 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -2749,6 +2749,43 @@ static int prepare_resize_partition( return 1; } +static int get_maximum_partition_size( + int fd, + struct fdisk_partition *p, + uint64_t *ret_maximum_partition_size) { + + _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL; + uint64_t start_lba, start, last_lba, end; + int r; + + assert(fd >= 0); + assert(p); + assert(ret_maximum_partition_size); + + c = fdisk_new_context(); + if (!c) + return log_oom(); + + r = fdisk_assign_device(c, FORMAT_PROC_FD_PATH(fd), 0); + if (r < 0) + return log_error_errno(r, "Failed to open device: %m"); + + start_lba = fdisk_partition_get_start(p); + assert(start_lba <= UINT64_MAX/512); + start = start_lba * 512; + + last_lba = fdisk_get_last_lba(c); /* One sector before boundary where usable space ends */ + assert(last_lba < UINT64_MAX/512); + end = DISK_SIZE_ROUND_DOWN((last_lba + 1) * 512); /* Round down to multiple of 4K */ + + if (start > end) + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Last LBA is before partition start."); + + *ret_maximum_partition_size = DISK_SIZE_ROUND_DOWN(end - start); + + return 1; +} + static int ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *userdata) { char *result; @@ -3214,6 +3251,17 @@ int home_resize_luks( setup->partition_offset + setup->partition_size > old_image_size) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Old partition doesn't fit in backing storage, refusing."); + /* Get target partition information in here for new_partition_size calculation */ + r = prepare_resize_partition( + image_fd, + setup->partition_offset, + setup->partition_size, + &disk_uuid, + &table, + &partition); + if (r < 0) + return r; + if (S_ISREG(st.st_mode)) { uint64_t partition_table_extra, largest_size; @@ -3236,9 +3284,13 @@ int home_resize_luks( new_partition_size = 0; intention = INTENTION_SHRINK; } else { - uint64_t new_partition_size_rounded; + uint64_t new_partition_size_rounded = DISK_SIZE_ROUND_DOWN(h->disk_size); - new_partition_size_rounded = DISK_SIZE_ROUND_DOWN(h->disk_size); + if (h->disk_size == UINT64_MAX && partition) { + r = get_maximum_partition_size(image_fd, partition, &new_partition_size_rounded); + if (r < 0) + return r; + } if (setup->partition_size >= new_partition_size_rounded && setup->partition_size <= h->disk_size) { @@ -3332,16 +3384,6 @@ int home_resize_luks( special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), FORMAT_BYTES(new_fs_size)); - r = prepare_resize_partition( - image_fd, - setup->partition_offset, - setup->partition_size, - &disk_uuid, - &table, - &partition); - if (r < 0) - return r; - if (new_fs_size > old_fs_size) { /* → Grow */ if (S_ISREG(st.st_mode)) {