1 Date: Fri, Sep 26 2008 15:20:10 +1000
2 From: Peter Leckie <pleckie@sgi.com>
3 References: SGI:PV986789 bnc#482148
4 Subject: Clean up dquot pincount code
7 Clean up dquot pincount code.
9 This is a code cleanup and optimization that removes a per mount point
10 spinlock from the quota code and cleans up the code.
12 The patch changes the pincount from being an int protected by a spinlock
13 to an atomic_t allowing the pincount to be manipulated without holding
16 This cleanup also protects against random wakup's of both the aild and
17 xfssyncd by reevaluating the pincount after been woken. Two latter patches
18 will address the Spurious wakeups.
20 Signed-off-by: Peter Leckie <pleckie@sgi.com>
21 Acked-by: Jan Kara <jack@suse.cz>
23 Index: linux/fs/xfs/quota/xfs_dquot_item.c
24 ===================================================================
25 --- linux.orig/fs/xfs/quota/xfs_dquot_item.c 2008-10-09 17:13:53.000000000 -0500
26 +++ linux/fs/xfs/quota/xfs_dquot_item.c 2009-03-09 10:24:24.000000000 -0500
27 @@ -88,25 +88,23 @@ xfs_qm_dquot_logitem_format(
30 * Increment the pin count of the given dquot.
31 - * This value is protected by pinlock spinlock in the xQM structure.
34 xfs_qm_dquot_logitem_pin(
35 xfs_dq_logitem_t *logitem)
38 + xfs_dquot_t *dqp = logitem->qli_dquot;
40 - dqp = logitem->qli_dquot;
41 ASSERT(XFS_DQ_IS_LOCKED(dqp));
42 - spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
44 - spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
45 + atomic_inc(&dqp->q_pincount);
50 * Decrement the pin count of the given dquot, and wake up
51 * anyone in xfs_dqwait_unpin() if the count goes to 0. The
52 - * dquot must have been previously pinned with a call to xfs_dqpin().
53 + * dquot must have been previously pinned with a call to
54 + * xfs_qm_dquot_logitem_pin().
58 @@ -114,16 +112,12 @@ xfs_qm_dquot_logitem_unpin(
59 xfs_dq_logitem_t *logitem,
63 +xfs_dquot_t *dqp = logitem->qli_dquot;
65 + ASSERT(atomic_read(&dqp->q_pincount) > 0);
66 + if (atomic_dec_and_test(&dqp->q_pincount))
67 + wake_up(&dqp->q_pinwait);
69 - dqp = logitem->qli_dquot;
70 - ASSERT(dqp->q_pincount > 0);
71 - spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
73 - if (dqp->q_pincount == 0) {
74 - sv_broadcast(&dqp->q_pinwait);
76 - spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
80 @@ -193,7 +187,7 @@ xfs_qm_dqunpin_wait(
83 ASSERT(XFS_DQ_IS_LOCKED(dqp));
84 - if (dqp->q_pincount == 0) {
85 + if (atomic_read(&dqp->q_pincount) == 0) {
89 @@ -201,13 +195,7 @@ xfs_qm_dqunpin_wait(
90 * Give the log a push so we don't wait here too long.
92 xfs_log_force(dqp->q_mount, (xfs_lsn_t)0, XFS_LOG_FORCE);
93 - spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
94 - if (dqp->q_pincount == 0) {
95 - spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock));
98 - sv_wait(&(dqp->q_pinwait), PINOD,
99 - &(XFS_DQ_TO_QINF(dqp)->qi_pinlock), s);
100 + wait_event(dqp->q_pinwait, (atomic_read(&dqp->q_pincount) == 0));
104 @@ -310,7 +298,7 @@ xfs_qm_dquot_logitem_trylock(
107 dqp = qip->qli_dquot;
108 - if (dqp->q_pincount > 0)
109 + if (atomic_read(&dqp->q_pincount) > 0)
110 return (XFS_ITEM_PINNED);
112 if (! xfs_qm_dqlock_nowait(dqp))
113 Index: linux/fs/xfs/quota/xfs_dquot.h
114 ===================================================================
115 --- linux.orig/fs/xfs/quota/xfs_dquot.h 2008-10-09 17:13:53.000000000 -0500
116 +++ linux/fs/xfs/quota/xfs_dquot.h 2009-03-09 10:36:25.000000000 -0500
117 @@ -83,8 +83,9 @@ typedef struct xfs_dquot {
118 xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */
119 mutex_t q_qlock; /* quota lock */
120 struct completion q_flush; /* flush completion queue */
121 - uint q_pincount; /* pin count for this dquot */
122 - sv_t q_pinwait; /* sync var for pinning */
123 + atomic_t q_pincount; /* dquot pin count */
124 + wait_queue_head_t q_pinwait; /* dquot pinning wait queue */
126 #ifdef XFS_DQUOT_TRACE
127 struct ktrace *q_trace; /* trace header structure */
129 Index: linux/fs/xfs/quota/xfs_dquot.c
130 ===================================================================
131 --- linux.orig/fs/xfs/quota/xfs_dquot.c 2008-10-09 17:13:53.000000000 -0500
132 +++ linux/fs/xfs/quota/xfs_dquot.c 2009-03-09 10:38:06.000000000 -0500
133 @@ -101,7 +101,7 @@ xfs_qm_dqinit(
135 dqp->dq_flnext = dqp->dq_flprev = dqp;
136 mutex_init(&dqp->q_qlock);
137 - sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq");
138 + init_waitqueue_head(&dqp->q_pinwait);
141 * Because we want to use a counting completion, complete
142 @@ -131,7 +131,7 @@ xfs_qm_dqinit(
143 dqp->q_res_bcount = 0;
144 dqp->q_res_icount = 0;
145 dqp->q_res_rtbcount = 0;
146 - dqp->q_pincount = 0;
147 + atomic_set(&dqp->q_pincount, 0);
149 ASSERT(dqp->dq_flnext == dqp->dq_flprev);
151 @@ -1489,7 +1489,7 @@ xfs_qm_dqpurge(
152 "xfs_qm_dqpurge: dquot %p flush failed", dqp);
155 - ASSERT(dqp->q_pincount == 0);
156 + ASSERT(atomic_read(&dqp->q_pincount) == 0);
157 ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
158 !(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL));
160 Index: linux/fs/xfs/quota/xfs_qm.h
161 ===================================================================
162 --- linux.orig/fs/xfs/quota/xfs_qm.h 2008-10-09 17:13:53.000000000 -0500
163 +++ linux/fs/xfs/quota/xfs_qm.h 2009-03-09 10:11:15.000000000 -0500
164 @@ -106,7 +106,6 @@ typedef struct xfs_qm {
165 typedef struct xfs_quotainfo {
166 xfs_inode_t *qi_uquotaip; /* user quota inode */
167 xfs_inode_t *qi_gquotaip; /* group quota inode */
168 - spinlock_t qi_pinlock; /* dquot pinning lock */
169 xfs_dqlist_t qi_dqlist; /* all dquots in filesys */
170 int qi_dqreclaims; /* a change here indicates
171 a removal in the dqlist */
172 Index: linux/fs/xfs/quota/xfs_qm.c
173 ===================================================================
174 --- linux.orig/fs/xfs/quota/xfs_qm.c 2008-10-09 17:13:53.000000000 -0500
175 +++ linux/fs/xfs/quota/xfs_qm.c 2009-03-09 10:12:12.000000000 -0500
176 @@ -1137,7 +1137,6 @@ xfs_qm_init_quotainfo(
180 - spin_lock_init(&qinf->qi_pinlock);
181 xfs_qm_list_init(&qinf->qi_dqlist, "mpdqlist", 0);
182 qinf->qi_dqreclaims = 0;
184 @@ -1234,7 +1233,6 @@ xfs_qm_destroy_quotainfo(
186 xfs_qm_rele_quotafs_ref(mp);
188 - spinlock_destroy(&qi->qi_pinlock);
189 xfs_qm_list_destroy(&qi->qi_dqlist);
191 if (qi->qi_uquotaip) {