aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/quota
diff options
context:
space:
mode:
authorDave Chinner <david@fromorbit.com>2010-02-01 18:13:42 -0500
committerDave Chinner <david@fromorbit.com>2010-02-01 18:13:42 -0500
commitd808f617ad00a413585b806de340feda5ad9a2da (patch)
treeed03d4d019a9d8b566ffd454e112e9fbce70bad8 /fs/xfs/quota
parentc854363e80b49dd04a4de18ebc379eb8c8806674 (diff)
xfs: Don't issue buffer IO direct from AIL push V2
All buffers logged into the AIL are marked as delayed write. When the AIL needs to push the buffer out, it issues an async write of the buffer. This means that IO patterns are dependent on the order of buffers in the AIL. Instead of flushing the buffer, promote the buffer in the delayed write list so that the next time the xfsbufd is run the buffer will be flushed by the xfsbufd. Return the state to the xfsaild that the buffer was promoted so that the xfsaild knows that it needs to cause the xfsbufd to run to flush the buffers that were promoted. Using the xfsbufd for issuing the IO allows us to dispatch all buffer IO from the one queue. This means that we can make much more enlightened decisions on what order to flush buffers to disk as we don't have multiple places issuing IO. Optimisations to xfsbufd will be in a future patch. Version 2 - kill XFS_ITEM_FLUSHING as it is now unused. Signed-off-by: Dave Chinner <david@fromorbit.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs/quota')
-rw-r--r--fs/xfs/quota/xfs_dquot_item.c85
-rw-r--r--fs/xfs/quota/xfs_dquot_item.h4
2 files changed, 12 insertions, 77 deletions
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index 1b564376d50c..dda0fb045c8a 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -212,66 +212,31 @@ xfs_qm_dquot_logitem_pushbuf(
212 xfs_dquot_t *dqp; 212 xfs_dquot_t *dqp;
213 xfs_mount_t *mp; 213 xfs_mount_t *mp;
214 xfs_buf_t *bp; 214 xfs_buf_t *bp;
215 uint dopush;
216 215
217 dqp = qip->qli_dquot; 216 dqp = qip->qli_dquot;
218 ASSERT(XFS_DQ_IS_LOCKED(dqp)); 217 ASSERT(XFS_DQ_IS_LOCKED(dqp));
219 218
220 /* 219 /*
221 * The qli_pushbuf_flag keeps others from
222 * trying to duplicate our effort.
223 */
224 ASSERT(qip->qli_pushbuf_flag != 0);
225 ASSERT(qip->qli_push_owner == current_pid());
226
227 /*
228 * If flushlock isn't locked anymore, chances are that the 220 * If flushlock isn't locked anymore, chances are that the
229 * inode flush completed and the inode was taken off the AIL. 221 * inode flush completed and the inode was taken off the AIL.
230 * So, just get out. 222 * So, just get out.
231 */ 223 */
232 if (completion_done(&dqp->q_flush) || 224 if (completion_done(&dqp->q_flush) ||
233 ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) { 225 ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) {
234 qip->qli_pushbuf_flag = 0;
235 xfs_dqunlock(dqp); 226 xfs_dqunlock(dqp);
236 return; 227 return;
237 } 228 }
238 mp = dqp->q_mount; 229 mp = dqp->q_mount;
239 bp = xfs_incore(mp->m_ddev_targp, qip->qli_format.qlf_blkno, 230 bp = xfs_incore(mp->m_ddev_targp, qip->qli_format.qlf_blkno,
240 XFS_QI_DQCHUNKLEN(mp), XBF_TRYLOCK); 231 XFS_QI_DQCHUNKLEN(mp), XBF_TRYLOCK);
241 if (bp != NULL) { 232 xfs_dqunlock(dqp);
242 if (XFS_BUF_ISDELAYWRITE(bp)) { 233 if (!bp)
243 dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) &&
244 !completion_done(&dqp->q_flush));
245 qip->qli_pushbuf_flag = 0;
246 xfs_dqunlock(dqp);
247
248 if (XFS_BUF_ISPINNED(bp))
249 xfs_log_force(mp, 0);
250
251 if (dopush) {
252 int error;
253#ifdef XFSRACEDEBUG
254 delay_for_intr();
255 delay(300);
256#endif
257 error = xfs_bawrite(mp, bp);
258 if (error)
259 xfs_fs_cmn_err(CE_WARN, mp,
260 "xfs_qm_dquot_logitem_pushbuf: pushbuf error %d on qip %p, bp %p",
261 error, qip, bp);
262 } else {
263 xfs_buf_relse(bp);
264 }
265 } else {
266 qip->qli_pushbuf_flag = 0;
267 xfs_dqunlock(dqp);
268 xfs_buf_relse(bp);
269 }
270 return; 234 return;
271 } 235 if (XFS_BUF_ISDELAYWRITE(bp))
236 xfs_buf_delwri_promote(bp);
237 xfs_buf_relse(bp);
238 return;
272 239
273 qip->qli_pushbuf_flag = 0;
274 xfs_dqunlock(dqp);
275} 240}
276 241
277/* 242/*
@@ -289,50 +254,24 @@ xfs_qm_dquot_logitem_trylock(
289 xfs_dq_logitem_t *qip) 254 xfs_dq_logitem_t *qip)
290{ 255{
291 xfs_dquot_t *dqp; 256 xfs_dquot_t *dqp;
292 uint retval;
293 257
294 dqp = qip->qli_dquot; 258 dqp = qip->qli_dquot;
295 if (atomic_read(&dqp->q_pincount) > 0) 259 if (atomic_read(&dqp->q_pincount) > 0)
296 return (XFS_ITEM_PINNED); 260 return XFS_ITEM_PINNED;
297 261
298 if (! xfs_qm_dqlock_nowait(dqp)) 262 if (! xfs_qm_dqlock_nowait(dqp))
299 return (XFS_ITEM_LOCKED); 263 return XFS_ITEM_LOCKED;
300 264
301 retval = XFS_ITEM_SUCCESS;
302 if (!xfs_dqflock_nowait(dqp)) { 265 if (!xfs_dqflock_nowait(dqp)) {
303 /* 266 /*
304 * The dquot is already being flushed. It may have been 267 * dquot has already been flushed to the backing buffer,
305 * flushed delayed write, however, and we don't want to 268 * leave it locked, pushbuf routine will unlock it.
306 * get stuck waiting for that to complete. So, we want to check
307 * to see if we can lock the dquot's buffer without sleeping.
308 * If we can and it is marked for delayed write, then we
309 * hold it and send it out from the push routine. We don't
310 * want to do that now since we might sleep in the device
311 * strategy routine. We also don't want to grab the buffer lock
312 * here because we'd like not to call into the buffer cache
313 * while holding the AIL lock.
314 * Make sure to only return PUSHBUF if we set pushbuf_flag
315 * ourselves. If someone else is doing it then we don't
316 * want to go to the push routine and duplicate their efforts.
317 */ 269 */
318 if (qip->qli_pushbuf_flag == 0) { 270 return XFS_ITEM_PUSHBUF;
319 qip->qli_pushbuf_flag = 1;
320 ASSERT(qip->qli_format.qlf_blkno == dqp->q_blkno);
321#ifdef DEBUG
322 qip->qli_push_owner = current_pid();
323#endif
324 /*
325 * The dquot is left locked.
326 */
327 retval = XFS_ITEM_PUSHBUF;
328 } else {
329 retval = XFS_ITEM_FLUSHING;
330 xfs_dqunlock_nonotify(dqp);
331 }
332 } 271 }
333 272
334 ASSERT(qip->qli_item.li_flags & XFS_LI_IN_AIL); 273 ASSERT(qip->qli_item.li_flags & XFS_LI_IN_AIL);
335 return (retval); 274 return XFS_ITEM_SUCCESS;
336} 275}
337 276
338 277
diff --git a/fs/xfs/quota/xfs_dquot_item.h b/fs/xfs/quota/xfs_dquot_item.h
index 5a632531f843..5acae2ada70b 100644
--- a/fs/xfs/quota/xfs_dquot_item.h
+++ b/fs/xfs/quota/xfs_dquot_item.h
@@ -27,10 +27,6 @@ typedef struct xfs_dq_logitem {
27 xfs_log_item_t qli_item; /* common portion */ 27 xfs_log_item_t qli_item; /* common portion */
28 struct xfs_dquot *qli_dquot; /* dquot ptr */ 28 struct xfs_dquot *qli_dquot; /* dquot ptr */
29 xfs_lsn_t qli_flush_lsn; /* lsn at last flush */ 29 xfs_lsn_t qli_flush_lsn; /* lsn at last flush */
30 unsigned short qli_pushbuf_flag; /* 1 bit used in push_ail */
31#ifdef DEBUG
32 uint64_t qli_push_owner;
33#endif
34 xfs_dq_logformat_t qli_format; /* logged structure */ 30 xfs_dq_logformat_t qli_format; /* logged structure */
35} xfs_dq_logitem_t; 31} xfs_dq_logitem_t;
36 32