Commit 4bb928cd authored by Dave Chinner's avatar Dave Chinner Committed by Ben Myers

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: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarMark Tinguely <tinguely@sgi.com>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent 991aaf65
...@@ -402,9 +402,9 @@ xlog_cil_committed( ...@@ -402,9 +402,9 @@ xlog_cil_committed(
xfs_extent_busy_clear(mp, &ctx->busy_extents, xfs_extent_busy_clear(mp, &ctx->busy_extents,
(mp->m_flags & XFS_MOUNT_DISCARD) && !abort); (mp->m_flags & XFS_MOUNT_DISCARD) && !abort);
spin_lock(&ctx->cil->xc_cil_lock); spin_lock(&ctx->cil->xc_push_lock);
list_del(&ctx->committing); list_del(&ctx->committing);
spin_unlock(&ctx->cil->xc_cil_lock); spin_unlock(&ctx->cil->xc_push_lock);
xlog_cil_free_logvec(ctx->lv_chain); xlog_cil_free_logvec(ctx->lv_chain);
...@@ -459,7 +459,7 @@ xlog_cil_push( ...@@ -459,7 +459,7 @@ xlog_cil_push(
down_write(&cil->xc_ctx_lock); down_write(&cil->xc_ctx_lock);
ctx = cil->xc_ctx; ctx = cil->xc_ctx;
spin_lock(&cil->xc_cil_lock); spin_lock(&cil->xc_push_lock);
push_seq = cil->xc_push_seq; push_seq = cil->xc_push_seq;
ASSERT(push_seq <= ctx->sequence); ASSERT(push_seq <= ctx->sequence);
...@@ -470,10 +470,10 @@ xlog_cil_push( ...@@ -470,10 +470,10 @@ xlog_cil_push(
*/ */
if (list_empty(&cil->xc_cil)) { if (list_empty(&cil->xc_cil)) {
cil->xc_push_seq = 0; cil->xc_push_seq = 0;
spin_unlock(&cil->xc_cil_lock); spin_unlock(&cil->xc_push_lock);
goto out_skip; goto out_skip;
} }
spin_unlock(&cil->xc_cil_lock); spin_unlock(&cil->xc_push_lock);
/* check for a previously pushed seqeunce */ /* check for a previously pushed seqeunce */
...@@ -541,9 +541,9 @@ xlog_cil_push( ...@@ -541,9 +541,9 @@ xlog_cil_push(
* that higher sequences will wait for us to write out a commit record * that higher sequences will wait for us to write out a commit record
* before they do. * before they do.
*/ */
spin_lock(&cil->xc_cil_lock); spin_lock(&cil->xc_push_lock);
list_add(&ctx->committing, &cil->xc_committing); list_add(&ctx->committing, &cil->xc_committing);
spin_unlock(&cil->xc_cil_lock); spin_unlock(&cil->xc_push_lock);
up_write(&cil->xc_ctx_lock); up_write(&cil->xc_ctx_lock);
/* /*
...@@ -578,7 +578,7 @@ xlog_cil_push( ...@@ -578,7 +578,7 @@ xlog_cil_push(
* order the commit records so replay will get them in the right order. * order the commit records so replay will get them in the right order.
*/ */
restart: restart:
spin_lock(&cil->xc_cil_lock); spin_lock(&cil->xc_push_lock);
list_for_each_entry(new_ctx, &cil->xc_committing, committing) { list_for_each_entry(new_ctx, &cil->xc_committing, committing) {
/* /*
* Higher sequences will wait for this one so skip them. * Higher sequences will wait for this one so skip them.
...@@ -591,11 +591,11 @@ xlog_cil_push( ...@@ -591,11 +591,11 @@ xlog_cil_push(
* It is still being pushed! Wait for the push to * It is still being pushed! Wait for the push to
* complete, then start again from the beginning. * complete, then start again from the beginning.
*/ */
xlog_wait(&cil->xc_commit_wait, &cil->xc_cil_lock); xlog_wait(&cil->xc_commit_wait, &cil->xc_push_lock);
goto restart; goto restart;
} }
} }
spin_unlock(&cil->xc_cil_lock); spin_unlock(&cil->xc_push_lock);
/* xfs_log_done always frees the ticket on error. */ /* xfs_log_done always frees the ticket on error. */
commit_lsn = xfs_log_done(log->l_mp, tic, &commit_iclog, 0); commit_lsn = xfs_log_done(log->l_mp, tic, &commit_iclog, 0);
...@@ -614,10 +614,10 @@ xlog_cil_push( ...@@ -614,10 +614,10 @@ xlog_cil_push(
* callbacks to the iclog we can assign the commit LSN to the context * callbacks to the iclog we can assign the commit LSN to the context
* and wake up anyone who is waiting for the commit to complete. * and wake up anyone who is waiting for the commit to complete.
*/ */
spin_lock(&cil->xc_cil_lock); spin_lock(&cil->xc_push_lock);
ctx->commit_lsn = commit_lsn; ctx->commit_lsn = commit_lsn;
wake_up_all(&cil->xc_commit_wait); wake_up_all(&cil->xc_commit_wait);
spin_unlock(&cil->xc_cil_lock); spin_unlock(&cil->xc_push_lock);
/* release the hounds! */ /* release the hounds! */
return xfs_log_release_iclog(log->l_mp, commit_iclog); return xfs_log_release_iclog(log->l_mp, commit_iclog);
...@@ -670,12 +670,12 @@ xlog_cil_push_background( ...@@ -670,12 +670,12 @@ xlog_cil_push_background(
if (cil->xc_ctx->space_used < XLOG_CIL_SPACE_LIMIT(log)) if (cil->xc_ctx->space_used < XLOG_CIL_SPACE_LIMIT(log))
return; return;
spin_lock(&cil->xc_cil_lock); spin_lock(&cil->xc_push_lock);
if (cil->xc_push_seq < cil->xc_current_sequence) { if (cil->xc_push_seq < cil->xc_current_sequence) {
cil->xc_push_seq = cil->xc_current_sequence; cil->xc_push_seq = cil->xc_current_sequence;
queue_work(log->l_mp->m_cil_workqueue, &cil->xc_push_work); queue_work(log->l_mp->m_cil_workqueue, &cil->xc_push_work);
} }
spin_unlock(&cil->xc_cil_lock); spin_unlock(&cil->xc_push_lock);
} }
...@@ -698,14 +698,14 @@ xlog_cil_push_foreground( ...@@ -698,14 +698,14 @@ xlog_cil_push_foreground(
* If the CIL is empty or we've already pushed the sequence then * If the CIL is empty or we've already pushed the sequence then
* there's no work we need to do. * there's no work we need to do.
*/ */
spin_lock(&cil->xc_cil_lock); spin_lock(&cil->xc_push_lock);
if (list_empty(&cil->xc_cil) || push_seq <= cil->xc_push_seq) { if (list_empty(&cil->xc_cil) || push_seq <= cil->xc_push_seq) {
spin_unlock(&cil->xc_cil_lock); spin_unlock(&cil->xc_push_lock);
return; return;
} }
cil->xc_push_seq = push_seq; cil->xc_push_seq = push_seq;
spin_unlock(&cil->xc_cil_lock); spin_unlock(&cil->xc_push_lock);
/* do the push now */ /* do the push now */
xlog_cil_push(log); xlog_cil_push(log);
...@@ -808,7 +808,7 @@ xlog_cil_force_lsn( ...@@ -808,7 +808,7 @@ xlog_cil_force_lsn(
* on commits for those as well. * on commits for those as well.
*/ */
restart: restart:
spin_lock(&cil->xc_cil_lock); spin_lock(&cil->xc_push_lock);
list_for_each_entry(ctx, &cil->xc_committing, committing) { list_for_each_entry(ctx, &cil->xc_committing, committing) {
if (ctx->sequence > sequence) if (ctx->sequence > sequence)
continue; continue;
...@@ -817,7 +817,7 @@ xlog_cil_force_lsn( ...@@ -817,7 +817,7 @@ xlog_cil_force_lsn(
* It is still being pushed! Wait for the push to * It is still being pushed! Wait for the push to
* complete, then start again from the beginning. * complete, then start again from the beginning.
*/ */
xlog_wait(&cil->xc_commit_wait, &cil->xc_cil_lock); xlog_wait(&cil->xc_commit_wait, &cil->xc_push_lock);
goto restart; goto restart;
} }
if (ctx->sequence != sequence) if (ctx->sequence != sequence)
...@@ -825,7 +825,7 @@ xlog_cil_force_lsn( ...@@ -825,7 +825,7 @@ xlog_cil_force_lsn(
/* found it! */ /* found it! */
commit_lsn = ctx->commit_lsn; commit_lsn = ctx->commit_lsn;
} }
spin_unlock(&cil->xc_cil_lock); spin_unlock(&cil->xc_push_lock);
return commit_lsn; return commit_lsn;
} }
...@@ -883,6 +883,7 @@ xlog_cil_init( ...@@ -883,6 +883,7 @@ xlog_cil_init(
INIT_LIST_HEAD(&cil->xc_cil); INIT_LIST_HEAD(&cil->xc_cil);
INIT_LIST_HEAD(&cil->xc_committing); INIT_LIST_HEAD(&cil->xc_committing);
spin_lock_init(&cil->xc_cil_lock); spin_lock_init(&cil->xc_cil_lock);
spin_lock_init(&cil->xc_push_lock);
init_rwsem(&cil->xc_ctx_lock); init_rwsem(&cil->xc_ctx_lock);
init_waitqueue_head(&cil->xc_commit_wait); init_waitqueue_head(&cil->xc_commit_wait);
......
...@@ -278,14 +278,17 @@ struct xfs_cil { ...@@ -278,14 +278,17 @@ struct xfs_cil {
struct xlog *xc_log; struct xlog *xc_log;
struct list_head xc_cil; struct list_head xc_cil;
spinlock_t xc_cil_lock; spinlock_t xc_cil_lock;
struct rw_semaphore xc_ctx_lock ____cacheline_aligned_in_smp;
struct xfs_cil_ctx *xc_ctx; struct xfs_cil_ctx *xc_ctx;
struct rw_semaphore xc_ctx_lock;
spinlock_t xc_push_lock ____cacheline_aligned_in_smp;
xfs_lsn_t xc_push_seq;
struct list_head xc_committing; struct list_head xc_committing;
wait_queue_head_t xc_commit_wait; wait_queue_head_t xc_commit_wait;
xfs_lsn_t xc_current_sequence; xfs_lsn_t xc_current_sequence;
struct work_struct xc_push_work; struct work_struct xc_push_work;
xfs_lsn_t xc_push_seq; } ____cacheline_aligned_in_smp;
};
/* /*
* The amount of log space we allow the CIL to aggregate is difficult to size. * The amount of log space we allow the CIL to aggregate is difficult to size.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment