From: "Maxim V. Patlasov" <mpatla...@parallels.com>

This is a port of
da0fae4 ext4: Teach the fs where the balloon inode is

This adds the balloon_ino mount option and stores the inode
pointer on the in-memory super block object.

This is not good solution - in a perfect world the balloon
inode should be hidden (like the journalling one), but this
requires
a) reserve its number in the mainline sources;)
b) teach e2fsprogs not to treat one as orphaned

Until (if) we do this it's better to keep this as a regular
file on the disk.

(cherry picked from vz7 commit 54ac06cf671c68a3778e9f939ba3794fd6a51470)
Signed-off-by: Konstantin Khorenko <khore...@virtuozzo.com>
Signed-off-by: Kirill Tkhai <ktk...@virtuozzo.com>

+++
ext4: Fix placement of balloon ino option

Signed-off-by: Konstantin Khorenko <khore...@virtuozzo.com>

Rebase from 5.14.0-42.el9 to 5.14.0-70.13.1.el9 (RHEL9 RTM):
 - the patch has been rewritten due to ext4 API change to "fs_context"

Signed-off-by: Konstantin Khorenko <khore...@virtuozzo.com>

Feature: fs/ext4: fast online shrink support
---
 fs/ext4/ext4.h  |  2 ++
 fs/ext4/super.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index e65344cb56ba..807cd5cbe379 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1649,6 +1649,8 @@ struct ext4_sb_info {
        atomic_t s_mb_discarded;
        atomic_t s_lock_busy;
 
+       struct inode *s_balloon_ino;
+
        /* locality groups */
        struct ext4_locality_group __percpu *s_locality_groups;
 
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index b7e9492cb33d..c5aef54cc07b 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1594,6 +1594,7 @@ enum {
        Opt_max_dir_size_kb, Opt_nojournal_checksum, Opt_nombcache,
        Opt_no_prefetch_block_bitmaps, Opt_mb_optimize_scan,
        Opt_errors, Opt_data, Opt_data_err, Opt_jqfmt, Opt_dax_type,
+       Opt_balloon_ino,
 #ifdef CONFIG_EXT4_DEBUG
        Opt_fc_debug_max_replay, Opt_fc_debug_force
 #endif
@@ -1742,6 +1743,7 @@ static const struct fs_parameter_spec ext4_param_specs[] 
= {
        fsparam_flag    ("reservation",         Opt_removed),   /* mount option 
from ext2/3 */
        fsparam_flag    ("noreservation",       Opt_removed),   /* mount option 
from ext2/3 */
        fsparam_u32     ("journal",             Opt_removed),   /* mount option 
from ext2/3 */
+       fsparam_u32     ("balloon_ino",         Opt_balloon_ino),
        {}
 };
 
@@ -1842,6 +1844,7 @@ static const struct mount_opts {
        {Opt_fc_debug_force, EXT4_MOUNT2_JOURNAL_FAST_COMMIT,
         MOPT_SET | MOPT_2 | MOPT_EXT4_ONLY},
 #endif
+       {Opt_balloon_ino, 0, 0},
        {Opt_err, 0, 0}
 };
 
@@ -1887,6 +1890,7 @@ ext4_sb_read_encoding(const struct ext4_super_block *es)
 #define EXT4_SPEC_s_fc_debug_max_replay                (1 << 17)
 #define EXT4_SPEC_s_sb_block                   (1 << 18)
 #define EXT4_SPEC_mb_optimize_scan             (1 << 19)
+#define EXT4_SPEC_balloon_ino                  (1 << 20)
 
 struct ext4_fs_context {
        char            *s_qf_names[EXT4_MAXQUOTAS];
@@ -1912,6 +1916,7 @@ struct ext4_fs_context {
        unsigned int    mask_s_mount_opt2;
        unsigned long   vals_s_mount_flags;
        unsigned long   mask_s_mount_flags;
+       unsigned long   balloon_ino;
        unsigned int    opt_flags;      /* MOPT flags */
        unsigned int    spec;
        u32             s_max_batch_time;
@@ -2338,6 +2343,10 @@ static int ext4_parse_param(struct fs_context *fc, 
struct fs_parameter *param)
                        return -EINVAL;
                }
                return 0;
+       case Opt_balloon_ino:
+               ctx->balloon_ino = result.uint_32;
+               ctx->spec |= EXT4_SPEC_balloon_ino;
+               return 0;
        }
 
        /*
@@ -3016,6 +3025,9 @@ static int _ext4_show_options(struct seq_file *seq, 
struct super_block *sb,
                SEQ_OPTS_PUTS("mb_optimize_scan=1");
        }
 
+       if (sbi->s_balloon_ino)
+               SEQ_OPTS_PRINT("balloon_ino=%ld", sbi->s_balloon_ino->i_ino);
+
        ext4_show_quota_options(seq, sb);
        return 0;
 }
@@ -4306,6 +4318,54 @@ static struct ext4_sb_info *ext4_alloc_sbi(struct 
super_block *sb)
        return NULL;
 }
 
+static void ext4_load_balloon(struct super_block *sb, unsigned long ino)
+{
+       struct inode *inode;
+       struct ext4_sb_info *sbi;
+
+       sbi = EXT4_SB(sb);
+
+       if (!ino) {
+               /* FIXME locking */
+               if (sbi->s_balloon_ino) {
+                       iput(sbi->s_balloon_ino);
+                       sbi->s_balloon_ino = NULL;
+               }
+
+               return;
+       }
+
+       if (ino < EXT4_FIRST_INO(sb)) {
+               ext4_msg(sb, KERN_WARNING, "bad balloon inode specified");
+               return;
+       }
+
+       inode = ext4_iget(sb, ino, EXT4_IGET_NORMAL);
+       if (IS_ERR(inode)) {
+               ext4_msg(sb, KERN_WARNING, "can't load balloon inode (%ld)", 
PTR_ERR(inode));
+               return;
+       }
+
+       if (!S_ISREG(inode->i_mode)) {
+               iput(inode);
+               ext4_msg(sb, KERN_WARNING, "balloon should be regular");
+               return;
+       }
+
+       if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) {
+               iput(inode);
+               ext4_msg(sb, KERN_WARNING, "balloon should support extents");
+               return;
+       }
+
+       /* FIXME - locking */
+       if (sbi->s_balloon_ino)
+               iput(sbi->s_balloon_ino);
+       sbi->s_balloon_ino = inode;
+       ext4_msg(sb, KERN_INFO, "loaded balloon from %ld (%llu blocks)",
+                       inode->i_ino, inode->i_blocks);
+}
+
 static void ext4_set_def_opts(struct super_block *sb,
                              struct ext4_super_block *es)
 {
@@ -5569,6 +5629,9 @@ static int __ext4_fill_super(struct fs_context *fc, 
struct super_block *sb)
                ext4_msg(sb, KERN_WARNING,
                         "mounting with \"discard\" option, but the device does 
not support discard");
 
+       if (ctx->spec & EXT4_SPEC_balloon_ino)
+               ext4_load_balloon(sb, ctx->balloon_ino);
+
        if (es->s_error_count)
                mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
 
@@ -6636,6 +6699,9 @@ static int __ext4_remount(struct fs_context *fc, struct 
super_block *sb)
                        goto restore_opts;
        }
 
+       if (ctx->spec & EXT4_SPEC_balloon_ino)
+               ext4_load_balloon(sb, ctx->balloon_ino);
+
 #ifdef CONFIG_QUOTA
        if (enable_quota) {
                if (sb_any_quota_suspended(sb))
@@ -7297,12 +7363,23 @@ static inline int ext3_feature_set_ok(struct 
super_block *sb)
        return 1;
 }
 
+static void ext4_kill_sb(struct super_block *sb)
+{
+       struct ext4_sb_info *sbi;
+
+       sbi = EXT4_SB(sb);
+       if (sbi && sbi->s_balloon_ino)
+               iput(sbi->s_balloon_ino);
+
+       kill_block_super(sb);
+}
+
 static struct file_system_type ext4_fs_type = {
        .owner                  = THIS_MODULE,
        .name                   = "ext4",
        .init_fs_context        = ext4_init_fs_context,
        .parameters             = ext4_param_specs,
-       .kill_sb                = kill_block_super,
+       .kill_sb                = ext4_kill_sb,
        .fs_flags               = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
 };
 MODULE_ALIAS_FS("ext4");
-- 
2.43.5

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to