From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> Refactor the group and project quota inode pointer switcheroo that happens only on v4 filesystems into a separate function prior to enhancing the xfs_qm_qino_alloc function. Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> --- fs/xfs/xfs_qm.c | 79 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 58be2ef90351..b5f2853a5009 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -742,6 +742,53 @@ xfs_qm_destroy_quotainfo( mp->m_quotainfo = NULL; } +/* + * Switch the group and project quota in-core inode pointers if needed. + * + * On v4 superblocks that don't have separate pquotino, we share an inode + * between gquota and pquota. If the on-disk superblock has GQUOTA and the + * filesystem is now mounted with PQUOTA, just use sb_gquotino for sb_pquotino + * and vice-versa. + */ +STATIC int +xfs_qm_qino_switch( + struct xfs_mount *mp, + struct xfs_inode **ip, + unsigned int flags, + bool *need_alloc) +{ + xfs_ino_t ino = NULLFSINO; + int error; + + if (xfs_sb_version_has_pquotino(&mp->m_sb) || + !(flags & (XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA))) + return 0; + + if ((flags & XFS_QMOPT_PQUOTA) && + (mp->m_sb.sb_gquotino != NULLFSINO)) { + ino = mp->m_sb.sb_gquotino; + if (mp->m_sb.sb_pquotino != NULLFSINO) + return -EFSCORRUPTED; + } else if ((flags & XFS_QMOPT_GQUOTA) && + (mp->m_sb.sb_pquotino != NULLFSINO)) { + ino = mp->m_sb.sb_pquotino; + if (mp->m_sb.sb_gquotino != NULLFSINO) + return -EFSCORRUPTED; + } + + if (ino == NULLFSINO) + return 0; + + error = xfs_iget(mp, NULL, ino, 0, 0, ip); + if (error) + return error; + + mp->m_sb.sb_gquotino = NULLFSINO; + mp->m_sb.sb_pquotino = NULLFSINO; + *need_alloc = false; + return 0; +} + /* * Create an inode and return with a reference already taken, but unlocked * This is how we create quota inodes @@ -762,35 +809,9 @@ xfs_qm_qino_alloc( bool need_alloc = true; *ip = NULL; - /* - * With superblock that doesn't have separate pquotino, we - * share an inode between gquota and pquota. If the on-disk - * superblock has GQUOTA and the filesystem is now mounted - * with PQUOTA, just use sb_gquotino for sb_pquotino and - * vice-versa. - */ - if (!xfs_sb_version_has_pquotino(&mp->m_sb) && - (flags & (XFS_QMOPT_PQUOTA|XFS_QMOPT_GQUOTA))) { - xfs_ino_t ino = NULLFSINO; - - if ((flags & XFS_QMOPT_PQUOTA) && - (mp->m_sb.sb_gquotino != NULLFSINO)) { - ino = mp->m_sb.sb_gquotino; - ASSERT(mp->m_sb.sb_pquotino == NULLFSINO); - } else if ((flags & XFS_QMOPT_GQUOTA) && - (mp->m_sb.sb_pquotino != NULLFSINO)) { - ino = mp->m_sb.sb_pquotino; - ASSERT(mp->m_sb.sb_gquotino == NULLFSINO); - } - if (ino != NULLFSINO) { - error = xfs_iget(mp, NULL, ino, 0, 0, ip); - if (error) - return error; - mp->m_sb.sb_gquotino = NULLFSINO; - mp->m_sb.sb_pquotino = NULLFSINO; - need_alloc = false; - } - } + error = xfs_qm_qino_switch(mp, ip, flags, &need_alloc); + if (error) + return error; error = xfs_trans_alloc(mp, &M_RES(mp)->tr_create, XFS_QM_QINOCREATE_SPACE_RES(mp), 0, 0, &tp);