diff options
Diffstat (limited to 'fs/jbd2/commit.c')
-rw-r--r-- | fs/jbd2/commit.c | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 7f21cf3aaf92..eef6979821a4 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -848,10 +848,16 @@ restart_loop: | |||
848 | while (commit_transaction->t_forget) { | 848 | while (commit_transaction->t_forget) { |
849 | transaction_t *cp_transaction; | 849 | transaction_t *cp_transaction; |
850 | struct buffer_head *bh; | 850 | struct buffer_head *bh; |
851 | int try_to_free = 0; | ||
851 | 852 | ||
852 | jh = commit_transaction->t_forget; | 853 | jh = commit_transaction->t_forget; |
853 | spin_unlock(&journal->j_list_lock); | 854 | spin_unlock(&journal->j_list_lock); |
854 | bh = jh2bh(jh); | 855 | bh = jh2bh(jh); |
856 | /* | ||
857 | * Get a reference so that bh cannot be freed before we are | ||
858 | * done with it. | ||
859 | */ | ||
860 | get_bh(bh); | ||
855 | jbd_lock_bh_state(bh); | 861 | jbd_lock_bh_state(bh); |
856 | J_ASSERT_JH(jh, jh->b_transaction == commit_transaction); | 862 | J_ASSERT_JH(jh, jh->b_transaction == commit_transaction); |
857 | 863 | ||
@@ -914,28 +920,27 @@ restart_loop: | |||
914 | __jbd2_journal_insert_checkpoint(jh, commit_transaction); | 920 | __jbd2_journal_insert_checkpoint(jh, commit_transaction); |
915 | if (is_journal_aborted(journal)) | 921 | if (is_journal_aborted(journal)) |
916 | clear_buffer_jbddirty(bh); | 922 | clear_buffer_jbddirty(bh); |
917 | JBUFFER_TRACE(jh, "refile for checkpoint writeback"); | ||
918 | __jbd2_journal_refile_buffer(jh); | ||
919 | jbd_unlock_bh_state(bh); | ||
920 | } else { | 923 | } else { |
921 | J_ASSERT_BH(bh, !buffer_dirty(bh)); | 924 | J_ASSERT_BH(bh, !buffer_dirty(bh)); |
922 | /* The buffer on BJ_Forget list and not jbddirty means | 925 | /* |
926 | * The buffer on BJ_Forget list and not jbddirty means | ||
923 | * it has been freed by this transaction and hence it | 927 | * it has been freed by this transaction and hence it |
924 | * could not have been reallocated until this | 928 | * could not have been reallocated until this |
925 | * transaction has committed. *BUT* it could be | 929 | * transaction has committed. *BUT* it could be |
926 | * reallocated once we have written all the data to | 930 | * reallocated once we have written all the data to |
927 | * disk and before we process the buffer on BJ_Forget | 931 | * disk and before we process the buffer on BJ_Forget |
928 | * list. */ | 932 | * list. |
929 | JBUFFER_TRACE(jh, "refile or unfile freed buffer"); | 933 | */ |
930 | __jbd2_journal_refile_buffer(jh); | 934 | if (!jh->b_next_transaction) |
931 | if (!jh->b_transaction) { | 935 | try_to_free = 1; |
932 | jbd_unlock_bh_state(bh); | ||
933 | /* needs a brelse */ | ||
934 | jbd2_journal_remove_journal_head(bh); | ||
935 | release_buffer_page(bh); | ||
936 | } else | ||
937 | jbd_unlock_bh_state(bh); | ||
938 | } | 936 | } |
937 | JBUFFER_TRACE(jh, "refile or unfile buffer"); | ||
938 | __jbd2_journal_refile_buffer(jh); | ||
939 | jbd_unlock_bh_state(bh); | ||
940 | if (try_to_free) | ||
941 | release_buffer_page(bh); /* Drops bh reference */ | ||
942 | else | ||
943 | __brelse(bh); | ||
939 | cond_resched_lock(&journal->j_list_lock); | 944 | cond_resched_lock(&journal->j_list_lock); |
940 | } | 945 | } |
941 | spin_unlock(&journal->j_list_lock); | 946 | spin_unlock(&journal->j_list_lock); |