aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-09-30 00:45:03 -0400
committerAlex Elder <aelder@sgi.com>2011-10-11 22:15:09 -0400
commit670ce93fef93bba8c8a422a79747385bec8e846a (patch)
tree2f358f3c38f847cd12caf5f5f1eb3c36d586c546 /fs/xfs
parent3815832a2aa4df9815d15dac05227e0c8551833f (diff)
xfs: reduce the number of log forces from tail pushing
The AIL push code will issue a log force on ever single push loop that it exits and has encountered pinned items. It doesn't rescan these pinned items until it revisits the AIL from the start. Hence we only need to force the log once per walk from the start of the AIL to the target LSN. This results in numbers like this: xs_push_ail_flush..... 1456 xs_log_force......... 1485 For an 8-way 50M inode create workload - almost all the log forces are coming from the AIL pushing code. Reduce the number of log forces by only forcing the log if the previous walk found pinned buffers. This reduces the numbers to: xs_push_ail_flush..... 665 xs_log_force......... 682 For the same test. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_trans_ail.c33
-rw-r--r--fs/xfs/xfs_trans_priv.h1
2 files changed, 21 insertions, 13 deletions
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index c15aa29fa169..9df7f9f1b5ee 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -372,12 +372,24 @@ xfs_ail_worker(
372 xfs_lsn_t lsn; 372 xfs_lsn_t lsn;
373 xfs_lsn_t target; 373 xfs_lsn_t target;
374 long tout = 10; 374 long tout = 10;
375 int flush_log = 0;
376 int stuck = 0; 375 int stuck = 0;
377 int count = 0; 376 int count = 0;
378 int push_xfsbufd = 0; 377 int push_xfsbufd = 0;
379 378
379 /*
380 * If last time we ran we encountered pinned items, force the log first
381 * and wait for it before pushing again.
382 */
380 spin_lock(&ailp->xa_lock); 383 spin_lock(&ailp->xa_lock);
384 if (ailp->xa_last_pushed_lsn == 0 && ailp->xa_log_flush &&
385 !list_empty(&ailp->xa_ail)) {
386 ailp->xa_log_flush = 0;
387 spin_unlock(&ailp->xa_lock);
388 XFS_STATS_INC(xs_push_ail_flush);
389 xfs_log_force(mp, XFS_LOG_SYNC);
390 spin_lock(&ailp->xa_lock);
391 }
392
381 target = ailp->xa_target; 393 target = ailp->xa_target;
382 lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->xa_last_pushed_lsn); 394 lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->xa_last_pushed_lsn);
383 if (!lip || XFS_FORCED_SHUTDOWN(mp)) { 395 if (!lip || XFS_FORCED_SHUTDOWN(mp)) {
@@ -435,7 +447,7 @@ xfs_ail_worker(
435 case XFS_ITEM_PINNED: 447 case XFS_ITEM_PINNED:
436 XFS_STATS_INC(xs_push_ail_pinned); 448 XFS_STATS_INC(xs_push_ail_pinned);
437 stuck++; 449 stuck++;
438 flush_log = 1; 450 ailp->xa_log_flush++;
439 break; 451 break;
440 452
441 case XFS_ITEM_LOCKED: 453 case XFS_ITEM_LOCKED:
@@ -480,16 +492,6 @@ xfs_ail_worker(
480 xfs_trans_ail_cursor_done(ailp, &cur); 492 xfs_trans_ail_cursor_done(ailp, &cur);
481 spin_unlock(&ailp->xa_lock); 493 spin_unlock(&ailp->xa_lock);
482 494
483 if (flush_log) {
484 /*
485 * If something we need to push out was pinned, then
486 * push out the log so it will become unpinned and
487 * move forward in the AIL.
488 */
489 XFS_STATS_INC(xs_push_ail_flush);
490 xfs_log_force(mp, 0);
491 }
492
493 if (push_xfsbufd) { 495 if (push_xfsbufd) {
494 /* we've got delayed write buffers to flush */ 496 /* we've got delayed write buffers to flush */
495 wake_up_process(mp->m_ddev_targp->bt_task); 497 wake_up_process(mp->m_ddev_targp->bt_task);
@@ -500,6 +502,7 @@ out_done:
500 if (!count) { 502 if (!count) {
501 /* We're past our target or empty, so idle */ 503 /* We're past our target or empty, so idle */
502 ailp->xa_last_pushed_lsn = 0; 504 ailp->xa_last_pushed_lsn = 0;
505 ailp->xa_log_flush = 0;
503 506
504 /* 507 /*
505 * We clear the XFS_AIL_PUSHING_BIT first before checking 508 * We clear the XFS_AIL_PUSHING_BIT first before checking
@@ -532,9 +535,13 @@ out_done:
532 * were stuck. 535 * were stuck.
533 * 536 *
534 * Backoff a bit more to allow some I/O to complete before 537 * Backoff a bit more to allow some I/O to complete before
535 * continuing from where we were. 538 * restarting from the start of the AIL. This prevents us
539 * from spinning on the same items, and if they are pinned will
540 * all the restart to issue a log force to unpin the stuck
541 * items.
536 */ 542 */
537 tout = 20; 543 tout = 20;
544 ailp->xa_last_pushed_lsn = 0;
538 } 545 }
539 546
540 /* There is more to do, requeue us. */ 547 /* There is more to do, requeue us. */
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index 212946b97239..0a6eec6d472a 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -71,6 +71,7 @@ struct xfs_ail {
71 struct delayed_work xa_work; 71 struct delayed_work xa_work;
72 xfs_lsn_t xa_last_pushed_lsn; 72 xfs_lsn_t xa_last_pushed_lsn;
73 unsigned long xa_flags; 73 unsigned long xa_flags;
74 int xa_log_flush;
74}; 75};
75 76
76#define XFS_AIL_PUSHING_BIT 0 77#define XFS_AIL_PUSHING_BIT 0