aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-08-23 21:45:53 -0400
committerDave Chinner <david@fromorbit.com>2010-08-23 21:45:53 -0400
commit3b93c7aaefc05ee2a75e2726929b01a321402984 (patch)
tree736a4017e86d65598ae7b30cb11412afd66f9629 /fs
parenta44f13edf0ebb4e41942d0f16ca80489dcf6659d (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')
-rw-r--r--fs/xfs/xfs_log_cil.c34
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(
270static void 270static void
271xlog_cil_format_items( 271xlog_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
303static void
304xlog_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
310static void 320static 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)