1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-28 07:21:32 +03:00

homework: rework how we disassemble a home dir in home_deactivate()

Let's first move the home dir to a new mount point that is only visible
in our own private namespace. Then, do FITRIM and stuff there, so that
we know the regular userspace can't interfere with that, and we know
that the home fs is not used anymore.

(This will become even more important once we add auto-grow/auto-shrink
for home dirs)
This commit is contained in:
Lennart Poettering 2021-10-29 09:44:31 +02:00
parent e2f8c1124d
commit a71a0693cd
3 changed files with 44 additions and 25 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
/* 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;