diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index ae4f8a8e32..7275b231cc 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -1020,16 +1020,6 @@ int run_fitrim(int root_fd) { return 1; } -int run_fitrim_by_path(const char *root_path) { - _cleanup_close_ int root_fd = -1; - - root_fd = open(root_path, O_RDONLY|O_DIRECTORY|O_CLOEXEC); - if (root_fd < 0) - return log_error_errno(errno, "Failed to open file system '%s' for trimming: %m", root_path); - - return run_fitrim(root_fd); -} - int run_fallocate(int backing_fd, const struct stat *st) { struct stat stbuf; @@ -1528,15 +1518,17 @@ int home_deactivate_luks(UserRecord *h, HomeSetup *setup) { return we_detached; } -int home_trim_luks(UserRecord *h) { +int home_trim_luks(UserRecord *h, HomeSetup *setup) { assert(h); + assert(setup); + assert(setup->root_fd >= 0); if (!user_record_luks_offline_discard(h)) { log_debug("Not trimming on logout."); return 0; } - (void) run_fitrim_by_path(user_record_home_directory(h)); + (void) run_fitrim(setup->root_fd); return 0; } diff --git a/src/home/homework-luks.h b/src/home/homework-luks.h index f8af66e083..f6ec11c2e6 100644 --- a/src/home/homework-luks.h +++ b/src/home/homework-luks.h @@ -9,7 +9,7 @@ int home_setup_luks(UserRecord *h, HomeSetupFlags flags, const char *force_image int home_activate_luks(UserRecord *h, HomeSetup *setup, PasswordCache *cache, UserRecord **ret_home); int home_deactivate_luks(UserRecord *h, HomeSetup *setup); -int home_trim_luks(UserRecord *h); +int home_trim_luks(UserRecord *h, HomeSetup *setup); int home_store_header_identity_luks(UserRecord *h, HomeSetup *setup, UserRecord *old_home); @@ -39,7 +39,6 @@ static inline uint64_t luks_volume_key_size_convert(struct crypt_device *cd) { } int run_fitrim(int root_fd); -int run_fitrim_by_path(const char *root_path); int run_fallocate(int backing_fd, const struct stat *st); int run_fallocate_by_path(const char *backing_path); int run_mark_dirty(int fd, bool b); diff --git a/src/home/homework.c b/src/home/homework.c index 65066a5156..94cfd41780 100644 --- a/src/home/homework.c +++ b/src/home/homework.c @@ -924,21 +924,47 @@ static int home_deactivate(UserRecord *h, bool force) { if (r < 0) return r; if (r == USER_TEST_MOUNTED) { - if (user_record_storage(h) == USER_LUKS) { - r = home_trim_luks(h); - if (r < 0) - return r; - } + /* Before we do anything, let's move the home mount away. */ + r = home_unshare_and_mkdir(); + if (r < 0) + return r; + + r = mount_nofollow_verbose(LOG_ERR, user_record_home_directory(h), HOME_RUNTIME_WORK_DIR, NULL, MS_BIND, NULL); + if (r < 0) + return r; + + setup.undo_mount = true; /* remember to unmount the new bind mount from HOME_RUNTIME_WORK_DIR */ + + /* Let's explicitly open the new root fs, using the moved path */ + setup.root_fd = open(HOME_RUNTIME_WORK_DIR, O_RDONLY|O_DIRECTORY|O_CLOEXEC); + if (setup.root_fd < 0) + return log_error_errno(errno, "Failed to open moved home directory: %m"); + + /* Now get rid of the home at its original place (we only keep the bind mount we created above) */ + r = umount_verbose(LOG_ERR, user_record_home_directory(h), UMOUNT_NOFOLLOW | (force ? MNT_FORCE|MNT_DETACH : 0)); + if (r < 0) + return r; + + if (user_record_storage(h) == USER_LUKS) + (void) home_trim_luks(h, &setup); /* Sync explicitly, so that the drop caches logic below can work as documented */ - r = syncfs_path(AT_FDCWD, user_record_home_directory(h)); - if (r < 0) - log_debug_errno(r, "Failed to synchronize home directory, ignoring: %m"); + if (syncfs(setup.root_fd) < 0) + log_debug_errno(errno, "Failed to synchronize home directory, ignoring: %m"); else log_info("Syncing completed."); - if (umount2(user_record_home_directory(h), UMOUNT_NOFOLLOW | (force ? MNT_FORCE|MNT_DETACH : 0)) < 0) - return log_error_errno(errno, "Failed to unmount %s: %m", user_record_home_directory(h)); + setup.root_fd = safe_close(setup.root_fd); + + /* Now get rid of the bind mount, too */ + r = umount_verbose(LOG_ERR, HOME_RUNTIME_WORK_DIR, UMOUNT_NOFOLLOW | (force ? MNT_FORCE|MNT_DETACH : 0)); + if (r < 0) + return r; + + setup.undo_mount = false; /* Remember that the bind mount doesn't need to be unmounted anymore */ + + if (user_record_drop_caches(h)) + setup.do_drop_caches = true; log_info("Unmounting completed."); done = true; @@ -956,8 +982,10 @@ static int home_deactivate(UserRecord *h, bool force) { if (!done) return log_error_errno(SYNTHETIC_ERRNO(ENOEXEC), "Home is not active."); - if (user_record_drop_caches(h)) + if (setup.do_drop_caches) { + setup.do_drop_caches = false; drop_caches_now(); + } log_info("Everything completed."); return 0;