diff options
author | Dave Chinner <dchinner@redhat.com> | 2010-08-23 21:45:53 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2010-08-23 21:45:53 -0400 |
commit | 3b93c7aaefc05ee2a75e2726929b01a321402984 (patch) | |
tree | 736a4017e86d65598ae7b30cb11412afd66f9629 /fs/xfs | |
parent | a44f13edf0ebb4e41942d0f16ca80489dcf6659d (diff) |
xfs: don't do memory allocation under the CIL context lock
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.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_log_cil.c | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index 9768f2437bb3..ed575fb4b495 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c | |||
@@ -270,15 +270,10 @@ xlog_cil_insert( | |||
270 | static void | 270 | static void |
271 | xlog_cil_format_items( | 271 | xlog_cil_format_items( |
272 | struct log *log, | 272 | struct log *log, |
273 | struct xfs_log_vec *log_vector, | 273 | struct xfs_log_vec *log_vector) |
274 | struct xlog_ticket *ticket, | ||
275 | xfs_lsn_t *start_lsn) | ||
276 | { | 274 | { |
277 | struct xfs_log_vec *lv; | 275 | struct xfs_log_vec *lv; |
278 | 276 | ||
279 | if (start_lsn) | ||
280 | *start_lsn = log->l_cilp->xc_ctx->sequence; | ||
281 | |||
282 | ASSERT(log_vector); | 277 | ASSERT(log_vector); |
283 | for (lv = log_vector; lv; lv = lv->lv_next) { | 278 | for (lv = log_vector; lv; lv = lv->lv_next) { |
284 | void *ptr; | 279 | void *ptr; |
@@ -302,9 +297,24 @@ xlog_cil_format_items( | |||
302 | ptr += vec->i_len; | 297 | ptr += vec->i_len; |
303 | } | 298 | } |
304 | ASSERT(ptr == lv->lv_buf + lv->lv_buf_len); | 299 | ASSERT(ptr == lv->lv_buf + lv->lv_buf_len); |
300 | } | ||
301 | } | ||
305 | 302 | ||
303 | static void | ||
304 | xlog_cil_insert_items( | ||
305 | struct log *log, | ||
306 | struct xfs_log_vec *log_vector, | ||
307 | struct xlog_ticket *ticket, | ||
308 | xfs_lsn_t *start_lsn) | ||
309 | { | ||
310 | struct xfs_log_vec *lv; | ||
311 | |||
312 | if (start_lsn) | ||
313 | *start_lsn = log->l_cilp->xc_ctx->sequence; | ||
314 | |||
315 | ASSERT(log_vector); | ||
316 | for (lv = log_vector; lv; lv = lv->lv_next) | ||
306 | xlog_cil_insert(log, ticket, lv->lv_item, lv); | 317 | xlog_cil_insert(log, ticket, lv->lv_item, lv); |
307 | } | ||
308 | } | 318 | } |
309 | 319 | ||
310 | static void | 320 | static void |
@@ -612,9 +622,17 @@ xfs_log_commit_cil( | |||
612 | return XFS_ERROR(EIO); | 622 | return XFS_ERROR(EIO); |
613 | } | 623 | } |
614 | 624 | ||
625 | /* | ||
626 | * do all the hard work of formatting items (including memory | ||
627 | * allocation) outside the CIL context lock. This prevents stalling CIL | ||
628 | * pushes when we are low on memory and a transaction commit spends a | ||
629 | * lot of time in memory reclaim. | ||
630 | */ | ||
631 | xlog_cil_format_items(log, log_vector); | ||
632 | |||
615 | /* lock out background commit */ | 633 | /* lock out background commit */ |
616 | down_read(&log->l_cilp->xc_ctx_lock); | 634 | down_read(&log->l_cilp->xc_ctx_lock); |
617 | xlog_cil_format_items(log, log_vector, tp->t_ticket, commit_lsn); | 635 | xlog_cil_insert_items(log, log_vector, tp->t_ticket, commit_lsn); |
618 | 636 | ||
619 | /* check we didn't blow the reservation */ | 637 | /* check we didn't blow the reservation */ |
620 | if (tp->t_ticket->t_curr_res < 0) | 638 | if (tp->t_ticket->t_curr_res < 0) |