[Devel] [PATCH vz9 01/10] ext4: Teach the fs where the balloon inode is

Konstantin Khorenko khorenko at virtuozzo.com
Thu Nov 28 19:51:45 MSK 2024


From: "Maxim V. Patlasov" <MPatlasov at 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 <khorenko at virtuozzo.com>
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>

+++
ext4: Fix placement of balloon ino option

Signed-off-by: Konstantin Khorenko <khorenko at 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 <khorenko at 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



More information about the Devel mailing list