diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/jbd2/checkpoint.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'fs/jbd2/checkpoint.c')
-rw-r--r-- | fs/jbd2/checkpoint.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 5247e7ffdcb4..2c62c5aae82f 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
@@ -97,10 +97,14 @@ static int __try_to_free_cp_buf(struct journal_head *jh) | |||
97 | 97 | ||
98 | if (jh->b_jlist == BJ_None && !buffer_locked(bh) && | 98 | if (jh->b_jlist == BJ_None && !buffer_locked(bh) && |
99 | !buffer_dirty(bh) && !buffer_write_io_error(bh)) { | 99 | !buffer_dirty(bh) && !buffer_write_io_error(bh)) { |
100 | /* | ||
101 | * Get our reference so that bh cannot be freed before | ||
102 | * we unlock it | ||
103 | */ | ||
104 | get_bh(bh); | ||
100 | JBUFFER_TRACE(jh, "remove from checkpoint list"); | 105 | JBUFFER_TRACE(jh, "remove from checkpoint list"); |
101 | ret = __jbd2_journal_remove_checkpoint(jh) + 1; | 106 | ret = __jbd2_journal_remove_checkpoint(jh) + 1; |
102 | jbd_unlock_bh_state(bh); | 107 | jbd_unlock_bh_state(bh); |
103 | jbd2_journal_remove_journal_head(bh); | ||
104 | BUFFER_TRACE(bh, "release"); | 108 | BUFFER_TRACE(bh, "release"); |
105 | __brelse(bh); | 109 | __brelse(bh); |
106 | } else { | 110 | } else { |
@@ -223,8 +227,8 @@ restart: | |||
223 | spin_lock(&journal->j_list_lock); | 227 | spin_lock(&journal->j_list_lock); |
224 | goto restart; | 228 | goto restart; |
225 | } | 229 | } |
230 | get_bh(bh); | ||
226 | if (buffer_locked(bh)) { | 231 | if (buffer_locked(bh)) { |
227 | atomic_inc(&bh->b_count); | ||
228 | spin_unlock(&journal->j_list_lock); | 232 | spin_unlock(&journal->j_list_lock); |
229 | jbd_unlock_bh_state(bh); | 233 | jbd_unlock_bh_state(bh); |
230 | wait_on_buffer(bh); | 234 | wait_on_buffer(bh); |
@@ -243,7 +247,6 @@ restart: | |||
243 | */ | 247 | */ |
244 | released = __jbd2_journal_remove_checkpoint(jh); | 248 | released = __jbd2_journal_remove_checkpoint(jh); |
245 | jbd_unlock_bh_state(bh); | 249 | jbd_unlock_bh_state(bh); |
246 | jbd2_journal_remove_journal_head(bh); | ||
247 | __brelse(bh); | 250 | __brelse(bh); |
248 | } | 251 | } |
249 | 252 | ||
@@ -284,7 +287,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
284 | int ret = 0; | 287 | int ret = 0; |
285 | 288 | ||
286 | if (buffer_locked(bh)) { | 289 | if (buffer_locked(bh)) { |
287 | atomic_inc(&bh->b_count); | 290 | get_bh(bh); |
288 | spin_unlock(&journal->j_list_lock); | 291 | spin_unlock(&journal->j_list_lock); |
289 | jbd_unlock_bh_state(bh); | 292 | jbd_unlock_bh_state(bh); |
290 | wait_on_buffer(bh); | 293 | wait_on_buffer(bh); |
@@ -299,6 +302,16 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
299 | transaction->t_chp_stats.cs_forced_to_close++; | 302 | transaction->t_chp_stats.cs_forced_to_close++; |
300 | spin_unlock(&journal->j_list_lock); | 303 | spin_unlock(&journal->j_list_lock); |
301 | jbd_unlock_bh_state(bh); | 304 | jbd_unlock_bh_state(bh); |
305 | if (unlikely(journal->j_flags & JBD2_UNMOUNT)) | ||
306 | /* | ||
307 | * The journal thread is dead; so starting and | ||
308 | * waiting for a commit to finish will cause | ||
309 | * us to wait for a _very_ long time. | ||
310 | */ | ||
311 | printk(KERN_ERR "JBD2: %s: " | ||
312 | "Waiting for Godot: block %llu\n", | ||
313 | journal->j_devname, | ||
314 | (unsigned long long) bh->b_blocknr); | ||
302 | jbd2_log_start_commit(journal, tid); | 315 | jbd2_log_start_commit(journal, tid); |
303 | jbd2_log_wait_commit(journal, tid); | 316 | jbd2_log_wait_commit(journal, tid); |
304 | ret = 1; | 317 | ret = 1; |
@@ -306,12 +319,12 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
306 | ret = 1; | 319 | ret = 1; |
307 | if (unlikely(buffer_write_io_error(bh))) | 320 | if (unlikely(buffer_write_io_error(bh))) |
308 | ret = -EIO; | 321 | ret = -EIO; |
322 | get_bh(bh); | ||
309 | J_ASSERT_JH(jh, !buffer_jbddirty(bh)); | 323 | J_ASSERT_JH(jh, !buffer_jbddirty(bh)); |
310 | BUFFER_TRACE(bh, "remove from checkpoint"); | 324 | BUFFER_TRACE(bh, "remove from checkpoint"); |
311 | __jbd2_journal_remove_checkpoint(jh); | 325 | __jbd2_journal_remove_checkpoint(jh); |
312 | spin_unlock(&journal->j_list_lock); | 326 | spin_unlock(&journal->j_list_lock); |
313 | jbd_unlock_bh_state(bh); | 327 | jbd_unlock_bh_state(bh); |
314 | jbd2_journal_remove_journal_head(bh); | ||
315 | __brelse(bh); | 328 | __brelse(bh); |
316 | } else { | 329 | } else { |
317 | /* | 330 | /* |
@@ -532,8 +545,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
532 | */ | 545 | */ |
533 | if ((journal->j_fs_dev != journal->j_dev) && | 546 | if ((journal->j_fs_dev != journal->j_dev) && |
534 | (journal->j_flags & JBD2_BARRIER)) | 547 | (journal->j_flags & JBD2_BARRIER)) |
535 | blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL, | 548 | blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); |
536 | BLKDEV_IFL_WAIT); | ||
537 | if (!(journal->j_flags & JBD2_ABORT)) | 549 | if (!(journal->j_flags & JBD2_ABORT)) |
538 | jbd2_journal_update_superblock(journal, 1); | 550 | jbd2_journal_update_superblock(journal, 1); |
539 | return 0; | 551 | return 0; |
@@ -545,7 +557,8 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
545 | /* | 557 | /* |
546 | * journal_clean_one_cp_list | 558 | * journal_clean_one_cp_list |
547 | * | 559 | * |
548 | * Find all the written-back checkpoint buffers in the given list and release them. | 560 | * Find all the written-back checkpoint buffers in the given list and |
561 | * release them. | ||
549 | * | 562 | * |
550 | * Called with the journal locked. | 563 | * Called with the journal locked. |
551 | * Called with j_list_lock held. | 564 | * Called with j_list_lock held. |
@@ -654,8 +667,8 @@ out: | |||
654 | * checkpoint lists. | 667 | * checkpoint lists. |
655 | * | 668 | * |
656 | * The function returns 1 if it frees the transaction, 0 otherwise. | 669 | * The function returns 1 if it frees the transaction, 0 otherwise. |
670 | * The function can free jh and bh. | ||
657 | * | 671 | * |
658 | * This function is called with the journal locked. | ||
659 | * This function is called with j_list_lock held. | 672 | * This function is called with j_list_lock held. |
660 | * This function is called with jbd_lock_bh_state(jh2bh(jh)) | 673 | * This function is called with jbd_lock_bh_state(jh2bh(jh)) |
661 | */ | 674 | */ |
@@ -675,13 +688,14 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) | |||
675 | } | 688 | } |
676 | journal = transaction->t_journal; | 689 | journal = transaction->t_journal; |
677 | 690 | ||
691 | JBUFFER_TRACE(jh, "removing from transaction"); | ||
678 | __buffer_unlink(jh); | 692 | __buffer_unlink(jh); |
679 | jh->b_cp_transaction = NULL; | 693 | jh->b_cp_transaction = NULL; |
694 | jbd2_journal_put_journal_head(jh); | ||
680 | 695 | ||
681 | if (transaction->t_checkpoint_list != NULL || | 696 | if (transaction->t_checkpoint_list != NULL || |
682 | transaction->t_checkpoint_io_list != NULL) | 697 | transaction->t_checkpoint_io_list != NULL) |
683 | goto out; | 698 | goto out; |
684 | JBUFFER_TRACE(jh, "transaction has no more buffers"); | ||
685 | 699 | ||
686 | /* | 700 | /* |
687 | * There is one special case to worry about: if we have just pulled the | 701 | * There is one special case to worry about: if we have just pulled the |
@@ -692,10 +706,8 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) | |||
692 | * The locking here around t_state is a bit sleazy. | 706 | * The locking here around t_state is a bit sleazy. |
693 | * See the comment at the end of jbd2_journal_commit_transaction(). | 707 | * See the comment at the end of jbd2_journal_commit_transaction(). |
694 | */ | 708 | */ |
695 | if (transaction->t_state != T_FINISHED) { | 709 | if (transaction->t_state != T_FINISHED) |
696 | JBUFFER_TRACE(jh, "belongs to running/committing transaction"); | ||
697 | goto out; | 710 | goto out; |
698 | } | ||
699 | 711 | ||
700 | /* OK, that was the last buffer for the transaction: we can now | 712 | /* OK, that was the last buffer for the transaction: we can now |
701 | safely remove this transaction from the log */ | 713 | safely remove this transaction from the log */ |
@@ -714,7 +726,6 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) | |||
714 | wake_up(&journal->j_wait_logspace); | 726 | wake_up(&journal->j_wait_logspace); |
715 | ret = 1; | 727 | ret = 1; |
716 | out: | 728 | out: |
717 | JBUFFER_TRACE(jh, "exit"); | ||
718 | return ret; | 729 | return ret; |
719 | } | 730 | } |
720 | 731 | ||
@@ -733,6 +744,8 @@ void __jbd2_journal_insert_checkpoint(struct journal_head *jh, | |||
733 | J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jbddirty(jh2bh(jh))); | 744 | J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jbddirty(jh2bh(jh))); |
734 | J_ASSERT_JH(jh, jh->b_cp_transaction == NULL); | 745 | J_ASSERT_JH(jh, jh->b_cp_transaction == NULL); |
735 | 746 | ||
747 | /* Get reference for checkpointing transaction */ | ||
748 | jbd2_journal_grab_journal_head(jh2bh(jh)); | ||
736 | jh->b_cp_transaction = transaction; | 749 | jh->b_cp_transaction = transaction; |
737 | 750 | ||
738 | if (!transaction->t_checkpoint_list) { | 751 | if (!transaction->t_checkpoint_list) { |