]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
homework: add auto-shrink/auto-grow
authorLennart Poettering <lennart@poettering.net>
Fri, 29 Oct 2021 08:15:00 +0000 (10:15 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 23 Nov 2021 07:04:10 +0000 (08:04 +0100)
src/home/homework-luks.c
src/home/homework-luks.h
src/home/homework.c

index 57b41d26b831ef409b38d295c186ed1d51dde860..134df7b945705137fba21237076f3641862d3f7e 100644 (file)
@@ -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;
+}
index 796a883831fc29e395dcca4747e732ce9605c590..afbe8d490945be9f6d25e7b0e5097f639c944e5b 100644 (file)
@@ -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;
 
index 5907015e2b67a9929396bf2df4266a18de14fe50..351c31b73e73ff4be1c9204550fbe7776b68e046 100644 (file)
@@ -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 */