[Devel] [PATCH RH9 1/4] xfs: Teach the fs where the balloon inode is
Kirill Tkhai
ktkhai at virtuozzo.com
Fri Oct 22 19:40:27 MSK 2021
This adds balloon_ino=XXX mount option for xfs.
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 304875c0d3cc..aba14f5adc4e 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