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>
This commit is contained in:
parent
3815832a2a
commit
670ce93fef
|
@ -372,12 +372,24 @@ xfs_ail_worker(
|
|||
xfs_lsn_t lsn;
|
||||
xfs_lsn_t target;
|
||||
long tout = 10;
|
||||
int flush_log = 0;
|
||||
int stuck = 0;
|
||||
int count = 0;
|
||||
int push_xfsbufd = 0;
|
||||
|
||||
/*
|
||||
* If last time we ran we encountered pinned items, force the log first
|
||||
* and wait for it before pushing again.
|
||||
*/
|
||||
spin_lock(&ailp->xa_lock);
|
||||
if (ailp->xa_last_pushed_lsn == 0 && ailp->xa_log_flush &&
|
||||
!list_empty(&ailp->xa_ail)) {
|
||||
ailp->xa_log_flush = 0;
|
||||
spin_unlock(&ailp->xa_lock);
|
||||
XFS_STATS_INC(xs_push_ail_flush);
|
||||
xfs_log_force(mp, XFS_LOG_SYNC);
|
||||
spin_lock(&ailp->xa_lock);
|
||||
}
|
||||
|
||||
target = ailp->xa_target;
|
||||
lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->xa_last_pushed_lsn);
|
||||
if (!lip || XFS_FORCED_SHUTDOWN(mp)) {
|
||||
|
@ -435,7 +447,7 @@ xfs_ail_worker(
|
|||
case XFS_ITEM_PINNED:
|
||||
XFS_STATS_INC(xs_push_ail_pinned);
|
||||
stuck++;
|
||||
flush_log = 1;
|
||||
ailp->xa_log_flush++;
|
||||
break;
|
||||
|
||||
case XFS_ITEM_LOCKED:
|
||||
|
@ -480,16 +492,6 @@ xfs_ail_worker(
|
|||
xfs_trans_ail_cursor_done(ailp, &cur);
|
||||
spin_unlock(&ailp->xa_lock);
|
||||
|
||||
if (flush_log) {
|
||||
/*
|
||||
* If something we need to push out was pinned, then
|
||||
* push out the log so it will become unpinned and
|
||||
* move forward in the AIL.
|
||||
*/
|
||||
XFS_STATS_INC(xs_push_ail_flush);
|
||||
xfs_log_force(mp, 0);
|
||||
}
|
||||
|
||||
if (push_xfsbufd) {
|
||||
/* we've got delayed write buffers to flush */
|
||||
wake_up_process(mp->m_ddev_targp->bt_task);
|
||||
|
@ -500,6 +502,7 @@ out_done:
|
|||
if (!count) {
|
||||
/* We're past our target or empty, so idle */
|
||||
ailp->xa_last_pushed_lsn = 0;
|
||||
ailp->xa_log_flush = 0;
|
||||
|
||||
/*
|
||||
* We clear the XFS_AIL_PUSHING_BIT first before checking
|
||||
|
@ -532,9 +535,13 @@ out_done:
|
|||
* were stuck.
|
||||
*
|
||||
* Backoff a bit more to allow some I/O to complete before
|
||||
* continuing from where we were.
|
||||
* restarting from the start of the AIL. This prevents us
|
||||
* from spinning on the same items, and if they are pinned will
|
||||
* all the restart to issue a log force to unpin the stuck
|
||||
* items.
|
||||
*/
|
||||
tout = 20;
|
||||
ailp->xa_last_pushed_lsn = 0;
|
||||
}
|
||||
|
||||
/* There is more to do, requeue us. */
|
||||
|
|
|
@ -71,6 +71,7 @@ struct xfs_ail {
|
|||
struct delayed_work xa_work;
|
||||
xfs_lsn_t xa_last_pushed_lsn;
|
||||
unsigned long xa_flags;
|
||||
int xa_log_flush;
|
||||
};
|
||||
|
||||
#define XFS_AIL_PUSHING_BIT 0
|
||||
|
|
Loading…
Reference in a new issue