diff options
-rw-r--r-- | fs/jbd2/checkpoint.c | 2 | ||||
-rw-r--r-- | fs/jbd2/commit.c | 13 | ||||
-rw-r--r-- | fs/jbd2/transaction.c | 69 | ||||
-rw-r--r-- | include/linux/jbd2.h | 8 |
4 files changed, 51 insertions, 41 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 076d1cc44f95..f8cdc02520f9 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
@@ -775,7 +775,7 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact | |||
775 | J_ASSERT(transaction->t_log_list == NULL); | 775 | J_ASSERT(transaction->t_log_list == NULL); |
776 | J_ASSERT(transaction->t_checkpoint_list == NULL); | 776 | J_ASSERT(transaction->t_checkpoint_list == NULL); |
777 | J_ASSERT(transaction->t_checkpoint_io_list == NULL); | 777 | J_ASSERT(transaction->t_checkpoint_io_list == NULL); |
778 | J_ASSERT(transaction->t_updates == 0); | 778 | J_ASSERT(atomic_read(&transaction->t_updates) == 0); |
779 | J_ASSERT(journal->j_committing_transaction != transaction); | 779 | J_ASSERT(journal->j_committing_transaction != transaction); |
780 | J_ASSERT(journal->j_running_transaction != transaction); | 780 | J_ASSERT(journal->j_running_transaction != transaction); |
781 | 781 | ||
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index af056810acb6..fbd2c564e916 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -417,12 +417,12 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
417 | stats.run.rs_locked); | 417 | stats.run.rs_locked); |
418 | 418 | ||
419 | spin_lock(&commit_transaction->t_handle_lock); | 419 | spin_lock(&commit_transaction->t_handle_lock); |
420 | while (commit_transaction->t_updates) { | 420 | while (atomic_read(&commit_transaction->t_updates)) { |
421 | DEFINE_WAIT(wait); | 421 | DEFINE_WAIT(wait); |
422 | 422 | ||
423 | prepare_to_wait(&journal->j_wait_updates, &wait, | 423 | prepare_to_wait(&journal->j_wait_updates, &wait, |
424 | TASK_UNINTERRUPTIBLE); | 424 | TASK_UNINTERRUPTIBLE); |
425 | if (commit_transaction->t_updates) { | 425 | if (atomic_read(&commit_transaction->t_updates)) { |
426 | spin_unlock(&commit_transaction->t_handle_lock); | 426 | spin_unlock(&commit_transaction->t_handle_lock); |
427 | spin_unlock(&journal->j_state_lock); | 427 | spin_unlock(&journal->j_state_lock); |
428 | schedule(); | 428 | schedule(); |
@@ -433,7 +433,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
433 | } | 433 | } |
434 | spin_unlock(&commit_transaction->t_handle_lock); | 434 | spin_unlock(&commit_transaction->t_handle_lock); |
435 | 435 | ||
436 | J_ASSERT (commit_transaction->t_outstanding_credits <= | 436 | J_ASSERT (atomic_read(&commit_transaction->t_outstanding_credits) <= |
437 | journal->j_max_transaction_buffers); | 437 | journal->j_max_transaction_buffers); |
438 | 438 | ||
439 | /* | 439 | /* |
@@ -527,11 +527,12 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
527 | stats.run.rs_logging = jiffies; | 527 | stats.run.rs_logging = jiffies; |
528 | stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing, | 528 | stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing, |
529 | stats.run.rs_logging); | 529 | stats.run.rs_logging); |
530 | stats.run.rs_blocks = commit_transaction->t_outstanding_credits; | 530 | stats.run.rs_blocks = |
531 | atomic_read(&commit_transaction->t_outstanding_credits); | ||
531 | stats.run.rs_blocks_logged = 0; | 532 | stats.run.rs_blocks_logged = 0; |
532 | 533 | ||
533 | J_ASSERT(commit_transaction->t_nr_buffers <= | 534 | J_ASSERT(commit_transaction->t_nr_buffers <= |
534 | commit_transaction->t_outstanding_credits); | 535 | atomic_read(&commit_transaction->t_outstanding_credits)); |
535 | 536 | ||
536 | err = 0; | 537 | err = 0; |
537 | descriptor = NULL; | 538 | descriptor = NULL; |
@@ -616,7 +617,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
616 | * the free space in the log, but this counter is changed | 617 | * the free space in the log, but this counter is changed |
617 | * by jbd2_journal_next_log_block() also. | 618 | * by jbd2_journal_next_log_block() also. |
618 | */ | 619 | */ |
619 | commit_transaction->t_outstanding_credits--; | 620 | atomic_dec(&commit_transaction->t_outstanding_credits); |
620 | 621 | ||
621 | /* Bump b_count to prevent truncate from stumbling over | 622 | /* Bump b_count to prevent truncate from stumbling over |
622 | the shadowed buffer! @@@ This can go if we ever get | 623 | the shadowed buffer! @@@ This can go if we ever get |
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); |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 5a72bc75b273..a72ce21de0e1 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
@@ -601,13 +601,13 @@ struct transaction_s | |||
601 | * Number of outstanding updates running on this transaction | 601 | * Number of outstanding updates running on this transaction |
602 | * [t_handle_lock] | 602 | * [t_handle_lock] |
603 | */ | 603 | */ |
604 | int t_updates; | 604 | atomic_t t_updates; |
605 | 605 | ||
606 | /* | 606 | /* |
607 | * Number of buffers reserved for use by all handles in this transaction | 607 | * Number of buffers reserved for use by all handles in this transaction |
608 | * handle but not yet modified. [t_handle_lock] | 608 | * handle but not yet modified. [t_handle_lock] |
609 | */ | 609 | */ |
610 | int t_outstanding_credits; | 610 | atomic_t t_outstanding_credits; |
611 | 611 | ||
612 | /* | 612 | /* |
613 | * Forward and backward links for the circular list of all transactions | 613 | * Forward and backward links for the circular list of all transactions |
@@ -1258,8 +1258,8 @@ static inline int jbd_space_needed(journal_t *journal) | |||
1258 | { | 1258 | { |
1259 | int nblocks = journal->j_max_transaction_buffers; | 1259 | int nblocks = journal->j_max_transaction_buffers; |
1260 | if (journal->j_committing_transaction) | 1260 | if (journal->j_committing_transaction) |
1261 | nblocks += journal->j_committing_transaction-> | 1261 | nblocks += atomic_read(&journal->j_committing_transaction-> |
1262 | t_outstanding_credits; | 1262 | t_outstanding_credits); |
1263 | return nblocks; | 1263 | return nblocks; |
1264 | } | 1264 | } |
1265 | 1265 | ||