]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
growfs: port over to resize_fs() 14252/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 5 Dec 2019 09:15:49 +0000 (10:15 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 5 Dec 2019 09:15:49 +0000 (10:15 +0100)
src/partition/growfs.c
src/shared/resize-fs.c
src/shared/resize-fs.h

index 77bda6ea7fb02c51041d422bce39424a07f042ef..7e2452a5d15d17bc2e0f5e9958b6246cd3041cb4 100644 (file)
 #include "format-util.h"
 #include "log.h"
 #include "main-func.h"
-#include "missing_fs.h"
 #include "mountpoint-util.h"
 #include "parse-util.h"
-#include "path-util.h"
 #include "pretty-print.h"
-#include "stat-util.h"
-#include "strv.h"
-#include "util.h"
+#include "resize-fs.h"
 
 static const char *arg_target = NULL;
 static bool arg_dry_run = false;
 
-static int resize_ext4(const char *path, int mountfd, int devfd, uint64_t numblocks, uint64_t blocksize) {
-        assert((uint64_t) (int) blocksize == blocksize);
-
-        if (arg_dry_run)
-                return 0;
-
-        if (ioctl(mountfd, EXT4_IOC_RESIZE_FS, &numblocks) != 0)
-                return log_error_errno(errno, "Failed to resize \"%s\" to %"PRIu64" blocks (ext4): %m",
-                                       path, numblocks);
-
-        return 0;
-}
-
-static int resize_btrfs(const char *path, int mountfd, int devfd, uint64_t numblocks, uint64_t blocksize) {
-        struct btrfs_ioctl_vol_args args = {};
-        int r;
-
-        assert((uint64_t) (int) blocksize == blocksize);
-
-        /* https://bugzilla.kernel.org/show_bug.cgi?id=118111 */
-        if (numblocks * blocksize < 256*1024*1024) {
-                log_warning("%s: resizing of btrfs volumes smaller than 256M is not supported", path);
-                return -EOPNOTSUPP;
-        }
-
-        r = snprintf(args.name, sizeof(args.name), "%"PRIu64, numblocks * blocksize);
-        /* The buffer is large enough for any number to fit... */
-        assert((size_t) r < sizeof(args.name));
-
-        if (arg_dry_run)
-                return 0;
-
-        if (ioctl(mountfd, BTRFS_IOC_RESIZE, &args) != 0)
-                return log_error_errno(errno, "Failed to resize \"%s\" to %"PRIu64" blocks (btrfs): %m",
-                                       path, numblocks);
-
-        return 0;
-}
-
 #if HAVE_LIBCRYPTSETUP
 static int resize_crypt_luks_device(dev_t devno, const char *fstype, dev_t main_devno) {
         _cleanup_free_ char *devpath = NULL, *main_devpath = NULL;
@@ -160,7 +117,7 @@ static int maybe_resize_slave_device(const char *mountpath, dev_t main_devno) {
                 return resize_crypt_luks_device(devno, fstype, main_devno);
 #endif
 
-        log_debug("Don't know how to resize %s of type %s, ignoring", devpath, strnull(fstype));
+        log_debug("Don't know how to resize %s of type %s, ignoring.", devpath, strnull(fstype));
         return 0;
 }
 
@@ -235,11 +192,9 @@ static int parse_argv(int argc, char *argv[]) {
 static int run(int argc, char *argv[]) {
         _cleanup_close_ int mountfd = -1, devfd = -1;
         _cleanup_free_ char *devpath = NULL;
-        uint64_t size, numblocks;
+        uint64_t size, newsize;
         char fb[FORMAT_BYTES_MAX];
-        struct statfs sfs;
         dev_t devno;
-        int blocksize;
         int r;
 
         log_setup_service();
@@ -274,37 +229,24 @@ static int run(int argc, char *argv[]) {
         if (devfd < 0)
                 return log_error_errno(errno, "Failed to open \"%s\": %m", devpath);
 
-        if (ioctl(devfd, BLKBSZGET, &blocksize) != 0)
-                return log_error_errno(errno, "Failed to query block size of \"%s\": %m", devpath);
-
         if (ioctl(devfd, BLKGETSIZE64, &size) != 0)
                 return log_error_errno(errno, "Failed to query size of \"%s\": %m", devpath);
 
-        if (size % blocksize != 0)
-                log_notice("Partition size %"PRIu64" is not a multiple of the blocksize %d,"
-                           " ignoring %"PRIu64" bytes", size, blocksize, size % blocksize);
-
-        numblocks = size / blocksize;
-
-        if (fstatfs(mountfd, &sfs) < 0)
-                return log_error_errno(errno, "Failed to stat file system \"%s\": %m", arg_target);
-
-        switch(sfs.f_type) {
-        case EXT4_SUPER_MAGIC:
-                r = resize_ext4(arg_target, mountfd, devfd, numblocks, blocksize);
-                break;
-        case BTRFS_SUPER_MAGIC:
-                r = resize_btrfs(arg_target, mountfd, devfd, numblocks, blocksize);
-                break;
-        default:
-                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
-                                       "Don't know how to resize fs %llx on \"%s\"",
-                                       (long long unsigned) sfs.f_type, arg_target);
-        }
-        if (r > 0)
-                log_info("Successfully resized \"%s\" to %s bytes (%"PRIu64" blocks of %d bytes).",
-                         arg_target, format_bytes(fb, sizeof fb, size), numblocks, blocksize);
-        return r;
+        log_debug("Resizing \"%s\" to %"PRIu64" bytes...", arg_target, size);
+        r = resize_fs(mountfd, size, &newsize);
+        if (r < 0)
+                return log_error_errno(r, "Failed to resize \"%s\" to %"PRIu64" bytes: %m",
+                                       arg_target, size);
+        if (newsize == size)
+                log_info("Successfully resized \"%s\" to %s bytes.",
+                         arg_target,
+                         format_bytes(fb, sizeof fb, newsize));
+        else
+                log_info("Successfully resized \"%s\" to %s bytes (%"PRIu64" bytes lost due to blocksize).",
+                         arg_target,
+                         format_bytes(fb, sizeof fb, newsize),
+                         size - newsize);
+        return 0;
 }
 
 DEFINE_MAIN_FUNCTION(run);
index 9f33dd77d88a3404148c987b039d6776c5f6b9b7..5ed26a6c9237a8eededb428a62df047673fa12d6 100644 (file)
@@ -13,7 +13,7 @@
 #include "resize-fs.h"
 #include "stat-util.h"
 
-int resize_fs(int fd, uint64_t sz) {
+int resize_fs(int fd, uint64_t sz, uint64_t *ret_size) {
         struct statfs sfs;
         int r;
 
@@ -38,6 +38,9 @@ int resize_fs(int fd, uint64_t sz) {
                 if (ioctl(fd, EXT4_IOC_RESIZE_FS, &u) < 0)
                         return -errno;
 
+                if (ret_size)
+                        *ret_size = u * sfs.f_bsize;
+
         } else if (is_fs_type(&sfs, BTRFS_SUPER_MAGIC)) {
                 struct btrfs_ioctl_vol_args args = {};
 
@@ -49,12 +52,17 @@ int resize_fs(int fd, uint64_t sz) {
                 if (sz < BTRFS_MINIMAL_SIZE)
                         return -ERANGE;
 
+                sz -= sz % sfs.f_bsize;
+
                 r = snprintf(args.name, sizeof(args.name), "%" PRIu64, sz);
                 assert((size_t) r < sizeof(args.name));
 
                 if (ioctl(fd, BTRFS_IOC_RESIZE, &args) < 0)
                         return -errno;
 
+                if (ret_size)
+                        *ret_size = sz;
+
         } else if (is_fs_type(&sfs, XFS_SB_MAGIC)) {
                 xfs_fsop_geom_t geo;
                 xfs_growfs_data_t d;
@@ -73,6 +81,9 @@ int resize_fs(int fd, uint64_t sz) {
                 if (ioctl(fd, XFS_IOC_FSGROWFSDATA, &d) < 0)
                         return -errno;
 
+                if (ret_size)
+                        *ret_size = d.newblocks * geo.blocksize;
+
         } else
                 return -EOPNOTSUPP;
 
index b5441765289ec3ee982259adda711583441be3db..92b41d318c15ea4c974ea83aad0c6525a3581362 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "stat-util.h"
 
-int resize_fs(int fd, uint64_t sz);
+int resize_fs(int fd, uint64_t sz, uint64_t *ret_size);
 
 #define BTRFS_MINIMAL_SIZE (256U*1024U*1024U)
 #define XFS_MINIMAL_SIZE (14U*1024U*1024U)