xfs: Fix issues found doing large inode count testing
cover xfs: Fix issues found doing large inode count testing
Two fixes - one that prevents stalls in the CIl commit subsystem when memory is low, one that brings CPu usage of the buffer cache hash down to something more sensible.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 1/2 xfs: don't do memory allocation under the CIL context lock
From: Dave Chinner <[email protected]>
Formatting items requires memory allocation when using delayed logging. Currently that memory allocation is done while holding the CIL context lock in read mode. This means that if memory allocation takes some time (e.g. enters reclaim), we cannot push on the CIL until the allocation(s) required by formatting complete. This can stall CIL pushes for some time, and once a push is stalled so are all new transaction commits.
Fix this splitting the item formatting into two steps. The first step which does the allocation and memcpy() into the allocated buffer is now done outside the CIL context lock, and only the CIL insert is done inside the CIL context lock. This avoids the stall issue.
--- fs/xfs/xfs_log_cil.c | 34 ++++++++++++++++++++++++++-------- 1 files changed, 26 insertions(+), 8 deletions(-)
fs/xfs/xfs_log_cil.c +26 -8
@@ -270,15 +270,10 @@ xlog_cil_insert(static void xlog_cil_format_items (struct log *log, -struct xfs_log_vec *log_vector, -struct xlog_ticket *ticket, -xfs_lsn_t *start_lsn) +struct xfs_log_vec *log_vector) {struct xfs_log_vec *lv; -if (start_lsn) - *start_lsn = log->l_cilp->xc_ctx->sequence; -ASSERT (log_vector);for (lv = log_vector; lv; lv = lv->lv_next) {void *ptr;
@@ -302,9 +297,24 @@ xlog_cil_format_items( ptr += vec->i_len; }ASSERT (ptr == lv->lv_buf + lv->lv_buf_len); + } +} +static void +xlog_cil_insert_items ( +struct log *log, +struct xfs_log_vec *log_vector, +struct xlog_ticket *ticket, +xfs_lsn_t *start_lsn) +{ +struct xfs_log_vec *lv; + +if (start_lsn) + *start_lsn = log->l_cilp->xc_ctx->sequence; + +ASSERT (log_vector); +for (lv = log_vector; lv; lv = lv->lv_next)xlog_cil_insert (log, ticket, lv->lv_item, lv); - } } static void
@@ -612,9 +622,17 @@ xfs_log_commit_cil(return XFS_ERROR (EIO ); } +/* +* do all the hard work of formatting items (including memory +* allocation) outside the CIL context lock. This prevents stalling CIL +* pushes when we are low on memory and a transaction commit spends a +* lot of time in memory reclaim. +*/ +xlog_cil_format_items (log, log_vector); +/* lock out background commit */ down_read (&log->l_cilp->xc_ctx_lock); -xlog_cil_format_items (log, log_vector, tp->t_ticket, commit_lsn); +xlog_cil_insert_items (log, log_vector, tp->t_ticket, commit_lsn);/* check we didn't blow the reservation */ if (tp->t_ticket->t_curr_res <0 )
Signature · 6 lines
1.7.1 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 1/2] xfs: don't do memory allocation under the CIL context lock
Looks good,
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
PATCH 2/2 xfs: improve buffer cache hash scalability
In reply to Dave ChinnerWhen doing large parallel file creates on a 16p machines, large amounts of time is being spent in _xfs_buf_find(). A system wide profile with perf top shows this:
1134740.00 19.3% _xfs_buf_find
733142.00 12.5% __ticket_spin_lockThe problem is that the hash contains 45,000 buffers, and the hash table width is only 256 buffers. That means we've got around 200 buffers per chain, and searching it is quite expensive. The hash table size needs to increase.
Secondly, every time we do a lookup, we promote the buffer we find to the head of the hash chain. This is causing cachelines to be dirtied and causes invalidation of cachelines across all CPUs that may have walked the hash chain recently. hence every walk of the hash chain is effectively a cold cache walk. Remove the promotion to avoid this invalidation.
The results are:
1045043.00 21.2% __ticket_spin_lock
326184.00 6.6% _xfs_buf_findA 70% drop in the CPU usage when looking up buffers. Unfortunately that does not result in an increase in performance underthis workload as contention on the inode_lock soaks up most of the reduction in CPU usage.
--- fs/xfs/linux-2.6/xfs_buf.c | 8 +------- fs/xfs/linux-2.6/xfs_buf.h | 1 - 2 files changed, 1 insertions(+), 8 deletions(-)
fs/xfs/linux-2.6/xfs_buf.c +1 -7
@@ -440,12 +440,7 @@ _xfs_buf_find(ASSERT (btp == bp->b_target);if (bp->b_file_offset == range_base && bp->b_buffer_length == range_length) { -/* -* If we look at something, bring it to the -* front of the list for next time. -*/ atomic_inc (&bp->b_hold); -list_move (&bp->b_hash_list, &hash->bh_list); goto found; } }
@@ -1443,8 +1438,7 @@ xfs_alloc_bufhash( {unsigned int i; - btp->bt_hashshift = external ?3 :8 ;/* 8 or 256 buckets */ - btp->bt_hashmask = (1 << btp->bt_hashshift) -1 ; + btp->bt_hashshift = external ?3 :12 ;/* 8 or 4096 buckets */ btp->bt_hash =kmem_zalloc_large ((1 << btp->bt_hashshift) *sizeof (xfs_bufhash_t));for (i =0 ; i < (1 << btp->bt_hashshift); i++) {
fs/xfs/linux-2.6/xfs_buf.h +0 -1
@@ -137,7 +137,6 @@ typedef struct xfs_buftarg {size_t bt_smask;/* per device buffer hash table */ -uint bt_hashmask;uint bt_hashshift;xfs_bufhash_t *bt_hash;
Signature · 6 lines
1.7.1 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 2/2] xfs: improve buffer cache hash scalability
fs/xfs/linux-2.6/xfs_buf.c xfs_alloc_bufhash( · line 1441
Quoted 7 lines
fs/xfs/linux-2.6/xfs_buf.c +1
-2@@ -1443,8 +1438,7 @@ xfs_alloc_bufhash( {unsigned int i; - btp->bt_hashshift = external ?3 :8 ;/* 8 or 256 buckets */ - btp->bt_hashmask = (1 << btp->bt_hashshift) -1 ; + btp->bt_hashshift = external ?3 :12 ;/* 8 or 4096 buckets */
Not directly related to the patch, but we never have hashes buffers on the log device. And on the RT device we only use hashed buffers twice to verify the device size. With a little work on the latter we can stop allocating the buf hash entirely for the RT and log devices.
Anyway, the patch looks good for now, although we should try to get rid of the hash long term.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Re: [PATCH 2/2] xfs: improve buffer cache hash scalability
In reply to Dave ChinnerQuoted 10 lines · Dave Chinner
When doing large parallel file creates on a 16p machines, large amounts of time is being spent in
_xfs_buf_find(). A system wide profile with perf top shows this:1134740.00 19.3% _xfs_buf_find 733142.00 12.5% __ticket_spin_lockThe problem is that the hash contains 45,000 buffers, and the hash table width is only 256 buffers. That means we've got around 200 buffers per chain, and searching it is quite expensive. The hash table size needs to increase.
My only comment on this is that 4096 buckets is good now but someday that may not be right either. Is there any better way (based on size of underlying block_device and maybe taking into account other things like page size or CPU count) to decide this hash size?
Either way it looks good.
. . .
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs