[Devel] [PATCH RHEL9 COMMIT] xfs: Teach the fs where the balloon inode is

Konstantin Khorenko khorenko at virtuozzo.com
Mon Oct 25 15:49:49 MSK 2021


The commit is pushed to "branch-rh9-5.14.vz9.1.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh9-5.14.0-4.vz9.10.16
------>
commit a582ee7309cc7cc2e18efe80577339268fa68647
Author: Kirill Tkhai <ktkhai at virtuozzo.com>
Date:   Mon Oct 25 15:49:49 2021 +0300

    xfs: Teach the fs where the balloon inode is
    
    This adds balloon_ino=XXX mount option for xfs.
    
    https://jira.sw.ru/browse/PSBM-133811
    
    Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
 fs/xfs/xfs_mount.h |  2 ++
 fs/xfs/xfs_super.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_super.h |  2 ++
 3 files changed, 83 insertions(+)

diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index c78b63fe779a..4eb318bb44ac 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -154,6 +154,8 @@ typedef struct xfs_mount {
 	uint8_t			m_rt_checked;
 	uint8_t			m_rt_sick;
 
+	uint64_t		m_balloon_ino;
+
 	/*
 	 * End of read-mostly variables. Frequently written variables and locks
 	 * should be placed below this comment from now on. The first variable
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index fd1cd6aacd10..bd28e2a0d496 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -95,6 +95,7 @@ enum {
 	Opt_prjquota, Opt_uquota, Opt_gquota, Opt_pquota,
 	Opt_uqnoenforce, Opt_gqnoenforce, Opt_pqnoenforce, Opt_qnoenforce,
 	Opt_discard, Opt_nodiscard, Opt_dax, Opt_dax_enum,
+	Opt_balloon_ino,
 };
 
 static const struct fs_parameter_spec xfs_fs_parameters[] = {
@@ -139,6 +140,7 @@ static const struct fs_parameter_spec xfs_fs_parameters[] = {
 	fsparam_flag("nodiscard",	Opt_nodiscard),
 	fsparam_flag("dax",		Opt_dax),
 	fsparam_enum("dax",		Opt_dax_enum, dax_param_enums),
+	fsparam_u64("balloon_ino",	Opt_balloon_ino),
 	{}
 };
 
@@ -171,6 +173,7 @@ xfs_fs_show_options(
 	};
 	struct xfs_mount	*mp = XFS_M(root->d_sb);
 	struct proc_xfs_info	*xfs_infop;
+	u64			balloon_ino;
 
 	for (xfs_infop = xfs_info_set; xfs_infop->flag; xfs_infop++) {
 		if (mp->m_flags & xfs_infop->flag)
@@ -224,6 +227,9 @@ xfs_fs_show_options(
 	if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
 		seq_puts(m, ",noquota");
 
+	if ((balloon_ino = READ_ONCE(mp->m_balloon_ino)) != 0)
+		seq_printf(m, ",balloon_ino=%llu",
+				balloon_ino);
 	return 0;
 }
 
@@ -776,6 +782,41 @@ xfs_fs_sync_fs(
 	return 0;
 }
 
+struct xfs_inode *
+xfs_balloon_get(struct xfs_mount *mp, u64 balloon_ino, uint flags)
+{
+	struct xfs_inode *ip;
+	struct inode *inode;
+	int error;
+
+	if (!xfs_verify_dir_ino(mp, balloon_ino))
+		return ERR_PTR(-EINVAL);
+
+	error = xfs_iget(mp, NULL, balloon_ino, flags, 0, &ip);
+	if (error)
+		return ERR_PTR(error);
+	inode = VFS_I(ip);
+	if (!S_ISREG(inode->i_mode) || IS_IMMUTABLE(inode))
+		return ERR_PTR(-EINVAL);
+
+	return ip;
+}
+
+STATIC int
+xfs_balloon_check(struct xfs_mount *mp, u64 balloon_ino)
+{
+	struct xfs_inode *ip;
+
+	if (!balloon_ino)
+		return 0;
+
+	ip = xfs_balloon_get(mp, balloon_ino, XFS_IGET_UNTRUSTED);
+	if (IS_ERR(ip))
+		return PTR_ERR(ip);
+	xfs_irele(ip);
+	return 0;
+}
+
 STATIC int
 xfs_fs_statfs(
 	struct dentry		*dentry,
@@ -790,6 +831,7 @@ xfs_fs_statfs(
 	uint64_t		fdblocks;
 	xfs_extlen_t		lsize;
 	int64_t			ffree;
+	u64			balloon_ino;
 
 	statp->f_type = XFS_SUPER_MAGIC;
 	statp->f_namelen = MAXNAMELEN - 1;
@@ -840,6 +882,17 @@ xfs_fs_statfs(
 			sbp->sb_frextents * sbp->sb_rextsize;
 	}
 
+	if ((balloon_ino = READ_ONCE(mp->m_balloon_ino)) != 0) {
+		struct xfs_inode *ip;
+
+		ip = xfs_balloon_get(mp, balloon_ino, 0);
+		if (ip) {
+			/* Note, i_nblocks also contains metadata blocks */
+			statp->f_blocks -= ip->i_nblocks + ip->i_delayed_blks;
+			xfs_irele(ip);
+		}
+	}
+
 	return 0;
 }
 
@@ -1273,6 +1326,9 @@ xfs_fs_parse_param(
 		xfs_mount_set_dax_mode(parsing_mp, result.uint_32);
 		return 0;
 #endif
+	case Opt_balloon_ino:
+		parsing_mp->m_balloon_ino = result.uint_64;
+		return 0;
 	/* Following mount options will be removed in September 2025 */
 	case Opt_ikeep:
 		xfs_fs_warn_deprecated(fc, param, XFS_MOUNT_IKEEP, true);
@@ -1603,6 +1659,10 @@ xfs_fs_fill_super(
 	if (error)
 		goto out_filestream_unmount;
 
+	error = xfs_balloon_check(mp, mp->m_balloon_ino);
+	if (error)
+		goto out_unmount;
+
 	root = igrab(VFS_I(mp->m_rootip));
 	if (!root) {
 		error = -ENOENT;
@@ -1809,6 +1869,25 @@ xfs_fs_reconfigure(
 			return error;
 	}
 
+	if (mp->m_balloon_ino != new_mp->m_balloon_ino) {
+		/* We never replace balloon file, so prohibit this */
+		if (mp->m_balloon_ino)
+			return -EBUSY;
+		/*
+		 * Note, that there maybe tasks, which have already
+		 * opened the new balloon file. So, in general this
+		 * is racy (someone even may remove this file)
+		 * though the synchronization here would be too heavy.
+		 * Since the effects of the race are not serious, and
+		 * the race is not possible in process of our normal
+		 * usage, we just ignore it.
+		 */
+		error = xfs_balloon_check(mp, new_mp->m_balloon_ino);
+		if (error)
+			return error;
+		WRITE_ONCE(mp->m_balloon_ino, new_mp->m_balloon_ino);
+	}
+
 	return 0;
 }
 
diff --git a/fs/xfs/xfs_super.h b/fs/xfs/xfs_super.h
index 167d23f92ffe..34409cbb11e3 100644
--- a/fs/xfs/xfs_super.h
+++ b/fs/xfs/xfs_super.h
@@ -100,4 +100,6 @@ extern struct workqueue_struct *xfs_discard_wq;
 
 #define XFS_M(sb)		((struct xfs_mount *)((sb)->s_fs_info))
 
+extern struct xfs_inode *xfs_balloon_get(struct xfs_mount *mp,
+					 u64 balloon_ino, uint flags);
 #endif	/* __XFS_SUPER_H__ */


More information about the Devel mailing list