Skip to content

Commit

Permalink
homework: resize to maximum disk space if disk size is not specified
Browse files Browse the repository at this point in the history
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: systemd#22255, systemd#23967
  • Loading branch information
gibeom-gwon committed Oct 19, 2022
1 parent b7a279f commit 04000f0
Showing 1 changed file with 57 additions and 11 deletions.
68 changes: 57 additions & 11 deletions src/home/homework-luks.c
Expand Up @@ -2724,6 +2724,46 @@ 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;
_cleanup_free_ char *path = NULL;
uint64_t start_lba, start, last_lba, end;
int r;

assert(fd >= 0);
assert(ret_maximum_partition_size);

c = fdisk_new_context();
if (!c)
return log_oom();

if (asprintf(&path, "/proc/self/fd/%i", fd) < 0)
return log_oom();

r = fdisk_assign_device(c, path, 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;

if (start == UINT64_MAX)
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Overflow while rounding up start LBA.");

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 */

*ret_maximum_partition_size = end - start;

return 1;
}

static int ask_cb(struct fdisk_context *c, struct fdisk_ask *ask, void *userdata) {
char *result;

Expand Down Expand Up @@ -3192,6 +3232,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;

Expand All @@ -3216,7 +3267,12 @@ int home_resize_luks(
} else {
uint64_t new_partition_size_rounded;

new_partition_size_rounded = DISK_SIZE_ROUND_DOWN(h->disk_size);
if (h->disk_size == UINT64_MAX) {
r = get_maximum_partition_size(image_fd, partition, &new_partition_size_rounded);
if (r < 0)
return r;
} else
new_partition_size_rounded = DISK_SIZE_ROUND_DOWN(h->disk_size);

if (setup->partition_size >= new_partition_size_rounded &&
setup->partition_size <= h->disk_size) {
Expand Down Expand Up @@ -3310,16 +3366,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)) {
Expand Down

0 comments on commit 04000f0

Please sign in to comment.