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;
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;
}
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);
}
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);
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;
- /* Sync explicitly, so that the drop caches logic below can work as documented */
- r = syncfs_path(AT_FDCWD, user_record_home_directory(h));
+ r = mount_nofollow_verbose(LOG_ERR, user_record_home_directory(h), HOME_RUNTIME_WORK_DIR, NULL, MS_BIND, NULL);
if (r < 0)
- log_debug_errno(r, "Failed to synchronize home directory, ignoring: %m");
+ 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 */
+ 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;
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;