]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
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 | |
5 | Patch-mainline: 2.6.28 | |
6 | ||
7 | Clean up dquot pincount code. | |
8 | ||
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. | |
11 | ||
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 | |
14 | the spinlock. | |
15 | ||
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. | |
19 | ||
20 | Signed-off-by: Peter Leckie <pleckie@sgi.com> | |
21 | Acked-by: Jan Kara <jack@suse.cz> | |
22 | ||
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( | |
28 | ||
29 | /* | |
30 | * Increment the pin count of the given dquot. | |
31 | - * This value is protected by pinlock spinlock in the xQM structure. | |
32 | */ | |
33 | STATIC void | |
34 | xfs_qm_dquot_logitem_pin( | |
35 | xfs_dq_logitem_t *logitem) | |
36 | { | |
37 | - xfs_dquot_t *dqp; | |
38 | + xfs_dquot_t *dqp = logitem->qli_dquot; | |
39 | ||
40 | - dqp = logitem->qli_dquot; | |
41 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | |
42 | - spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock)); | |
43 | - dqp->q_pincount++; | |
44 | - spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock)); | |
45 | + atomic_inc(&dqp->q_pincount); | |
46 | + | |
47 | } | |
48 | ||
49 | /* | |
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(). | |
55 | */ | |
56 | /* ARGSUSED */ | |
57 | STATIC void | |
58 | @@ -114,16 +112,12 @@ xfs_qm_dquot_logitem_unpin( | |
59 | xfs_dq_logitem_t *logitem, | |
60 | int stale) | |
61 | { | |
62 | - xfs_dquot_t *dqp; | |
63 | +xfs_dquot_t *dqp = logitem->qli_dquot; | |
64 | + | |
65 | + ASSERT(atomic_read(&dqp->q_pincount) > 0); | |
66 | + if (atomic_dec_and_test(&dqp->q_pincount)) | |
67 | + wake_up(&dqp->q_pinwait); | |
68 | ||
69 | - dqp = logitem->qli_dquot; | |
70 | - ASSERT(dqp->q_pincount > 0); | |
71 | - spin_lock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock)); | |
72 | - dqp->q_pincount--; | |
73 | - if (dqp->q_pincount == 0) { | |
74 | - sv_broadcast(&dqp->q_pinwait); | |
75 | - } | |
76 | - spin_unlock(&(XFS_DQ_TO_QINF(dqp)->qi_pinlock)); | |
77 | } | |
78 | ||
79 | /* ARGSUSED */ | |
80 | @@ -193,7 +187,7 @@ xfs_qm_dqunpin_wait( | |
81 | xfs_dquot_t *dqp) | |
82 | { | |
83 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | |
84 | - if (dqp->q_pincount == 0) { | |
85 | + if (atomic_read(&dqp->q_pincount) == 0) { | |
86 | return; | |
87 | } | |
88 | ||
89 | @@ -201,13 +195,7 @@ xfs_qm_dqunpin_wait( | |
90 | * Give the log a push so we don't wait here too long. | |
91 | */ | |
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)); | |
96 | - return; | |
97 | - } | |
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)); | |
101 | } | |
102 | ||
103 | /* | |
104 | @@ -310,7 +298,7 @@ xfs_qm_dquot_logitem_trylock( | |
105 | uint retval; | |
106 | ||
107 | dqp = qip->qli_dquot; | |
108 | - if (dqp->q_pincount > 0) | |
109 | + if (atomic_read(&dqp->q_pincount) > 0) | |
110 | return (XFS_ITEM_PINNED); | |
111 | ||
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 */ | |
125 | + | |
126 | #ifdef XFS_DQUOT_TRACE | |
127 | struct ktrace *q_trace; /* trace header structure */ | |
128 | #endif | |
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( | |
134 | if (brandnewdquot) { | |
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); | |
139 | ||
140 | /* | |
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); | |
148 | dqp->q_hash = NULL; | |
149 | ASSERT(dqp->dq_flnext == dqp->dq_flprev); | |
150 | ||
151 | @@ -1489,7 +1489,7 @@ xfs_qm_dqpurge( | |
152 | "xfs_qm_dqpurge: dquot %p flush failed", dqp); | |
153 | xfs_dqflock(dqp); | |
154 | } | |
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)); | |
159 | ||
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( | |
177 | return error; | |
178 | } | |
179 | ||
180 | - spin_lock_init(&qinf->qi_pinlock); | |
181 | xfs_qm_list_init(&qinf->qi_dqlist, "mpdqlist", 0); | |
182 | qinf->qi_dqreclaims = 0; | |
183 | ||
184 | @@ -1234,7 +1233,6 @@ xfs_qm_destroy_quotainfo( | |
185 | */ | |
186 | xfs_qm_rele_quotafs_ref(mp); | |
187 | ||
188 | - spinlock_destroy(&qi->qi_pinlock); | |
189 | xfs_qm_list_destroy(&qi->qi_dqlist); | |
190 | ||
191 | if (qi->qi_uquotaip) { |