xfs: prepare to reuse the dquot pointer space in struct xfs_inode

Files participating in the metadata directory tree are not accounted to
the quota subsystem.  Therefore, the i_[ugp]dquot pointers in struct
xfs_inode are never used and should always be NULL.

In the next patch we want to add a u64 count of fs blocks reserved for
metadata btree expansion, but we don't want every inode in the fs to pay
the memory price for this feature.  The intent is to union those three
pointers with the u64 counter, but for that to work we must guard
against all access to the dquot pointers for metadata files.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Darrick J. Wong 2024-11-20 16:20:18 -08:00
parent 2f63b20b7a
commit 84140a96cf
10 changed files with 26 additions and 18 deletions

View file

@ -1004,9 +1004,7 @@ xfs_attr_add_fork(
unsigned int blks; /* space reservation */
int error; /* error return value */
if (xfs_is_metadir_inode(ip))
ASSERT(XFS_IS_DQDETACHED(ip));
else
if (!xfs_is_metadir_inode(ip))
ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
blks = XFS_ADDAFORK_SPACE_RES(mp);

View file

@ -1042,9 +1042,7 @@ xfs_bmap_add_attrfork(
int error; /* error return value */
xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
if (xfs_is_metadir_inode(ip))
ASSERT(XFS_IS_DQDETACHED(ip));
else
if (!xfs_is_metadir_inode(ip))
ASSERT(!XFS_NOT_DQATTACHED(mp, ip));
ASSERT(!xfs_inode_has_attr_fork(ip));

View file

@ -749,6 +749,7 @@ xrep_tempexch_reserve_quota(
* or the two inodes have the same dquots.
*/
if (!XFS_IS_QUOTA_ON(tp->t_mountp) || req->ip1 == req->ip2 ||
xfs_is_metadir_inode(req->ip1) ||
(req->ip1->i_udquot == req->ip2->i_udquot &&
req->ip1->i_gdquot == req->ip2->i_gdquot &&
req->ip1->i_pdquot == req->ip2->i_pdquot))

View file

@ -160,6 +160,9 @@ static inline struct xfs_dquot *xfs_inode_dquot(
struct xfs_inode *ip,
xfs_dqtype_t type)
{
if (xfs_is_metadir_inode(ip))
return NULL;
switch (type) {
case XFS_DQTYPE_USER:
return ip->i_udquot;

View file

@ -119,6 +119,9 @@ xfs_exchrange_reserve_quota(
int ip1_error = 0;
int error;
ASSERT(!xfs_is_metadir_inode(req->ip1));
ASSERT(!xfs_is_metadir_inode(req->ip2));
/*
* Don't bother with a quota reservation if we're not enforcing them
* or the two inodes have the same dquots.

View file

@ -25,9 +25,13 @@ struct xfs_dquot;
typedef struct xfs_inode {
/* Inode linking and identification information. */
struct xfs_mount *i_mount; /* fs mount struct ptr */
struct xfs_dquot *i_udquot; /* user dquot */
struct xfs_dquot *i_gdquot; /* group dquot */
struct xfs_dquot *i_pdquot; /* project dquot */
union {
struct {
struct xfs_dquot *i_udquot; /* user dquot */
struct xfs_dquot *i_gdquot; /* group dquot */
struct xfs_dquot *i_pdquot; /* project dquot */
};
};
/* Inode location stuff */
xfs_ino_t i_ino; /* inode number (agno/agino)*/

View file

@ -428,6 +428,8 @@ void
xfs_qm_dqdetach(
xfs_inode_t *ip)
{
if (xfs_is_metadir_inode(ip))
return;
if (!(ip->i_udquot || ip->i_gdquot || ip->i_pdquot))
return;

View file

@ -29,11 +29,6 @@ struct xfs_buf;
(XFS_IS_GQUOTA_ON(mp) && (ip)->i_gdquot == NULL) || \
(XFS_IS_PQUOTA_ON(mp) && (ip)->i_pdquot == NULL))
#define XFS_IS_DQDETACHED(ip) \
((ip)->i_udquot == NULL && \
(ip)->i_gdquot == NULL && \
(ip)->i_pdquot == NULL)
#define XFS_QM_NEED_QUOTACHECK(mp) \
((XFS_IS_UQUOTA_ON(mp) && \
(mp->m_sb.sb_qflags & XFS_UQUOTA_CHKD) == 0) || \

View file

@ -1266,6 +1266,9 @@ retry:
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
if (xfs_is_metadir_inode(ip))
goto out;
error = xfs_qm_dqattach_locked(ip, false);
if (error) {
/* Caller should have allocated the dquots! */
@ -1334,6 +1337,7 @@ retry:
goto out_cancel;
}
out:
*tpp = tp;
return 0;

View file

@ -156,7 +156,8 @@ xfs_trans_mod_ino_dquot(
unsigned int field,
int64_t delta)
{
ASSERT(!xfs_is_metadir_inode(ip) || XFS_IS_DQDETACHED(ip));
if (xfs_is_metadir_inode(ip))
return;
xfs_trans_mod_dquot(tp, dqp, field, delta);
@ -246,11 +247,10 @@ xfs_trans_mod_dquot_byino(
xfs_mount_t *mp = tp->t_mountp;
if (!XFS_IS_QUOTA_ON(mp) ||
xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
xfs_is_quota_inode(&mp->m_sb, ip->i_ino) ||
xfs_is_metadir_inode(ip))
return;
ASSERT(!xfs_is_metadir_inode(ip) || XFS_IS_DQDETACHED(ip));
if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
xfs_trans_mod_ino_dquot(tp, ip, ip->i_udquot, field, delta);
if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot)