diff options
Diffstat (limited to 'fs/jbd/transaction.c')
-rw-r--r-- | fs/jbd/transaction.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index e1b3c8af4d..cceaf57e37 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/highmem.h> | 28 | #include <linux/highmem.h> |
29 | 29 | ||
30 | static void __journal_temp_unlink_buffer(struct journal_head *jh); | ||
31 | |||
30 | /* | 32 | /* |
31 | * get_transaction: obtain a new transaction_t object. | 33 | * get_transaction: obtain a new transaction_t object. |
32 | * | 34 | * |
@@ -53,7 +55,7 @@ get_transaction(journal_t *journal, transaction_t *transaction) | |||
53 | spin_lock_init(&transaction->t_handle_lock); | 55 | spin_lock_init(&transaction->t_handle_lock); |
54 | 56 | ||
55 | /* Set up the commit timer for the new transaction. */ | 57 | /* Set up the commit timer for the new transaction. */ |
56 | journal->j_commit_timer.expires = transaction->t_expires; | 58 | journal->j_commit_timer.expires = round_jiffies(transaction->t_expires); |
57 | add_timer(&journal->j_commit_timer); | 59 | add_timer(&journal->j_commit_timer); |
58 | 60 | ||
59 | J_ASSERT(journal->j_running_transaction == NULL); | 61 | J_ASSERT(journal->j_running_transaction == NULL); |
@@ -967,6 +969,13 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh) | |||
967 | */ | 969 | */ |
968 | jbd_lock_bh_state(bh); | 970 | jbd_lock_bh_state(bh); |
969 | spin_lock(&journal->j_list_lock); | 971 | spin_lock(&journal->j_list_lock); |
972 | |||
973 | /* Now that we have bh_state locked, are we really still mapped? */ | ||
974 | if (!buffer_mapped(bh)) { | ||
975 | JBUFFER_TRACE(jh, "unmapped buffer, bailing out"); | ||
976 | goto no_journal; | ||
977 | } | ||
978 | |||
970 | if (jh->b_transaction) { | 979 | if (jh->b_transaction) { |
971 | JBUFFER_TRACE(jh, "has transaction"); | 980 | JBUFFER_TRACE(jh, "has transaction"); |
972 | if (jh->b_transaction != handle->h_transaction) { | 981 | if (jh->b_transaction != handle->h_transaction) { |
@@ -1028,6 +1037,11 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh) | |||
1028 | sync_dirty_buffer(bh); | 1037 | sync_dirty_buffer(bh); |
1029 | jbd_lock_bh_state(bh); | 1038 | jbd_lock_bh_state(bh); |
1030 | spin_lock(&journal->j_list_lock); | 1039 | spin_lock(&journal->j_list_lock); |
1040 | /* Since we dropped the lock... */ | ||
1041 | if (!buffer_mapped(bh)) { | ||
1042 | JBUFFER_TRACE(jh, "buffer got unmapped"); | ||
1043 | goto no_journal; | ||
1044 | } | ||
1031 | /* The buffer may become locked again at any | 1045 | /* The buffer may become locked again at any |
1032 | time if it is redirtied */ | 1046 | time if it is redirtied */ |
1033 | } | 1047 | } |
@@ -1314,13 +1328,14 @@ int journal_stop(handle_t *handle) | |||
1314 | int old_handle_count, err; | 1328 | int old_handle_count, err; |
1315 | pid_t pid; | 1329 | pid_t pid; |
1316 | 1330 | ||
1317 | J_ASSERT(transaction->t_updates > 0); | ||
1318 | J_ASSERT(journal_current_handle() == handle); | 1331 | J_ASSERT(journal_current_handle() == handle); |
1319 | 1332 | ||
1320 | if (is_handle_aborted(handle)) | 1333 | if (is_handle_aborted(handle)) |
1321 | err = -EIO; | 1334 | err = -EIO; |
1322 | else | 1335 | else { |
1336 | J_ASSERT(transaction->t_updates > 0); | ||
1323 | err = 0; | 1337 | err = 0; |
1338 | } | ||
1324 | 1339 | ||
1325 | if (--handle->h_ref > 0) { | 1340 | if (--handle->h_ref > 0) { |
1326 | jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1, | 1341 | jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1, |
@@ -1486,7 +1501,7 @@ __blist_del_buffer(struct journal_head **list, struct journal_head *jh) | |||
1486 | * | 1501 | * |
1487 | * Called under j_list_lock. The journal may not be locked. | 1502 | * Called under j_list_lock. The journal may not be locked. |
1488 | */ | 1503 | */ |
1489 | void __journal_temp_unlink_buffer(struct journal_head *jh) | 1504 | static void __journal_temp_unlink_buffer(struct journal_head *jh) |
1490 | { | 1505 | { |
1491 | struct journal_head **list = NULL; | 1506 | struct journal_head **list = NULL; |
1492 | transaction_t *transaction; | 1507 | transaction_t *transaction; |
@@ -1823,6 +1838,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1823 | } | 1838 | } |
1824 | } | 1839 | } |
1825 | } else if (transaction == journal->j_committing_transaction) { | 1840 | } else if (transaction == journal->j_committing_transaction) { |
1841 | JBUFFER_TRACE(jh, "on committing transaction"); | ||
1826 | if (jh->b_jlist == BJ_Locked) { | 1842 | if (jh->b_jlist == BJ_Locked) { |
1827 | /* | 1843 | /* |
1828 | * The buffer is on the committing transaction's locked | 1844 | * The buffer is on the committing transaction's locked |
@@ -1837,7 +1853,6 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1837 | * can remove it's next_transaction pointer from the | 1853 | * can remove it's next_transaction pointer from the |
1838 | * running transaction if that is set, but nothing | 1854 | * running transaction if that is set, but nothing |
1839 | * else. */ | 1855 | * else. */ |
1840 | JBUFFER_TRACE(jh, "on committing transaction"); | ||
1841 | set_buffer_freed(bh); | 1856 | set_buffer_freed(bh); |
1842 | if (jh->b_next_transaction) { | 1857 | if (jh->b_next_transaction) { |
1843 | J_ASSERT(jh->b_next_transaction == | 1858 | J_ASSERT(jh->b_next_transaction == |
@@ -1857,6 +1872,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1857 | * i_size already for this truncate so recovery will not | 1872 | * i_size already for this truncate so recovery will not |
1858 | * expose the disk blocks we are discarding here.) */ | 1873 | * expose the disk blocks we are discarding here.) */ |
1859 | J_ASSERT_JH(jh, transaction == journal->j_running_transaction); | 1874 | J_ASSERT_JH(jh, transaction == journal->j_running_transaction); |
1875 | JBUFFER_TRACE(jh, "on running transaction"); | ||
1860 | may_free = __dispose_buffer(jh, transaction); | 1876 | may_free = __dispose_buffer(jh, transaction); |
1861 | } | 1877 | } |
1862 | 1878 | ||