From e5250faba921c84f191a11bd6fc619626fe730b2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 21 Nov 2017 18:56:52 +0100 Subject: [PATCH] growfs: add support for resizing encrypted partitions --- src/partition/growfs.c | 81 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/partition/growfs.c b/src/partition/growfs.c index 6fba06e02..816aad394 100644 --- a/src/partition/growfs.c +++ b/src/partition/growfs.c @@ -27,7 +27,9 @@ #include #include +#include "crypt-util.h" #include "device-nodes.h" +#include "dissect-image.h" #include "escape.h" #include "fd-util.h" #include "format-util.h" @@ -63,6 +65,81 @@ static int resize_btrfs(int mountfd, int devfd, uint64_t numblocks, uint64_t blo return 0; } +static int resize_crypt_luks_device(dev_t devno, const char *fstype, dev_t main_devno) { + char devpath[DEV_NUM_PATH_MAX], main_devpath[DEV_NUM_PATH_MAX]; + _cleanup_close_ int main_devfd = -1; + _cleanup_(crypt_freep) struct crypt_device *cd = NULL; + uint64_t size; + int r; + + xsprintf_dev_num_path(main_devpath, "block", main_devno); + main_devfd = open(main_devpath, O_RDONLY|O_CLOEXEC); + if (main_devfd < 0) + return log_error_errno(errno, "Failed to open \"%s\": %m", main_devpath); + + if (ioctl(main_devfd, BLKGETSIZE64, &size) != 0) + return log_error_errno(errno, "Failed to query size of \"%s\" (before resize): %m", + main_devpath); + + log_debug("%s is %"PRIu64" bytes", main_devpath, size); + + xsprintf_dev_num_path(devpath, "block", devno); + r = crypt_init(&cd, devpath); + if (r < 0) + return log_error_errno(r, "crypt_init(\"%s\") failed: %m", devpath); + + crypt_set_log_callback(cd, cryptsetup_log_glue, NULL); + + r = crypt_load(cd, CRYPT_LUKS, NULL); + if (r < 0) + return log_debug_errno(r, "Failed to load LUKS metadata for %s: %m", devpath); + + r = crypt_resize(cd, main_devpath, 0); + if (r < 0) + return log_error_errno(r, "crypt_resize() of %s failed: %m", devpath); + + if (ioctl(main_devfd, BLKGETSIZE64, &size) != 0) + log_warning_errno(errno, "Failed to query size of \"%s\" (after resize): %m", + devpath); + else + log_debug("%s is now %"PRIu64" bytes", main_devpath, size); + + return 1; +} + +static int maybe_resize_slave_device(const char *mountpath, dev_t main_devno) { + dev_t devno; + char devpath[DEV_NUM_PATH_MAX]; + _cleanup_free_ char *fstype = NULL; + int r; + + crypt_set_log_callback(NULL, cryptsetup_log_glue, NULL); + crypt_set_debug_level(1); + + r = get_block_device_harder(mountpath, &devno); + if (r < 0) + return log_error_errno(r, "Failed to determine underlying block device of \"%s\": %m", + mountpath); + + log_debug("Underlying device %d:%d, main dev %d:%d, %s", + major(devno), minor(devno), + major(main_devno), minor(main_devno), + devno == main_devno ? "same" : "different"); + if (devno == main_devno) + return 0; + + xsprintf_dev_num_path(devpath, "block", devno); + r = probe_filesystem(devpath, &fstype); + if (r < 0) + return log_warning_errno(r, "Failed to probe \"%s\": %m", devpath); + + if (streq_ptr(fstype, "crypto_LUKS")) + return resize_crypt_luks_device(devno, fstype, main_devno); + + log_debug("Don't know how to resize %s of type %s, ignoring", devpath, strnull(fstype)); + return 0; +} + int main(int argc, char *argv[]) { dev_t devno; _cleanup_close_ int mountfd = -1, devfd = -1; @@ -97,6 +174,10 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } + r = maybe_resize_slave_device(argv[1], devno); + if (r < 0) + return EXIT_FAILURE; + mountfd = open(argv[1], O_RDONLY|O_CLOEXEC); if (mountfd < 0) { log_error_errno(errno, "Failed to open \"%s\": %m", argv[1]); -- 2.30.2