Commit 3b93c7aaefc05ee2a75e2726929b01a321402984

Authored by Dave Chinner
Committed by Dave Chinner
1 parent a44f13edf0

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>

Showing 1 changed file with 26 additions and 8 deletions Side-by-side Diff

fs/xfs/xfs_log_cil.c
... ... @@ -270,15 +270,10 @@
270 270 static void
271 271 xlog_cil_format_items(
272 272 struct log *log,
273   - struct xfs_log_vec *log_vector,
274   - struct xlog_ticket *ticket,
275   - xfs_lsn_t *start_lsn)
  273 + struct xfs_log_vec *log_vector)
276 274 {
277 275 struct xfs_log_vec *lv;
278 276  
279   - if (start_lsn)
280   - *start_lsn = log->l_cilp->xc_ctx->sequence;
281   -
282 277 ASSERT(log_vector);
283 278 for (lv = log_vector; lv; lv = lv->lv_next) {
284 279 void *ptr;
285 280  
286 281  
... ... @@ -302,9 +297,24 @@
302 297 ptr += vec->i_len;
303 298 }
304 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 317 xlog_cil_insert(log, ticket, lv->lv_item, lv);
307   - }
308 318 }
309 319  
310 320 static void
311 321  
... ... @@ -612,9 +622,17 @@
612 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 633 /* lock out background commit */
616 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 637 /* check we didn't blow the reservation */
620 638 if (tp->t_ticket->t_curr_res < 0)