[XFS] Clean up dquot pincount code.
This is a code cleanup and optimization that removes a per mount point spinlock from the quota code and cleans up the code. The patch changes the pincount from being an int protected by a spinlock to an atomic_t allowing the pincount to be manipulated without holding the spinlock. This cleanup also protects against random wakup's of both the aild and xfssyncd by reevaluating the pincount after been woken. Two latter patches will address the Spurious wakeups. SGI-PV: 986789 SGI-Modid: xfs-linux-melb:xfs-kern:32215a Signed-off-by: Peter Leckie <pleckie@sgi.com> Signed-off-by: Christoph Hellwig <hch@infradead.org> Signed-off-by: David Chinner <david@fromorbit.com> Signed-off-by: Donald Douwsma <donaldd@sgi.com> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
This commit is contained in:
committed by
Lachlan McIlroy
parent
d112f29845
commit
bc3048e3cd
@@ -101,7 +101,7 @@ xfs_qm_dqinit(
|
|||||||
if (brandnewdquot) {
|
if (brandnewdquot) {
|
||||||
dqp->dq_flnext = dqp->dq_flprev = dqp;
|
dqp->dq_flnext = dqp->dq_flprev = dqp;
|
||||||
mutex_init(&dqp->q_qlock);
|
mutex_init(&dqp->q_qlock);
|
||||||
sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq");
|
init_waitqueue_head(&dqp->q_pinwait);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Because we want to use a counting completion, complete
|
* Because we want to use a counting completion, complete
|
||||||
@@ -131,7 +131,7 @@ xfs_qm_dqinit(
|
|||||||
dqp->q_res_bcount = 0;
|
dqp->q_res_bcount = 0;
|
||||||
dqp->q_res_icount = 0;
|
dqp->q_res_icount = 0;
|
||||||
dqp->q_res_rtbcount = 0;
|
dqp->q_res_rtbcount = 0;
|
||||||
dqp->q_pincount = 0;
|
atomic_set(&dqp->q_pincount, 0);
|
||||||
dqp->q_hash = NULL;
|
dqp->q_hash = NULL;
|
||||||
ASSERT(dqp->dq_flnext == dqp->dq_flprev);
|
ASSERT(dqp->dq_flnext == dqp->dq_flprev);
|
||||||
|
|
||||||
@@ -1489,7 +1489,7 @@ xfs_qm_dqpurge(
|
|||||||
"xfs_qm_dqpurge: dquot %p flush failed", dqp);
|
"xfs_qm_dqpurge: dquot %p flush failed", dqp);
|
||||||
xfs_dqflock(dqp);
|
xfs_dqflock(dqp);
|
||||||
}
|
}
|
||||||
ASSERT(dqp->q_pincount == 0);
|
ASSERT(atomic_read(&dqp->q_pincount) == 0);
|
||||||
ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
|
ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
|
||||||
!(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL));
|
!(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL));
|
||||||
|
|
||||||
|
@@ -83,8 +83,8 @@ typedef struct xfs_dquot {
|
|||||||
xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */
|
xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */
|
||||||
mutex_t q_qlock; /* quota lock */
|
mutex_t q_qlock; /* quota lock */
|
||||||
struct completion q_flush; /* flush completion queue */
|
struct completion q_flush; /* flush completion queue */
|
||||||
uint q_pincount; /* pin count for this dquot */
|
atomic_t q_pincount; /* dquot pin count */
|
||||||
sv_t q_pinwait; /* sync var for pinning */
|
wait_queue_head_t q_pinwait; /* dquot pinning wait queue */
|
||||||
#ifdef XFS_DQUOT_TRACE
|
#ifdef XFS_DQUOT_TRACE
|
||||||
struct ktrace *q_trace; /* trace header structure */
|
struct ktrace *q_trace; /* trace header structure */
|
||||||
#endif
|
#endif
|
||||||
|
@@ -88,25 +88,22 @@ xfs_qm_dquot_logitem_format(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Increment the pin count of the given dquot.
|
* Increment the pin count of the given dquot.
|
||||||
* This value is protected by pinlock spinlock in the xQM structure.
|
|
||||||
*/
|
*/
|
||||||
STATIC void
|
STATIC void
|
||||||
xfs_qm_dquot_logitem_pin(
|
xfs_qm_dquot_logitem_pin(
|
||||||
xfs_dq_logitem_t *logitem)
|
xfs_dq_logitem_t *logitem)
|
||||||
{
|
{
|
||||||
xfs_dquot_t *dqp;
|
xfs_dquot_t *dqp = logitem->qli_dquot;
|
||||||
|
|
||||||
dqp = logitem->qli_dquot;
|
|
||||||
ASSERT(XFS_DQ_IS_LOCKED(dqp));
|
ASSERT(XFS_DQ_IS_LOCKED(dqp));
|
||||||
spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
|
atomic_inc(dqp->q_pincount);
|
||||||
dqp->q_pincount++;
|
|
||||||
spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Decrement the pin count of the given dquot, and wake up
|
* Decrement the pin count of the given dquot, and wake up
|
||||||
* anyone in xfs_dqwait_unpin() if the count goes to 0. The
|
* anyone in xfs_dqwait_unpin() if the count goes to 0. The
|
||||||
* dquot must have been previously pinned with a call to xfs_dqpin().
|
* dquot must have been previously pinned with a call to
|
||||||
|
* xfs_qm_dquot_logitem_pin().
|
||||||
*/
|
*/
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
STATIC void
|
STATIC void
|
||||||
@@ -114,16 +111,11 @@ xfs_qm_dquot_logitem_unpin(
|
|||||||
xfs_dq_logitem_t *logitem,
|
xfs_dq_logitem_t *logitem,
|
||||||
int stale)
|
int stale)
|
||||||
{
|
{
|
||||||
xfs_dquot_t *dqp;
|
xfs_dquot_t *dqp = logitem->qli_dquot;
|
||||||
|
|
||||||
dqp = logitem->qli_dquot;
|
ASSERT(atomic_read(&dqp->q_pincount) > 0);
|
||||||
ASSERT(dqp->q_pincount > 0);
|
if (atomic_dec_and_test(&dqp->q_pincount))
|
||||||
spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
|
wake_up(&dqp->q_pinwait);
|
||||||
dqp->q_pincount--;
|
|
||||||
if (dqp->q_pincount == 0) {
|
|
||||||
sv_broadcast(&dqp->q_pinwait);
|
|
||||||
}
|
|
||||||
spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
@@ -193,21 +185,14 @@ xfs_qm_dqunpin_wait(
|
|||||||
xfs_dquot_t *dqp)
|
xfs_dquot_t *dqp)
|
||||||
{
|
{
|
||||||
ASSERT(XFS_DQ_IS_LOCKED(dqp));
|
ASSERT(XFS_DQ_IS_LOCKED(dqp));
|
||||||
if (dqp->q_pincount == 0) {
|
if (atomic_read(&dqp->q_pincount) == 0)
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Give the log a push so we don't wait here too long.
|
* Give the log a push so we don't wait here too long.
|
||||||
*/
|
*/
|
||||||
xfs_log_force(dqp->q_mount, (xfs_lsn_t)0, XFS_LOG_FORCE);
|
xfs_log_force(dqp->q_mount, (xfs_lsn_t)0, XFS_LOG_FORCE);
|
||||||
spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
|
wait_event(dqp->q_pinwait, (atomic_read(&dqp->q_pincount) == 0));
|
||||||
if (dqp->q_pincount == 0) {
|
|
||||||
spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sv_wait(&(dqp->q_pinwait), PINOD,
|
|
||||||
&(XFS_DQ_TO_QINF(dqp)->qi_pinlock), s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -310,7 +295,7 @@ xfs_qm_dquot_logitem_trylock(
|
|||||||
uint retval;
|
uint retval;
|
||||||
|
|
||||||
dqp = qip->qli_dquot;
|
dqp = qip->qli_dquot;
|
||||||
if (dqp->q_pincount > 0)
|
if (atomic_read(&dqp->q_pincount) > 0)
|
||||||
return (XFS_ITEM_PINNED);
|
return (XFS_ITEM_PINNED);
|
||||||
|
|
||||||
if (! xfs_qm_dqlock_nowait(dqp))
|
if (! xfs_qm_dqlock_nowait(dqp))
|
||||||
|
@@ -1137,7 +1137,6 @@ xfs_qm_init_quotainfo(
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_init(&qinf->qi_pinlock);
|
|
||||||
xfs_qm_list_init(&qinf->qi_dqlist, "mpdqlist", 0);
|
xfs_qm_list_init(&qinf->qi_dqlist, "mpdqlist", 0);
|
||||||
qinf->qi_dqreclaims = 0;
|
qinf->qi_dqreclaims = 0;
|
||||||
|
|
||||||
@@ -1234,7 +1233,6 @@ xfs_qm_destroy_quotainfo(
|
|||||||
*/
|
*/
|
||||||
xfs_qm_rele_quotafs_ref(mp);
|
xfs_qm_rele_quotafs_ref(mp);
|
||||||
|
|
||||||
spinlock_destroy(&qi->qi_pinlock);
|
|
||||||
xfs_qm_list_destroy(&qi->qi_dqlist);
|
xfs_qm_list_destroy(&qi->qi_dqlist);
|
||||||
|
|
||||||
if (qi->qi_uquotaip) {
|
if (qi->qi_uquotaip) {
|
||||||
|
@@ -106,7 +106,6 @@ typedef struct xfs_qm {
|
|||||||
typedef struct xfs_quotainfo {
|
typedef struct xfs_quotainfo {
|
||||||
xfs_inode_t *qi_uquotaip; /* user quota inode */
|
xfs_inode_t *qi_uquotaip; /* user quota inode */
|
||||||
xfs_inode_t *qi_gquotaip; /* group quota inode */
|
xfs_inode_t *qi_gquotaip; /* group quota inode */
|
||||||
spinlock_t qi_pinlock; /* dquot pinning lock */
|
|
||||||
xfs_dqlist_t qi_dqlist; /* all dquots in filesys */
|
xfs_dqlist_t qi_dqlist; /* all dquots in filesys */
|
||||||
int qi_dqreclaims; /* a change here indicates
|
int qi_dqreclaims; /* a change here indicates
|
||||||
a removal in the dqlist */
|
a removal in the dqlist */
|
||||||
|
Reference in New Issue
Block a user