mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
xfs: Increase XFS_QM_TRANS_MAXDQS to 5
With parent pointers enabled, a rename operation can update up to 5 inodes: src_dp, target_dp, src_ip, target_ip and wip. This causes their dquots to a be attached to the transaction chain, so we need to increase XFS_QM_TRANS_MAXDQS. This patch also add a helper function xfs_dqlockn to lock an arbitrary number of dquots. Signed-off-by: Allison Henderson <allison.henderson@oracle.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
7560c937b4
commit
f103df7635
@ -1371,6 +1371,47 @@ xfs_dqlock2(
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_dqtrx_cmp(
|
||||
const void *a,
|
||||
const void *b)
|
||||
{
|
||||
const struct xfs_dqtrx *qa = a;
|
||||
const struct xfs_dqtrx *qb = b;
|
||||
|
||||
if (qa->qt_dquot->q_id > qb->qt_dquot->q_id)
|
||||
return 1;
|
||||
if (qa->qt_dquot->q_id < qb->qt_dquot->q_id)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
xfs_dqlockn(
|
||||
struct xfs_dqtrx *q)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
BUILD_BUG_ON(XFS_QM_TRANS_MAXDQS > MAX_LOCKDEP_SUBCLASSES);
|
||||
|
||||
/* Sort in order of dquot id, do not allow duplicates */
|
||||
for (i = 0; i < XFS_QM_TRANS_MAXDQS && q[i].qt_dquot != NULL; i++) {
|
||||
unsigned int j;
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
ASSERT(q[i].qt_dquot != q[j].qt_dquot);
|
||||
}
|
||||
if (i == 0)
|
||||
return;
|
||||
|
||||
sort(q, i, sizeof(struct xfs_dqtrx), xfs_dqtrx_cmp, NULL);
|
||||
|
||||
mutex_lock(&q[0].qt_dquot->q_qlock);
|
||||
for (i = 1; i < XFS_QM_TRANS_MAXDQS && q[i].qt_dquot != NULL; i++)
|
||||
mutex_lock_nested(&q[i].qt_dquot->q_qlock,
|
||||
XFS_QLOCK_NESTED + i - 1);
|
||||
}
|
||||
|
||||
int __init
|
||||
xfs_qm_init(void)
|
||||
{
|
||||
|
@ -223,6 +223,7 @@ int xfs_qm_dqget_uncached(struct xfs_mount *mp,
|
||||
void xfs_qm_dqput(struct xfs_dquot *dqp);
|
||||
|
||||
void xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *);
|
||||
void xfs_dqlockn(struct xfs_dqtrx *q);
|
||||
|
||||
void xfs_dquot_set_prealloc_limits(struct xfs_dquot *);
|
||||
|
||||
|
@ -136,7 +136,7 @@ enum {
|
||||
XFS_QM_TRANS_PRJ,
|
||||
XFS_QM_TRANS_DQTYPES
|
||||
};
|
||||
#define XFS_QM_TRANS_MAXDQS 2
|
||||
#define XFS_QM_TRANS_MAXDQS 5
|
||||
struct xfs_dquot_acct {
|
||||
struct xfs_dqtrx dqs[XFS_QM_TRANS_DQTYPES][XFS_QM_TRANS_MAXDQS];
|
||||
};
|
||||
|
@ -379,24 +379,29 @@ xfs_trans_mod_dquot(
|
||||
|
||||
/*
|
||||
* Given an array of dqtrx structures, lock all the dquots associated and join
|
||||
* them to the transaction, provided they have been modified. We know that the
|
||||
* highest number of dquots of one type - usr, grp and prj - involved in a
|
||||
* transaction is 3 so we don't need to make this very generic.
|
||||
* them to the transaction, provided they have been modified.
|
||||
*/
|
||||
STATIC void
|
||||
xfs_trans_dqlockedjoin(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_dqtrx *q)
|
||||
{
|
||||
unsigned int i;
|
||||
ASSERT(q[0].qt_dquot != NULL);
|
||||
if (q[1].qt_dquot == NULL) {
|
||||
xfs_dqlock(q[0].qt_dquot);
|
||||
xfs_trans_dqjoin(tp, q[0].qt_dquot);
|
||||
} else {
|
||||
ASSERT(XFS_QM_TRANS_MAXDQS == 2);
|
||||
} else if (q[2].qt_dquot == NULL) {
|
||||
xfs_dqlock2(q[0].qt_dquot, q[1].qt_dquot);
|
||||
xfs_trans_dqjoin(tp, q[0].qt_dquot);
|
||||
xfs_trans_dqjoin(tp, q[1].qt_dquot);
|
||||
} else {
|
||||
xfs_dqlockn(q);
|
||||
for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
|
||||
if (q[i].qt_dquot == NULL)
|
||||
break;
|
||||
xfs_trans_dqjoin(tp, q[i].qt_dquot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user