diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/quota/xfs_dquot.c | 34 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_dquot.h | 29 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_dquot_item.c | 8 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_qm.c | 8 |
4 files changed, 38 insertions, 41 deletions
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 9de42d031745..32290578c661 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c | |||
@@ -101,9 +101,16 @@ xfs_qm_dqinit( | |||
101 | if (brandnewdquot) { | 101 | if (brandnewdquot) { |
102 | dqp->dq_flnext = dqp->dq_flprev = dqp; | 102 | dqp->dq_flnext = dqp->dq_flprev = dqp; |
103 | mutex_init(&dqp->q_qlock); | 103 | mutex_init(&dqp->q_qlock); |
104 | initnsema(&dqp->q_flock, 1, "fdq"); | ||
105 | sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq"); | 104 | sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq"); |
106 | 105 | ||
106 | /* | ||
107 | * Because we want to use a counting completion, complete | ||
108 | * the flush completion once to allow a single access to | ||
109 | * the flush completion without blocking. | ||
110 | */ | ||
111 | init_completion(&dqp->q_flush); | ||
112 | complete(&dqp->q_flush); | ||
113 | |||
107 | #ifdef XFS_DQUOT_TRACE | 114 | #ifdef XFS_DQUOT_TRACE |
108 | dqp->q_trace = ktrace_alloc(DQUOT_TRACE_SIZE, KM_SLEEP); | 115 | dqp->q_trace = ktrace_alloc(DQUOT_TRACE_SIZE, KM_SLEEP); |
109 | xfs_dqtrace_entry(dqp, "DQINIT"); | 116 | xfs_dqtrace_entry(dqp, "DQINIT"); |
@@ -150,7 +157,6 @@ xfs_qm_dqdestroy( | |||
150 | ASSERT(! XFS_DQ_IS_ON_FREELIST(dqp)); | 157 | ASSERT(! XFS_DQ_IS_ON_FREELIST(dqp)); |
151 | 158 | ||
152 | mutex_destroy(&dqp->q_qlock); | 159 | mutex_destroy(&dqp->q_qlock); |
153 | freesema(&dqp->q_flock); | ||
154 | sv_destroy(&dqp->q_pinwait); | 160 | sv_destroy(&dqp->q_pinwait); |
155 | 161 | ||
156 | #ifdef XFS_DQUOT_TRACE | 162 | #ifdef XFS_DQUOT_TRACE |
@@ -1211,7 +1217,7 @@ xfs_qm_dqflush( | |||
1211 | int error; | 1217 | int error; |
1212 | 1218 | ||
1213 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 1219 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); |
1214 | ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp)); | 1220 | ASSERT(!completion_done(&dqp->q_flush)); |
1215 | xfs_dqtrace_entry(dqp, "DQFLUSH"); | 1221 | xfs_dqtrace_entry(dqp, "DQFLUSH"); |
1216 | 1222 | ||
1217 | /* | 1223 | /* |
@@ -1348,34 +1354,18 @@ xfs_qm_dqflush_done( | |||
1348 | xfs_dqfunlock(dqp); | 1354 | xfs_dqfunlock(dqp); |
1349 | } | 1355 | } |
1350 | 1356 | ||
1351 | |||
1352 | int | ||
1353 | xfs_qm_dqflock_nowait( | ||
1354 | xfs_dquot_t *dqp) | ||
1355 | { | ||
1356 | int locked; | ||
1357 | |||
1358 | locked = cpsema(&((dqp)->q_flock)); | ||
1359 | |||
1360 | /* XXX ifdef these out */ | ||
1361 | if (locked) | ||
1362 | (dqp)->dq_flags |= XFS_DQ_FLOCKED; | ||
1363 | return (locked); | ||
1364 | } | ||
1365 | |||
1366 | |||
1367 | int | 1357 | int |
1368 | xfs_qm_dqlock_nowait( | 1358 | xfs_qm_dqlock_nowait( |
1369 | xfs_dquot_t *dqp) | 1359 | xfs_dquot_t *dqp) |
1370 | { | 1360 | { |
1371 | return (mutex_trylock(&((dqp)->q_qlock))); | 1361 | return mutex_trylock(&dqp->q_qlock); |
1372 | } | 1362 | } |
1373 | 1363 | ||
1374 | void | 1364 | void |
1375 | xfs_dqlock( | 1365 | xfs_dqlock( |
1376 | xfs_dquot_t *dqp) | 1366 | xfs_dquot_t *dqp) |
1377 | { | 1367 | { |
1378 | mutex_lock(&(dqp->q_qlock)); | 1368 | mutex_lock(&dqp->q_qlock); |
1379 | } | 1369 | } |
1380 | 1370 | ||
1381 | void | 1371 | void |
@@ -1468,7 +1458,7 @@ xfs_qm_dqpurge( | |||
1468 | * if we're turning off quotas. Basically, we need this flush | 1458 | * if we're turning off quotas. Basically, we need this flush |
1469 | * lock, and are willing to block on it. | 1459 | * lock, and are willing to block on it. |
1470 | */ | 1460 | */ |
1471 | if (! xfs_qm_dqflock_nowait(dqp)) { | 1461 | if (!xfs_dqflock_nowait(dqp)) { |
1472 | /* | 1462 | /* |
1473 | * Block on the flush lock after nudging dquot buffer, | 1463 | * Block on the flush lock after nudging dquot buffer, |
1474 | * if it is incore. | 1464 | * if it is incore. |
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h index f7393bba4e95..8958d0faf8d3 100644 --- a/fs/xfs/quota/xfs_dquot.h +++ b/fs/xfs/quota/xfs_dquot.h | |||
@@ -82,7 +82,7 @@ typedef struct xfs_dquot { | |||
82 | xfs_qcnt_t q_res_icount; /* total inos allocd+reserved */ | 82 | xfs_qcnt_t q_res_icount; /* total inos allocd+reserved */ |
83 | xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */ | 83 | xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */ |
84 | mutex_t q_qlock; /* quota lock */ | 84 | mutex_t q_qlock; /* quota lock */ |
85 | sema_t q_flock; /* flush lock */ | 85 | struct completion q_flush; /* flush completion queue */ |
86 | uint q_pincount; /* pin count for this dquot */ | 86 | uint q_pincount; /* pin count for this dquot */ |
87 | sv_t q_pinwait; /* sync var for pinning */ | 87 | sv_t q_pinwait; /* sync var for pinning */ |
88 | #ifdef XFS_DQUOT_TRACE | 88 | #ifdef XFS_DQUOT_TRACE |
@@ -113,17 +113,25 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) | |||
113 | 113 | ||
114 | 114 | ||
115 | /* | 115 | /* |
116 | * The following three routines simply manage the q_flock | 116 | * Manage the q_flush completion queue embedded in the dquot. This completion |
117 | * semaphore embedded in the dquot. This semaphore synchronizes | 117 | * queue synchronizes processes attempting to flush the in-core dquot back to |
118 | * processes attempting to flush the in-core dquot back to disk. | 118 | * disk. |
119 | */ | 119 | */ |
120 | #define xfs_dqflock(dqp) { psema(&((dqp)->q_flock), PINOD | PRECALC);\ | 120 | static inline void xfs_dqflock(xfs_dquot_t *dqp) |
121 | (dqp)->dq_flags |= XFS_DQ_FLOCKED; } | 121 | { |
122 | #define xfs_dqfunlock(dqp) { ASSERT(issemalocked(&((dqp)->q_flock))); \ | 122 | wait_for_completion(&dqp->q_flush); |
123 | vsema(&((dqp)->q_flock)); \ | 123 | } |
124 | (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); } | 124 | |
125 | static inline int xfs_dqflock_nowait(xfs_dquot_t *dqp) | ||
126 | { | ||
127 | return try_wait_for_completion(&dqp->q_flush); | ||
128 | } | ||
129 | |||
130 | static inline void xfs_dqfunlock(xfs_dquot_t *dqp) | ||
131 | { | ||
132 | complete(&dqp->q_flush); | ||
133 | } | ||
125 | 134 | ||
126 | #define XFS_DQ_IS_FLUSH_LOCKED(dqp) (issemalocked(&((dqp)->q_flock))) | ||
127 | #define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) | 135 | #define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) |
128 | #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) | 136 | #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) |
129 | #define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) | 137 | #define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) |
@@ -167,7 +175,6 @@ extern int xfs_qm_dqflush(xfs_dquot_t *, uint); | |||
167 | extern int xfs_qm_dqpurge(xfs_dquot_t *); | 175 | extern int xfs_qm_dqpurge(xfs_dquot_t *); |
168 | extern void xfs_qm_dqunpin_wait(xfs_dquot_t *); | 176 | extern void xfs_qm_dqunpin_wait(xfs_dquot_t *); |
169 | extern int xfs_qm_dqlock_nowait(xfs_dquot_t *); | 177 | extern int xfs_qm_dqlock_nowait(xfs_dquot_t *); |
170 | extern int xfs_qm_dqflock_nowait(xfs_dquot_t *); | ||
171 | extern void xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp); | 178 | extern void xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp); |
172 | extern void xfs_qm_adjust_dqtimers(xfs_mount_t *, | 179 | extern void xfs_qm_adjust_dqtimers(xfs_mount_t *, |
173 | xfs_disk_dquot_t *); | 180 | xfs_disk_dquot_t *); |
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 08d2fc89e6a1..f028644caa5e 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c | |||
@@ -151,7 +151,7 @@ xfs_qm_dquot_logitem_push( | |||
151 | dqp = logitem->qli_dquot; | 151 | dqp = logitem->qli_dquot; |
152 | 152 | ||
153 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 153 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); |
154 | ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp)); | 154 | ASSERT(!completion_done(&dqp->q_flush)); |
155 | 155 | ||
156 | /* | 156 | /* |
157 | * Since we were able to lock the dquot's flush lock and | 157 | * Since we were able to lock the dquot's flush lock and |
@@ -245,7 +245,7 @@ xfs_qm_dquot_logitem_pushbuf( | |||
245 | * inode flush completed and the inode was taken off the AIL. | 245 | * inode flush completed and the inode was taken off the AIL. |
246 | * So, just get out. | 246 | * So, just get out. |
247 | */ | 247 | */ |
248 | if (!issemalocked(&(dqp->q_flock)) || | 248 | if (completion_done(&dqp->q_flush) || |
249 | ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) { | 249 | ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) { |
250 | qip->qli_pushbuf_flag = 0; | 250 | qip->qli_pushbuf_flag = 0; |
251 | xfs_dqunlock(dqp); | 251 | xfs_dqunlock(dqp); |
@@ -258,7 +258,7 @@ xfs_qm_dquot_logitem_pushbuf( | |||
258 | if (bp != NULL) { | 258 | if (bp != NULL) { |
259 | if (XFS_BUF_ISDELAYWRITE(bp)) { | 259 | if (XFS_BUF_ISDELAYWRITE(bp)) { |
260 | dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) && | 260 | dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) && |
261 | issemalocked(&(dqp->q_flock))); | 261 | !completion_done(&dqp->q_flush)); |
262 | qip->qli_pushbuf_flag = 0; | 262 | qip->qli_pushbuf_flag = 0; |
263 | xfs_dqunlock(dqp); | 263 | xfs_dqunlock(dqp); |
264 | 264 | ||
@@ -317,7 +317,7 @@ xfs_qm_dquot_logitem_trylock( | |||
317 | return (XFS_ITEM_LOCKED); | 317 | return (XFS_ITEM_LOCKED); |
318 | 318 | ||
319 | retval = XFS_ITEM_SUCCESS; | 319 | retval = XFS_ITEM_SUCCESS; |
320 | if (! xfs_qm_dqflock_nowait(dqp)) { | 320 | if (!xfs_dqflock_nowait(dqp)) { |
321 | /* | 321 | /* |
322 | * The dquot is already being flushed. It may have been | 322 | * The dquot is already being flushed. It may have been |
323 | * flushed delayed write, however, and we don't want to | 323 | * flushed delayed write, however, and we don't want to |
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 021934a3d456..3825d7484079 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -484,7 +484,7 @@ again: | |||
484 | xfs_dqtrace_entry(dqp, "FLUSHALL: DQDIRTY"); | 484 | xfs_dqtrace_entry(dqp, "FLUSHALL: DQDIRTY"); |
485 | /* XXX a sentinel would be better */ | 485 | /* XXX a sentinel would be better */ |
486 | recl = XFS_QI_MPLRECLAIMS(mp); | 486 | recl = XFS_QI_MPLRECLAIMS(mp); |
487 | if (! xfs_qm_dqflock_nowait(dqp)) { | 487 | if (!xfs_dqflock_nowait(dqp)) { |
488 | /* | 488 | /* |
489 | * If we can't grab the flush lock then check | 489 | * If we can't grab the flush lock then check |
490 | * to see if the dquot has been flushed delayed | 490 | * to see if the dquot has been flushed delayed |
@@ -1062,7 +1062,7 @@ xfs_qm_sync( | |||
1062 | 1062 | ||
1063 | /* XXX a sentinel would be better */ | 1063 | /* XXX a sentinel would be better */ |
1064 | recl = XFS_QI_MPLRECLAIMS(mp); | 1064 | recl = XFS_QI_MPLRECLAIMS(mp); |
1065 | if (! xfs_qm_dqflock_nowait(dqp)) { | 1065 | if (!xfs_dqflock_nowait(dqp)) { |
1066 | if (nowait) { | 1066 | if (nowait) { |
1067 | xfs_dqunlock(dqp); | 1067 | xfs_dqunlock(dqp); |
1068 | continue; | 1068 | continue; |
@@ -2079,7 +2079,7 @@ xfs_qm_shake_freelist( | |||
2079 | * Try to grab the flush lock. If this dquot is in the process of | 2079 | * Try to grab the flush lock. If this dquot is in the process of |
2080 | * getting flushed to disk, we don't want to reclaim it. | 2080 | * getting flushed to disk, we don't want to reclaim it. |
2081 | */ | 2081 | */ |
2082 | if (! xfs_qm_dqflock_nowait(dqp)) { | 2082 | if (!xfs_dqflock_nowait(dqp)) { |
2083 | xfs_dqunlock(dqp); | 2083 | xfs_dqunlock(dqp); |
2084 | dqp = dqp->dq_flnext; | 2084 | dqp = dqp->dq_flnext; |
2085 | continue; | 2085 | continue; |
@@ -2257,7 +2257,7 @@ xfs_qm_dqreclaim_one(void) | |||
2257 | * Try to grab the flush lock. If this dquot is in the process of | 2257 | * Try to grab the flush lock. If this dquot is in the process of |
2258 | * getting flushed to disk, we don't want to reclaim it. | 2258 | * getting flushed to disk, we don't want to reclaim it. |
2259 | */ | 2259 | */ |
2260 | if (! xfs_qm_dqflock_nowait(dqp)) { | 2260 | if (!xfs_dqflock_nowait(dqp)) { |
2261 | xfs_dqunlock(dqp); | 2261 | xfs_dqunlock(dqp); |
2262 | continue; | 2262 | continue; |
2263 | } | 2263 | } |