Skip to content

Commit 8dd4204

Browse files
committed
jbd2: Remove t_handle_lock from start_this_handle()
This should remove the last exclusive lock from start_this_handle(), so that we should now be able to start multiple transactions at the same time on large SMP systems. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
1 parent a931da6 commit 8dd4204

File tree

3 files changed

+25
-13
lines changed

3 files changed

+25
-13
lines changed

fs/jbd2/commit.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1004,7 +1004,8 @@ void jbd2_journal_commit_transaction(journal_t *journal)
10041004
* File the transaction statistics
10051005
*/
10061006
stats.ts_tid = commit_transaction->t_tid;
1007-
stats.run.rs_handle_count = commit_transaction->t_handle_count;
1007+
stats.run.rs_handle_count =
1008+
atomic_read(&commit_transaction->t_handle_count);
10081009
trace_jbd2_run_stats(journal->j_fs_dev->bd_dev,
10091010
commit_transaction->t_tid, &stats.run);
10101011

fs/jbd2/transaction.c

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction)
5757
spin_lock_init(&transaction->t_handle_lock);
5858
atomic_set(&transaction->t_updates, 0);
5959
atomic_set(&transaction->t_outstanding_credits, 0);
60+
atomic_set(&transaction->t_handle_count, 0);
6061
INIT_LIST_HEAD(&transaction->t_inode_list);
6162
INIT_LIST_HEAD(&transaction->t_private_list);
6263

@@ -180,8 +181,8 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
180181
* buffers requested by this operation, we need to stall pending a log
181182
* checkpoint to free some more log space.
182183
*/
183-
spin_lock(&transaction->t_handle_lock);
184-
needed = atomic_read(&transaction->t_outstanding_credits) + nblocks;
184+
needed = atomic_add_return(nblocks,
185+
&transaction->t_outstanding_credits);
185186

186187
if (needed > journal->j_max_transaction_buffers) {
187188
/*
@@ -192,7 +193,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
192193
DEFINE_WAIT(wait);
193194

194195
jbd_debug(2, "Handle %p starting new commit...\n", handle);
195-
spin_unlock(&transaction->t_handle_lock);
196+
atomic_sub(nblocks, &transaction->t_outstanding_credits);
196197
prepare_to_wait(&journal->j_wait_transaction_locked, &wait,
197198
TASK_UNINTERRUPTIBLE);
198199
__jbd2_log_start_commit(journal, transaction->t_tid);
@@ -229,7 +230,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
229230
*/
230231
if (__jbd2_log_space_left(journal) < jbd_space_needed(journal)) {
231232
jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle);
232-
spin_unlock(&transaction->t_handle_lock);
233+
atomic_sub(nblocks, &transaction->t_outstanding_credits);
233234
read_unlock(&journal->j_state_lock);
234235
write_lock(&journal->j_state_lock);
235236
if (__jbd2_log_space_left(journal) < jbd_space_needed(journal))
@@ -239,23 +240,33 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
239240
}
240241

241242
/* OK, account for the buffers that this operation expects to
242-
* use and add the handle to the running transaction. */
243-
244-
if (time_after(transaction->t_start, ts)) {
243+
* use and add the handle to the running transaction.
244+
*
245+
* In order for t_max_wait to be reliable, it must be
246+
* protected by a lock. But doing so will mean that
247+
* start_this_handle() can not be run in parallel on SMP
248+
* systems, which limits our scalability. So we only enable
249+
* it when debugging is enabled. We may want to use a
250+
* separate flag, eventually, so we can enable this
251+
* independently of debugging.
252+
*/
253+
#ifdef CONFIG_JBD2_DEBUG
254+
if (jbd2_journal_enable_debug &&
255+
time_after(transaction->t_start, ts)) {
245256
ts = jbd2_time_diff(ts, transaction->t_start);
257+
spin_lock(&transaction->t_handle_lock);
246258
if (ts > transaction->t_max_wait)
247259
transaction->t_max_wait = ts;
260+
spin_unlock(&transaction->t_handle_lock);
248261
}
249-
262+
#endif
250263
handle->h_transaction = transaction;
251-
atomic_add(nblocks, &transaction->t_outstanding_credits);
252264
atomic_inc(&transaction->t_updates);
253-
transaction->t_handle_count++;
265+
atomic_inc(&transaction->t_handle_count);
254266
jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n",
255267
handle, nblocks,
256268
atomic_read(&transaction->t_outstanding_credits),
257269
__jbd2_log_space_left(journal));
258-
spin_unlock(&transaction->t_handle_lock);
259270
read_unlock(&journal->j_state_lock);
260271

261272
lock_map_acquire(&handle->h_lockdep_map);

include/linux/jbd2.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ struct transaction_s
629629
/*
630630
* How many handles used this transaction? [t_handle_lock]
631631
*/
632-
int t_handle_count;
632+
atomic_t t_handle_count;
633633

634634
/*
635635
* This transaction is being forced and some process is

0 commit comments

Comments
 (0)