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 <ktk...@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 <ktk...@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__ */
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to