diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-10-29 10:15:00 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-11-23 08:04:10 +0100 |
commit | 26191000383d79dd27c95748f668c4e27a37c799 (patch) | |
tree | a2ba97d87639163e1523bcdccc7a588e3f18a5f9 /src/home | |
parent | ab3b6fcb4016afbc40d11844b3467a3579705e14 (diff) | |
download | systemd-26191000383d79dd27c95748f668c4e27a37c799.tar.gz |
homework: add auto-shrink/auto-grow
Diffstat (limited to 'src/home')
-rw-r--r-- | src/home/homework-luks.c | 99 | ||||
-rw-r--r-- | src/home/homework-luks.h | 2 | ||||
-rw-r--r-- | src/home/homework.c | 4 |
3 files changed, 95 insertions, 10 deletions
diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index 57b41d26b8..134df7b945 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 796a883831..afbe8d4909 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 5907015e2b..351c31b73e 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 */ |