diff options
author | Theodore Ts'o <tytso@mit.edu> | 2010-08-02 08:43:25 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-08-02 08:43:25 -0400 |
commit | a51dca9cd3bb4ec5a05bfb6feabf024a5c808a37 (patch) | |
tree | 31256b4fa3ec1d0e1e27196607499877c662ee86 /fs/jbd2/transaction.c | |
parent | 8b67f04ab9de5d8f3a71aef72bf02c995a506db5 (diff) |
jbd2: Use atomic variables to avoid taking t_handle_lock in jbd2_journal_stop
By using an atomic_t for t_updates and t_outstanding credits, this
should allow us to not need to take transaction t_handle_lock in
jbd2_journal_stop().
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/jbd2/transaction.c')
-rw-r--r-- | fs/jbd2/transaction.c | 69 |
1 files changed, 39 insertions, 30 deletions
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 001e95fb0fe1..9c64c7ec48d4 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -55,6 +55,8 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction) | |||
55 | transaction->t_tid = journal->j_transaction_sequence++; | 55 | transaction->t_tid = journal->j_transaction_sequence++; |
56 | transaction->t_expires = jiffies + journal->j_commit_interval; | 56 | transaction->t_expires = jiffies + journal->j_commit_interval; |
57 | spin_lock_init(&transaction->t_handle_lock); | 57 | spin_lock_init(&transaction->t_handle_lock); |
58 | atomic_set(&transaction->t_updates, 0); | ||
59 | atomic_set(&transaction->t_outstanding_credits, 0); | ||
58 | INIT_LIST_HEAD(&transaction->t_inode_list); | 60 | INIT_LIST_HEAD(&transaction->t_inode_list); |
59 | INIT_LIST_HEAD(&transaction->t_private_list); | 61 | INIT_LIST_HEAD(&transaction->t_private_list); |
60 | 62 | ||
@@ -177,7 +179,7 @@ repeat_locked: | |||
177 | * checkpoint to free some more log space. | 179 | * checkpoint to free some more log space. |
178 | */ | 180 | */ |
179 | spin_lock(&transaction->t_handle_lock); | 181 | spin_lock(&transaction->t_handle_lock); |
180 | needed = transaction->t_outstanding_credits + nblocks; | 182 | needed = atomic_read(&transaction->t_outstanding_credits) + nblocks; |
181 | 183 | ||
182 | if (needed > journal->j_max_transaction_buffers) { | 184 | if (needed > journal->j_max_transaction_buffers) { |
183 | /* | 185 | /* |
@@ -240,11 +242,12 @@ repeat_locked: | |||
240 | } | 242 | } |
241 | 243 | ||
242 | handle->h_transaction = transaction; | 244 | handle->h_transaction = transaction; |
243 | transaction->t_outstanding_credits += nblocks; | 245 | atomic_add(nblocks, &transaction->t_outstanding_credits); |
244 | transaction->t_updates++; | 246 | atomic_inc(&transaction->t_updates); |
245 | transaction->t_handle_count++; | 247 | transaction->t_handle_count++; |
246 | jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n", | 248 | jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n", |
247 | handle, nblocks, transaction->t_outstanding_credits, | 249 | handle, nblocks, |
250 | atomic_read(&transaction->t_outstanding_credits), | ||
248 | __jbd2_log_space_left(journal)); | 251 | __jbd2_log_space_left(journal)); |
249 | spin_unlock(&transaction->t_handle_lock); | 252 | spin_unlock(&transaction->t_handle_lock); |
250 | spin_unlock(&journal->j_state_lock); | 253 | spin_unlock(&journal->j_state_lock); |
@@ -369,7 +372,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks) | |||
369 | } | 372 | } |
370 | 373 | ||
371 | spin_lock(&transaction->t_handle_lock); | 374 | spin_lock(&transaction->t_handle_lock); |
372 | wanted = transaction->t_outstanding_credits + nblocks; | 375 | wanted = atomic_read(&transaction->t_outstanding_credits) + nblocks; |
373 | 376 | ||
374 | if (wanted > journal->j_max_transaction_buffers) { | 377 | if (wanted > journal->j_max_transaction_buffers) { |
375 | jbd_debug(3, "denied handle %p %d blocks: " | 378 | jbd_debug(3, "denied handle %p %d blocks: " |
@@ -384,7 +387,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks) | |||
384 | } | 387 | } |
385 | 388 | ||
386 | handle->h_buffer_credits += nblocks; | 389 | handle->h_buffer_credits += nblocks; |
387 | transaction->t_outstanding_credits += nblocks; | 390 | atomic_add(nblocks, &transaction->t_outstanding_credits); |
388 | result = 0; | 391 | result = 0; |
389 | 392 | ||
390 | jbd_debug(3, "extended handle %p by %d\n", handle, nblocks); | 393 | jbd_debug(3, "extended handle %p by %d\n", handle, nblocks); |
@@ -426,15 +429,14 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, int gfp_mask) | |||
426 | * First unlink the handle from its current transaction, and start the | 429 | * First unlink the handle from its current transaction, and start the |
427 | * commit on that. | 430 | * commit on that. |
428 | */ | 431 | */ |
429 | J_ASSERT(transaction->t_updates > 0); | 432 | J_ASSERT(atomic_read(&transaction->t_updates) > 0); |
430 | J_ASSERT(journal_current_handle() == handle); | 433 | J_ASSERT(journal_current_handle() == handle); |
431 | 434 | ||
432 | spin_lock(&journal->j_state_lock); | 435 | spin_lock(&journal->j_state_lock); |
433 | spin_lock(&transaction->t_handle_lock); | 436 | spin_lock(&transaction->t_handle_lock); |
434 | transaction->t_outstanding_credits -= handle->h_buffer_credits; | 437 | atomic_sub(handle->h_buffer_credits, |
435 | transaction->t_updates--; | 438 | &transaction->t_outstanding_credits); |
436 | 439 | if (atomic_dec_and_test(&transaction->t_updates)) | |
437 | if (!transaction->t_updates) | ||
438 | wake_up(&journal->j_wait_updates); | 440 | wake_up(&journal->j_wait_updates); |
439 | spin_unlock(&transaction->t_handle_lock); | 441 | spin_unlock(&transaction->t_handle_lock); |
440 | 442 | ||
@@ -481,7 +483,7 @@ void jbd2_journal_lock_updates(journal_t *journal) | |||
481 | break; | 483 | break; |
482 | 484 | ||
483 | spin_lock(&transaction->t_handle_lock); | 485 | spin_lock(&transaction->t_handle_lock); |
484 | if (!transaction->t_updates) { | 486 | if (!atomic_read(&transaction->t_updates)) { |
485 | spin_unlock(&transaction->t_handle_lock); | 487 | spin_unlock(&transaction->t_handle_lock); |
486 | break; | 488 | break; |
487 | } | 489 | } |
@@ -1258,7 +1260,8 @@ int jbd2_journal_stop(handle_t *handle) | |||
1258 | { | 1260 | { |
1259 | transaction_t *transaction = handle->h_transaction; | 1261 | transaction_t *transaction = handle->h_transaction; |
1260 | journal_t *journal = transaction->t_journal; | 1262 | journal_t *journal = transaction->t_journal; |
1261 | int err; | 1263 | int err, wait_for_commit = 0; |
1264 | tid_t tid; | ||
1262 | pid_t pid; | 1265 | pid_t pid; |
1263 | 1266 | ||
1264 | J_ASSERT(journal_current_handle() == handle); | 1267 | J_ASSERT(journal_current_handle() == handle); |
@@ -1266,7 +1269,7 @@ int jbd2_journal_stop(handle_t *handle) | |||
1266 | if (is_handle_aborted(handle)) | 1269 | if (is_handle_aborted(handle)) |
1267 | err = -EIO; | 1270 | err = -EIO; |
1268 | else { | 1271 | else { |
1269 | J_ASSERT(transaction->t_updates > 0); | 1272 | J_ASSERT(atomic_read(&transaction->t_updates) > 0); |
1270 | err = 0; | 1273 | err = 0; |
1271 | } | 1274 | } |
1272 | 1275 | ||
@@ -1334,14 +1337,8 @@ int jbd2_journal_stop(handle_t *handle) | |||
1334 | if (handle->h_sync) | 1337 | if (handle->h_sync) |
1335 | transaction->t_synchronous_commit = 1; | 1338 | transaction->t_synchronous_commit = 1; |
1336 | current->journal_info = NULL; | 1339 | current->journal_info = NULL; |
1337 | spin_lock(&transaction->t_handle_lock); | 1340 | atomic_sub(handle->h_buffer_credits, |
1338 | transaction->t_outstanding_credits -= handle->h_buffer_credits; | 1341 | &transaction->t_outstanding_credits); |
1339 | transaction->t_updates--; | ||
1340 | if (!transaction->t_updates) { | ||
1341 | wake_up(&journal->j_wait_updates); | ||
1342 | if (journal->j_barrier_count) | ||
1343 | wake_up(&journal->j_wait_transaction_locked); | ||
1344 | } | ||
1345 | 1342 | ||
1346 | /* | 1343 | /* |
1347 | * If the handle is marked SYNC, we need to set another commit | 1344 | * If the handle is marked SYNC, we need to set another commit |
@@ -1350,15 +1347,13 @@ int jbd2_journal_stop(handle_t *handle) | |||
1350 | * transaction is too old now. | 1347 | * transaction is too old now. |
1351 | */ | 1348 | */ |
1352 | if (handle->h_sync || | 1349 | if (handle->h_sync || |
1353 | transaction->t_outstanding_credits > | 1350 | (atomic_read(&transaction->t_outstanding_credits) > |
1354 | journal->j_max_transaction_buffers || | 1351 | journal->j_max_transaction_buffers) || |
1355 | time_after_eq(jiffies, transaction->t_expires)) { | 1352 | time_after_eq(jiffies, transaction->t_expires)) { |
1356 | /* Do this even for aborted journals: an abort still | 1353 | /* Do this even for aborted journals: an abort still |
1357 | * completes the commit thread, it just doesn't write | 1354 | * completes the commit thread, it just doesn't write |
1358 | * anything to disk. */ | 1355 | * anything to disk. */ |
1359 | tid_t tid = transaction->t_tid; | ||
1360 | 1356 | ||
1361 | spin_unlock(&transaction->t_handle_lock); | ||
1362 | jbd_debug(2, "transaction too old, requesting commit for " | 1357 | jbd_debug(2, "transaction too old, requesting commit for " |
1363 | "handle %p\n", handle); | 1358 | "handle %p\n", handle); |
1364 | /* This is non-blocking */ | 1359 | /* This is non-blocking */ |
@@ -1369,11 +1364,25 @@ int jbd2_journal_stop(handle_t *handle) | |||
1369 | * to wait for the commit to complete. | 1364 | * to wait for the commit to complete. |
1370 | */ | 1365 | */ |
1371 | if (handle->h_sync && !(current->flags & PF_MEMALLOC)) | 1366 | if (handle->h_sync && !(current->flags & PF_MEMALLOC)) |
1372 | err = jbd2_log_wait_commit(journal, tid); | 1367 | wait_for_commit = 1; |
1373 | } else { | ||
1374 | spin_unlock(&transaction->t_handle_lock); | ||
1375 | } | 1368 | } |
1376 | 1369 | ||
1370 | /* | ||
1371 | * Once we drop t_updates, if it goes to zero the transaction | ||
1372 | * could start commiting on us and eventually disappear. So | ||
1373 | * once we do this, we must not dereference transaction | ||
1374 | * pointer again. | ||
1375 | */ | ||
1376 | tid = transaction->t_tid; | ||
1377 | if (atomic_dec_and_test(&transaction->t_updates)) { | ||
1378 | wake_up(&journal->j_wait_updates); | ||
1379 | if (journal->j_barrier_count) | ||
1380 | wake_up(&journal->j_wait_transaction_locked); | ||
1381 | } | ||
1382 | |||
1383 | if (wait_for_commit) | ||
1384 | err = jbd2_log_wait_commit(journal, tid); | ||
1385 | |||
1377 | lock_map_release(&handle->h_lockdep_map); | 1386 | lock_map_release(&handle->h_lockdep_map); |
1378 | 1387 | ||
1379 | jbd2_free_handle(handle); | 1388 | jbd2_free_handle(handle); |