From: Lennart Poettering Date: Fri, 29 Oct 2021 08:15:00 +0000 (+0200) Subject: homework: add auto-shrink/auto-grow X-Git-Tag: v250-rc1~183^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=26191000383d79dd27c95748f668c4e27a37c799;p=thirdparty%2Fsystemd.git homework: add auto-shrink/auto-grow --- diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index 57b41d26b83..134df7b9457 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -1402,6 +1402,42 @@ static void print_size_summary(uint64_t host_size, uint64_t encrypted_size, cons FORMAT_BYTES((uint64_t) sfs->f_bfree * (uint64_t) sfs->f_frsize)); } +static int home_auto_grow_luks( + UserRecord *h, + HomeSetup *setup, + PasswordCache *cache) { + + struct statfs sfs; + + assert(h); + assert(setup); + + if (!IN_SET(user_record_auto_resize_mode(h), AUTO_RESIZE_GROW, AUTO_RESIZE_SHRINK_AND_GROW)) + return 0; + + assert(setup->root_fd >= 0); + + if (fstatfs(setup->root_fd, &sfs) < 0) + return log_error_errno(errno, "Failed to statfs home directory: %m"); + + if (!fs_can_online_shrink_and_grow(sfs.f_type)) { + log_debug("Not auto-grow file system, since selected file system cannot do both online shrink and grow."); + return 0; + } + + log_debug("Initiating auto-grow..."); + + return home_resize_luks( + h, + HOME_SETUP_ALREADY_ACTIVATED| + HOME_SETUP_RESIZE_DONT_SYNC_IDENTITIES| + HOME_SETUP_RESIZE_DONT_SHRINK| + HOME_SETUP_RESIZE_DONT_UNDO, + setup, + cache, + NULL); +} + int home_activate_luks( UserRecord *h, HomeSetup *setup, @@ -1442,6 +1478,10 @@ int home_activate_luks( if (r < 0) return r; + r = home_auto_grow_luks(h, setup, cache); + if (r < 0) + return r; + r = block_get_size_by_fd(setup->loop->fd, &host_size); if (r < 0) return log_error_errno(r, "Failed to get loopback block device size: %m"); @@ -1484,7 +1524,7 @@ int home_activate_luks( setup->do_mark_clean = false; setup->do_drop_caches = false; - log_info("Everything completed."); + log_info("Activation completed."); print_size_summary(host_size, encrypted_size, &sfs); @@ -1498,7 +1538,6 @@ int home_deactivate_luks(UserRecord *h, HomeSetup *setup) { assert(h); assert(setup); - assert(!setup->crypt_device); /* Note that the DM device and loopback device are set to auto-detach, hence strictly speaking we * don't have to explicitly have to detach them. However, we do that nonetheless (in case of the DM @@ -1506,13 +1545,17 @@ int home_deactivate_luks(UserRecord *h, HomeSetup *setup) { * don't bother about the loopback device because unlike the DM device it doesn't have a fixed * name. */ - r = acquire_open_luks_device(h, setup, /* graceful= */ true); - if (r < 0) - return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", setup->dm_name); - if (r == 0) { - log_debug("LUKS device %s has already been detached.", setup->dm_name); - we_detached = false; - } else { + if (!setup->crypt_device) { + r = acquire_open_luks_device(h, setup, /* graceful= */ true); + if (r < 0) + return log_error_errno(r, "Failed to initialize cryptsetup context for %s: %m", setup->dm_name); + if (r == 0) { + log_debug("LUKS device %s has already been detached.", setup->dm_name); + we_detached = false; + } + } + + if (setup->crypt_device) { log_info("Discovered used LUKS device %s.", setup->dm_node); cryptsetup_enable_logging(setup->crypt_device); @@ -3396,7 +3439,7 @@ int home_resize_luks( return r; } - log_info("Everything completed."); + log_info("Resizing completed."); print_size_summary(new_image_size, new_fs_size, &sfs); @@ -3718,3 +3761,39 @@ int wait_for_block_device_gone(HomeSetup *setup, usec_t timeout_usec) { log_debug("Successfully waited until device %s disappeared.", setup->dm_node); return 0; } + +int home_auto_shrink_luks(UserRecord *h, HomeSetup *setup, PasswordCache *cache) { + struct statfs sfs; + int r; + + assert(h); + assert(user_record_storage(h) == USER_LUKS); + assert(setup); + assert(setup->root_fd >= 0); + + if (user_record_auto_resize_mode(h) != AUTO_RESIZE_SHRINK_AND_GROW) + return 0; + + if (fstatfs(setup->root_fd, &sfs) < 0) + return log_error_errno(errno, "Failed to statfs home directory: %m"); + + if (!fs_can_online_shrink_and_grow(sfs.f_type)) { + log_debug("Not auto-shrinking file system, since selected file system cannot do both online shrink and grow."); + return 0; + } + + r = home_resize_luks( + h, + HOME_SETUP_ALREADY_ACTIVATED| + HOME_SETUP_RESIZE_DONT_SYNC_IDENTITIES| + HOME_SETUP_RESIZE_MINIMIZE| + HOME_SETUP_RESIZE_DONT_GROW| + HOME_SETUP_RESIZE_DONT_UNDO, + setup, + cache, + NULL); + if (r < 0) + return r; + + return 1; +} diff --git a/src/home/homework-luks.h b/src/home/homework-luks.h index 796a883831f..afbe8d49094 100644 --- a/src/home/homework-luks.h +++ b/src/home/homework-luks.h @@ -24,6 +24,8 @@ int home_passwd_luks(UserRecord *h, HomeSetup *setup, const PasswordCache *cache int home_lock_luks(UserRecord *h, HomeSetup *setup); int home_unlock_luks(UserRecord *h, HomeSetup *setup, const PasswordCache *cache); +int home_auto_shrink_luks(UserRecord *h, HomeSetup *setup, PasswordCache *cache); + static inline uint64_t luks_volume_key_size_convert(struct crypt_device *cd) { int k; diff --git a/src/home/homework.c b/src/home/homework.c index 5907015e2b6..351c31b73e7 100644 --- a/src/home/homework.c +++ b/src/home/homework.c @@ -908,6 +908,7 @@ static int home_activate(UserRecord *h, UserRecord **ret_home) { static int home_deactivate(UserRecord *h, bool force) { _cleanup_(home_setup_done) HomeSetup setup = HOME_SETUP_INIT; + _cleanup_(password_cache_free) PasswordCache cache = {}; bool done = false; int r; @@ -952,6 +953,9 @@ static int home_deactivate(UserRecord *h, bool force) { else log_info("Syncing completed."); + if (user_record_storage(h) == USER_LUKS) + (void) home_auto_shrink_luks(h, &setup, &cache); + setup.root_fd = safe_close(setup.root_fd); /* Now get rid of the bind mount, too */