diff options
Diffstat (limited to 'fs/jbd2')
-rw-r--r-- | fs/jbd2/journal.c | 3 | ||||
-rw-r--r-- | fs/jbd2/transaction.c | 20 |
2 files changed, 19 insertions, 4 deletions
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 10db92ced0..c60f378b0f 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -725,6 +725,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, | |||
725 | __FUNCTION__); | 725 | __FUNCTION__); |
726 | kfree(journal); | 726 | kfree(journal); |
727 | journal = NULL; | 727 | journal = NULL; |
728 | goto out; | ||
728 | } | 729 | } |
729 | journal->j_dev = bdev; | 730 | journal->j_dev = bdev; |
730 | journal->j_fs_dev = fs_dev; | 731 | journal->j_fs_dev = fs_dev; |
@@ -735,7 +736,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, | |||
735 | J_ASSERT(bh != NULL); | 736 | J_ASSERT(bh != NULL); |
736 | journal->j_sb_buffer = bh; | 737 | journal->j_sb_buffer = bh; |
737 | journal->j_superblock = (journal_superblock_t *)bh->b_data; | 738 | journal->j_superblock = (journal_superblock_t *)bh->b_data; |
738 | 739 | out: | |
739 | return journal; | 740 | return journal; |
740 | } | 741 | } |
741 | 742 | ||
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 149957bef9..c051a94c8a 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -967,6 +967,13 @@ int jbd2_journal_dirty_data(handle_t *handle, struct buffer_head *bh) | |||
967 | */ | 967 | */ |
968 | jbd_lock_bh_state(bh); | 968 | jbd_lock_bh_state(bh); |
969 | spin_lock(&journal->j_list_lock); | 969 | spin_lock(&journal->j_list_lock); |
970 | |||
971 | /* Now that we have bh_state locked, are we really still mapped? */ | ||
972 | if (!buffer_mapped(bh)) { | ||
973 | JBUFFER_TRACE(jh, "unmapped buffer, bailing out"); | ||
974 | goto no_journal; | ||
975 | } | ||
976 | |||
970 | if (jh->b_transaction) { | 977 | if (jh->b_transaction) { |
971 | JBUFFER_TRACE(jh, "has transaction"); | 978 | JBUFFER_TRACE(jh, "has transaction"); |
972 | if (jh->b_transaction != handle->h_transaction) { | 979 | if (jh->b_transaction != handle->h_transaction) { |
@@ -1028,6 +1035,11 @@ int jbd2_journal_dirty_data(handle_t *handle, struct buffer_head *bh) | |||
1028 | sync_dirty_buffer(bh); | 1035 | sync_dirty_buffer(bh); |
1029 | jbd_lock_bh_state(bh); | 1036 | jbd_lock_bh_state(bh); |
1030 | spin_lock(&journal->j_list_lock); | 1037 | spin_lock(&journal->j_list_lock); |
1038 | /* Since we dropped the lock... */ | ||
1039 | if (!buffer_mapped(bh)) { | ||
1040 | JBUFFER_TRACE(jh, "buffer got unmapped"); | ||
1041 | goto no_journal; | ||
1042 | } | ||
1031 | /* The buffer may become locked again at any | 1043 | /* The buffer may become locked again at any |
1032 | time if it is redirtied */ | 1044 | time if it is redirtied */ |
1033 | } | 1045 | } |
@@ -1314,13 +1326,14 @@ int jbd2_journal_stop(handle_t *handle) | |||
1314 | int old_handle_count, err; | 1326 | int old_handle_count, err; |
1315 | pid_t pid; | 1327 | pid_t pid; |
1316 | 1328 | ||
1317 | J_ASSERT(transaction->t_updates > 0); | ||
1318 | J_ASSERT(journal_current_handle() == handle); | 1329 | J_ASSERT(journal_current_handle() == handle); |
1319 | 1330 | ||
1320 | if (is_handle_aborted(handle)) | 1331 | if (is_handle_aborted(handle)) |
1321 | err = -EIO; | 1332 | err = -EIO; |
1322 | else | 1333 | else { |
1334 | J_ASSERT(transaction->t_updates > 0); | ||
1323 | err = 0; | 1335 | err = 0; |
1336 | } | ||
1324 | 1337 | ||
1325 | if (--handle->h_ref > 0) { | 1338 | if (--handle->h_ref > 0) { |
1326 | jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1, | 1339 | jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1, |
@@ -1823,6 +1836,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1823 | } | 1836 | } |
1824 | } | 1837 | } |
1825 | } else if (transaction == journal->j_committing_transaction) { | 1838 | } else if (transaction == journal->j_committing_transaction) { |
1839 | JBUFFER_TRACE(jh, "on committing transaction"); | ||
1826 | if (jh->b_jlist == BJ_Locked) { | 1840 | if (jh->b_jlist == BJ_Locked) { |
1827 | /* | 1841 | /* |
1828 | * The buffer is on the committing transaction's locked | 1842 | * The buffer is on the committing transaction's locked |
@@ -1837,7 +1851,6 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1837 | * can remove it's next_transaction pointer from the | 1851 | * can remove it's next_transaction pointer from the |
1838 | * running transaction if that is set, but nothing | 1852 | * running transaction if that is set, but nothing |
1839 | * else. */ | 1853 | * else. */ |
1840 | JBUFFER_TRACE(jh, "on committing transaction"); | ||
1841 | set_buffer_freed(bh); | 1854 | set_buffer_freed(bh); |
1842 | if (jh->b_next_transaction) { | 1855 | if (jh->b_next_transaction) { |
1843 | J_ASSERT(jh->b_next_transaction == | 1856 | J_ASSERT(jh->b_next_transaction == |
@@ -1857,6 +1870,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1857 | * i_size already for this truncate so recovery will not | 1870 | * i_size already for this truncate so recovery will not |
1858 | * expose the disk blocks we are discarding here.) */ | 1871 | * expose the disk blocks we are discarding here.) */ |
1859 | J_ASSERT_JH(jh, transaction == journal->j_running_transaction); | 1872 | J_ASSERT_JH(jh, transaction == journal->j_running_transaction); |
1873 | JBUFFER_TRACE(jh, "on running transaction"); | ||
1860 | may_free = __dispose_buffer(jh, transaction); | 1874 | may_free = __dispose_buffer(jh, transaction); |
1861 | } | 1875 | } |
1862 | 1876 | ||