aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-08-12 06:50:08 -0400
committerBen Myers <bpm@sgi.com>2013-08-13 17:21:21 -0400
commit4bb928cdb900d0614f4766d5f1ca5bc3844f7656 (patch)
tree9bbc2d358dc02c3ff2d9a39cf91c9b485cba288d /fs/xfs
parent991aaf65ff0addc2692cfa8dc1ff082dcf69d26f (diff)
xfs: split the CIL lock
The xc_cil_lock is used for two purposes - to protect the CIL itself, and to protect the push/commit state and lists. These are two logically separate structures and operations, so can have their own locks. This means that pushing on the CIL and the commit wait ordering won't contend for a lock with other transactions that are completing concurrently. As the CIL insertion is the hottest path throught eh CIL, this is a big win. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_log_cil.c41
-rw-r--r--fs/xfs/xfs_log_priv.h9
2 files changed, 27 insertions, 23 deletions
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index c1a3384406fd..cfe97973ba36 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -402,9 +402,9 @@ xlog_cil_committed(
402 xfs_extent_busy_clear(mp, &ctx->busy_extents, 402 xfs_extent_busy_clear(mp, &ctx->busy_extents,
403 (mp->m_flags & XFS_MOUNT_DISCARD) && !abort); 403 (mp->m_flags & XFS_MOUNT_DISCARD) && !abort);
404 404
405 spin_lock(&ctx->cil->xc_cil_lock); 405 spin_lock(&ctx->cil->xc_push_lock);
406 list_del(&ctx->committing); 406 list_del(&ctx->committing);
407 spin_unlock(&ctx->cil->xc_cil_lock); 407 spin_unlock(&ctx->cil->xc_push_lock);
408 408
409 xlog_cil_free_logvec(ctx->lv_chain); 409 xlog_cil_free_logvec(ctx->lv_chain);
410 410
@@ -459,7 +459,7 @@ xlog_cil_push(
459 down_write(&cil->xc_ctx_lock); 459 down_write(&cil->xc_ctx_lock);
460 ctx = cil->xc_ctx; 460 ctx = cil->xc_ctx;
461 461
462 spin_lock(&cil->xc_cil_lock); 462 spin_lock(&cil->xc_push_lock);
463 push_seq = cil->xc_push_seq; 463 push_seq = cil->xc_push_seq;
464 ASSERT(push_seq <= ctx->sequence); 464 ASSERT(push_seq <= ctx->sequence);
465 465
@@ -470,10 +470,10 @@ xlog_cil_push(
470 */ 470 */
471 if (list_empty(&cil->xc_cil)) { 471 if (list_empty(&cil->xc_cil)) {
472 cil->xc_push_seq = 0; 472 cil->xc_push_seq = 0;
473 spin_unlock(&cil->xc_cil_lock); 473 spin_unlock(&cil->xc_push_lock);
474 goto out_skip; 474 goto out_skip;
475 } 475 }
476 spin_unlock(&cil->xc_cil_lock); 476 spin_unlock(&cil->xc_push_lock);
477 477
478 478
479 /* check for a previously pushed seqeunce */ 479 /* check for a previously pushed seqeunce */
@@ -541,9 +541,9 @@ xlog_cil_push(
541 * that higher sequences will wait for us to write out a commit record 541 * that higher sequences will wait for us to write out a commit record
542 * before they do. 542 * before they do.
543 */ 543 */
544 spin_lock(&cil->xc_cil_lock); 544 spin_lock(&cil->xc_push_lock);
545 list_add(&ctx->committing, &cil->xc_committing); 545 list_add(&ctx->committing, &cil->xc_committing);
546 spin_unlock(&cil->xc_cil_lock); 546 spin_unlock(&cil->xc_push_lock);
547 up_write(&cil->xc_ctx_lock); 547 up_write(&cil->xc_ctx_lock);
548 548
549 /* 549 /*
@@ -578,7 +578,7 @@ xlog_cil_push(
578 * order the commit records so replay will get them in the right order. 578 * order the commit records so replay will get them in the right order.
579 */ 579 */
580restart: 580restart:
581 spin_lock(&cil->xc_cil_lock); 581 spin_lock(&cil->xc_push_lock);
582 list_for_each_entry(new_ctx, &cil->xc_committing, committing) { 582 list_for_each_entry(new_ctx, &cil->xc_committing, committing) {
583 /* 583 /*
584 * Higher sequences will wait for this one so skip them. 584 * Higher sequences will wait for this one so skip them.
@@ -591,11 +591,11 @@ restart:
591 * It is still being pushed! Wait for the push to 591 * It is still being pushed! Wait for the push to
592 * complete, then start again from the beginning. 592 * complete, then start again from the beginning.
593 */ 593 */
594 xlog_wait(&cil->xc_commit_wait, &cil->xc_cil_lock); 594 xlog_wait(&cil->xc_commit_wait, &cil->xc_push_lock);
595 goto restart; 595 goto restart;
596 } 596 }
597 } 597 }
598 spin_unlock(&cil->xc_cil_lock); 598 spin_unlock(&cil->xc_push_lock);
599 599
600 /* xfs_log_done always frees the ticket on error. */ 600 /* xfs_log_done always frees the ticket on error. */
601 commit_lsn = xfs_log_done(log->l_mp, tic, &commit_iclog, 0); 601 commit_lsn = xfs_log_done(log->l_mp, tic, &commit_iclog, 0);
@@ -614,10 +614,10 @@ restart:
614 * callbacks to the iclog we can assign the commit LSN to the context 614 * callbacks to the iclog we can assign the commit LSN to the context
615 * and wake up anyone who is waiting for the commit to complete. 615 * and wake up anyone who is waiting for the commit to complete.
616 */ 616 */
617 spin_lock(&cil->xc_cil_lock); 617 spin_lock(&cil->xc_push_lock);
618 ctx->commit_lsn = commit_lsn; 618 ctx->commit_lsn = commit_lsn;
619 wake_up_all(&cil->xc_commit_wait); 619 wake_up_all(&cil->xc_commit_wait);
620 spin_unlock(&cil->xc_cil_lock); 620 spin_unlock(&cil->xc_push_lock);
621 621
622 /* release the hounds! */ 622 /* release the hounds! */
623 return xfs_log_release_iclog(log->l_mp, commit_iclog); 623 return xfs_log_release_iclog(log->l_mp, commit_iclog);
@@ -670,12 +670,12 @@ xlog_cil_push_background(
670 if (cil->xc_ctx->space_used < XLOG_CIL_SPACE_LIMIT(log)) 670 if (cil->xc_ctx->space_used < XLOG_CIL_SPACE_LIMIT(log))
671 return; 671 return;
672 672
673 spin_lock(&cil->xc_cil_lock); 673 spin_lock(&cil->xc_push_lock);
674 if (cil->xc_push_seq < cil->xc_current_sequence) { 674 if (cil->xc_push_seq < cil->xc_current_sequence) {
675 cil->xc_push_seq = cil->xc_current_sequence; 675 cil->xc_push_seq = cil->xc_current_sequence;
676 queue_work(log->l_mp->m_cil_workqueue, &cil->xc_push_work); 676 queue_work(log->l_mp->m_cil_workqueue, &cil->xc_push_work);
677 } 677 }
678 spin_unlock(&cil->xc_cil_lock); 678 spin_unlock(&cil->xc_push_lock);
679 679
680} 680}
681 681
@@ -698,14 +698,14 @@ xlog_cil_push_foreground(
698 * If the CIL is empty or we've already pushed the sequence then 698 * If the CIL is empty or we've already pushed the sequence then
699 * there's no work we need to do. 699 * there's no work we need to do.
700 */ 700 */
701 spin_lock(&cil->xc_cil_lock); 701 spin_lock(&cil->xc_push_lock);
702 if (list_empty(&cil->xc_cil) || push_seq <= cil->xc_push_seq) { 702 if (list_empty(&cil->xc_cil) || push_seq <= cil->xc_push_seq) {
703 spin_unlock(&cil->xc_cil_lock); 703 spin_unlock(&cil->xc_push_lock);
704 return; 704 return;
705 } 705 }
706 706
707 cil->xc_push_seq = push_seq; 707 cil->xc_push_seq = push_seq;
708 spin_unlock(&cil->xc_cil_lock); 708 spin_unlock(&cil->xc_push_lock);
709 709
710 /* do the push now */ 710 /* do the push now */
711 xlog_cil_push(log); 711 xlog_cil_push(log);
@@ -808,7 +808,7 @@ xlog_cil_force_lsn(
808 * on commits for those as well. 808 * on commits for those as well.
809 */ 809 */
810restart: 810restart:
811 spin_lock(&cil->xc_cil_lock); 811 spin_lock(&cil->xc_push_lock);
812 list_for_each_entry(ctx, &cil->xc_committing, committing) { 812 list_for_each_entry(ctx, &cil->xc_committing, committing) {
813 if (ctx->sequence > sequence) 813 if (ctx->sequence > sequence)
814 continue; 814 continue;
@@ -817,7 +817,7 @@ restart:
817 * It is still being pushed! Wait for the push to 817 * It is still being pushed! Wait for the push to
818 * complete, then start again from the beginning. 818 * complete, then start again from the beginning.
819 */ 819 */
820 xlog_wait(&cil->xc_commit_wait, &cil->xc_cil_lock); 820 xlog_wait(&cil->xc_commit_wait, &cil->xc_push_lock);
821 goto restart; 821 goto restart;
822 } 822 }
823 if (ctx->sequence != sequence) 823 if (ctx->sequence != sequence)
@@ -825,7 +825,7 @@ restart:
825 /* found it! */ 825 /* found it! */
826 commit_lsn = ctx->commit_lsn; 826 commit_lsn = ctx->commit_lsn;
827 } 827 }
828 spin_unlock(&cil->xc_cil_lock); 828 spin_unlock(&cil->xc_push_lock);
829 return commit_lsn; 829 return commit_lsn;
830} 830}
831 831
@@ -883,6 +883,7 @@ xlog_cil_init(
883 INIT_LIST_HEAD(&cil->xc_cil); 883 INIT_LIST_HEAD(&cil->xc_cil);
884 INIT_LIST_HEAD(&cil->xc_committing); 884 INIT_LIST_HEAD(&cil->xc_committing);
885 spin_lock_init(&cil->xc_cil_lock); 885 spin_lock_init(&cil->xc_cil_lock);
886 spin_lock_init(&cil->xc_push_lock);
886 init_rwsem(&cil->xc_ctx_lock); 887 init_rwsem(&cil->xc_ctx_lock);
887 init_waitqueue_head(&cil->xc_commit_wait); 888 init_waitqueue_head(&cil->xc_commit_wait);
888 889
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index edd0964fb65c..136654b9400d 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -278,14 +278,17 @@ struct xfs_cil {
278 struct xlog *xc_log; 278 struct xlog *xc_log;
279 struct list_head xc_cil; 279 struct list_head xc_cil;
280 spinlock_t xc_cil_lock; 280 spinlock_t xc_cil_lock;
281
282 struct rw_semaphore xc_ctx_lock ____cacheline_aligned_in_smp;
281 struct xfs_cil_ctx *xc_ctx; 283 struct xfs_cil_ctx *xc_ctx;
282 struct rw_semaphore xc_ctx_lock; 284
285 spinlock_t xc_push_lock ____cacheline_aligned_in_smp;
286 xfs_lsn_t xc_push_seq;
283 struct list_head xc_committing; 287 struct list_head xc_committing;
284 wait_queue_head_t xc_commit_wait; 288 wait_queue_head_t xc_commit_wait;
285 xfs_lsn_t xc_current_sequence; 289 xfs_lsn_t xc_current_sequence;
286 struct work_struct xc_push_work; 290 struct work_struct xc_push_work;
287 xfs_lsn_t xc_push_seq; 291} ____cacheline_aligned_in_smp;
288};
289 292
290/* 293/*
291 * The amount of log space we allow the CIL to aggregate is difficult to size. 294 * The amount of log space we allow the CIL to aggregate is difficult to size.