diff options
Diffstat (limited to 'fs/xfs/xfs_log_cil.c')
-rw-r--r-- | fs/xfs/xfs_log_cil.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index 53abd6b0a33..9b21f80f31c 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c | |||
@@ -336,6 +336,7 @@ xfs_log_commit_cil( | |||
336 | { | 336 | { |
337 | struct log *log = mp->m_log; | 337 | struct log *log = mp->m_log; |
338 | int log_flags = 0; | 338 | int log_flags = 0; |
339 | int push = 0; | ||
339 | 340 | ||
340 | if (flags & XFS_TRANS_RELEASE_LOG_RES) | 341 | if (flags & XFS_TRANS_RELEASE_LOG_RES) |
341 | log_flags = XFS_LOG_REL_PERM_RESERV; | 342 | log_flags = XFS_LOG_REL_PERM_RESERV; |
@@ -365,8 +366,20 @@ xfs_log_commit_cil( | |||
365 | xfs_log_done(mp, tp->t_ticket, NULL, log_flags); | 366 | xfs_log_done(mp, tp->t_ticket, NULL, log_flags); |
366 | xfs_trans_unreserve_and_mod_sb(tp); | 367 | xfs_trans_unreserve_and_mod_sb(tp); |
367 | 368 | ||
368 | /* background commit is allowed again */ | 369 | /* check for background commit before unlock */ |
370 | if (log->l_cilp->xc_ctx->space_used > XLOG_CIL_SPACE_LIMIT(log)) | ||
371 | push = 1; | ||
369 | up_read(&log->l_cilp->xc_ctx_lock); | 372 | up_read(&log->l_cilp->xc_ctx_lock); |
373 | |||
374 | /* | ||
375 | * We need to push CIL every so often so we don't cache more than we | ||
376 | * can fit in the log. The limit really is that a checkpoint can't be | ||
377 | * more than half the log (the current checkpoint is not allowed to | ||
378 | * overwrite the previous checkpoint), but commit latency and memory | ||
379 | * usage limit this to a smaller size in most cases. | ||
380 | */ | ||
381 | if (push) | ||
382 | xlog_cil_push(log, 0); | ||
370 | return 0; | 383 | return 0; |
371 | } | 384 | } |
372 | 385 | ||
@@ -429,18 +442,25 @@ xlog_cil_push( | |||
429 | if (!cil) | 442 | if (!cil) |
430 | return 0; | 443 | return 0; |
431 | 444 | ||
432 | /* XXX: don't sleep for background? */ | ||
433 | new_ctx = kmem_zalloc(sizeof(*new_ctx), KM_SLEEP|KM_NOFS); | 445 | new_ctx = kmem_zalloc(sizeof(*new_ctx), KM_SLEEP|KM_NOFS); |
434 | new_ctx->ticket = xlog_cil_ticket_alloc(log); | 446 | new_ctx->ticket = xlog_cil_ticket_alloc(log); |
435 | 447 | ||
436 | /* lock out transaction commit */ | 448 | /* lock out transaction commit, but don't block on background push */ |
437 | down_write(&cil->xc_ctx_lock); | 449 | if (!down_write_trylock(&cil->xc_ctx_lock)) { |
450 | if (!push_now) | ||
451 | goto out_free_ticket; | ||
452 | down_write(&cil->xc_ctx_lock); | ||
453 | } | ||
438 | ctx = cil->xc_ctx; | 454 | ctx = cil->xc_ctx; |
439 | 455 | ||
440 | /* check if we've anything to push */ | 456 | /* check if we've anything to push */ |
441 | if (list_empty(&cil->xc_cil)) | 457 | if (list_empty(&cil->xc_cil)) |
442 | goto out_skip; | 458 | goto out_skip; |
443 | 459 | ||
460 | /* check for spurious background flush */ | ||
461 | if (!push_now && cil->xc_ctx->space_used < XLOG_CIL_SPACE_LIMIT(log)) | ||
462 | goto out_skip; | ||
463 | |||
444 | /* | 464 | /* |
445 | * pull all the log vectors off the items in the CIL, and | 465 | * pull all the log vectors off the items in the CIL, and |
446 | * remove the items from the CIL. We don't need the CIL lock | 466 | * remove the items from the CIL. We don't need the CIL lock |
@@ -584,6 +604,7 @@ restart: | |||
584 | 604 | ||
585 | out_skip: | 605 | out_skip: |
586 | up_write(&cil->xc_ctx_lock); | 606 | up_write(&cil->xc_ctx_lock); |
607 | out_free_ticket: | ||
587 | xfs_log_ticket_put(new_ctx->ticket); | 608 | xfs_log_ticket_put(new_ctx->ticket); |
588 | kmem_free(new_ctx); | 609 | kmem_free(new_ctx); |
589 | return 0; | 610 | return 0; |