diff options
| -rw-r--r-- | fs/jbd2/checkpoint.c | 5 | ||||
| -rw-r--r-- | fs/jbd2/journal.c | 38 | ||||
| -rw-r--r-- | include/linux/jbd2.h | 4 |
3 files changed, 35 insertions, 12 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 6b7b73afef81..4227dc4f7437 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
| @@ -390,7 +390,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
| 390 | unsigned long blocknr; | 390 | unsigned long blocknr; |
| 391 | 391 | ||
| 392 | if (is_journal_aborted(journal)) | 392 | if (is_journal_aborted(journal)) |
| 393 | return 1; | 393 | return -EIO; |
| 394 | 394 | ||
| 395 | if (!jbd2_journal_get_log_tail(journal, &first_tid, &blocknr)) | 395 | if (!jbd2_journal_get_log_tail(journal, &first_tid, &blocknr)) |
| 396 | return 1; | 396 | return 1; |
| @@ -407,8 +407,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
| 407 | if (journal->j_flags & JBD2_BARRIER) | 407 | if (journal->j_flags & JBD2_BARRIER) |
| 408 | blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL); | 408 | blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL); |
| 409 | 409 | ||
| 410 | __jbd2_update_log_tail(journal, first_tid, blocknr); | 410 | return __jbd2_update_log_tail(journal, first_tid, blocknr); |
| 411 | return 0; | ||
| 412 | } | 411 | } |
| 413 | 412 | ||
| 414 | 413 | ||
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 303ccd953e95..5804466b5785 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -876,9 +876,10 @@ int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, | |||
| 876 | * | 876 | * |
| 877 | * Requires j_checkpoint_mutex | 877 | * Requires j_checkpoint_mutex |
| 878 | */ | 878 | */ |
| 879 | void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) | 879 | int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) |
| 880 | { | 880 | { |
| 881 | unsigned long freed; | 881 | unsigned long freed; |
| 882 | int ret; | ||
| 882 | 883 | ||
| 883 | BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); | 884 | BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); |
| 884 | 885 | ||
| @@ -888,7 +889,10 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) | |||
| 888 | * space and if we lose sb update during power failure we'd replay | 889 | * space and if we lose sb update during power failure we'd replay |
| 889 | * old transaction with possibly newly overwritten data. | 890 | * old transaction with possibly newly overwritten data. |
| 890 | */ | 891 | */ |
| 891 | jbd2_journal_update_sb_log_tail(journal, tid, block, WRITE_FUA); | 892 | ret = jbd2_journal_update_sb_log_tail(journal, tid, block, WRITE_FUA); |
| 893 | if (ret) | ||
| 894 | goto out; | ||
| 895 | |||
| 892 | write_lock(&journal->j_state_lock); | 896 | write_lock(&journal->j_state_lock); |
| 893 | freed = block - journal->j_tail; | 897 | freed = block - journal->j_tail; |
| 894 | if (block < journal->j_tail) | 898 | if (block < journal->j_tail) |
| @@ -904,6 +908,9 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) | |||
| 904 | journal->j_tail_sequence = tid; | 908 | journal->j_tail_sequence = tid; |
| 905 | journal->j_tail = block; | 909 | journal->j_tail = block; |
| 906 | write_unlock(&journal->j_state_lock); | 910 | write_unlock(&journal->j_state_lock); |
| 911 | |||
| 912 | out: | ||
| 913 | return ret; | ||
| 907 | } | 914 | } |
| 908 | 915 | ||
| 909 | /* | 916 | /* |
| @@ -1322,7 +1329,7 @@ static int journal_reset(journal_t *journal) | |||
| 1322 | return jbd2_journal_start_thread(journal); | 1329 | return jbd2_journal_start_thread(journal); |
| 1323 | } | 1330 | } |
| 1324 | 1331 | ||
| 1325 | static void jbd2_write_superblock(journal_t *journal, int write_op) | 1332 | static int jbd2_write_superblock(journal_t *journal, int write_op) |
| 1326 | { | 1333 | { |
| 1327 | struct buffer_head *bh = journal->j_sb_buffer; | 1334 | struct buffer_head *bh = journal->j_sb_buffer; |
| 1328 | journal_superblock_t *sb = journal->j_superblock; | 1335 | journal_superblock_t *sb = journal->j_superblock; |
| @@ -1361,7 +1368,10 @@ static void jbd2_write_superblock(journal_t *journal, int write_op) | |||
| 1361 | printk(KERN_ERR "JBD2: Error %d detected when updating " | 1368 | printk(KERN_ERR "JBD2: Error %d detected when updating " |
| 1362 | "journal superblock for %s.\n", ret, | 1369 | "journal superblock for %s.\n", ret, |
| 1363 | journal->j_devname); | 1370 | journal->j_devname); |
| 1371 | jbd2_journal_abort(journal, ret); | ||
| 1364 | } | 1372 | } |
| 1373 | |||
| 1374 | return ret; | ||
| 1365 | } | 1375 | } |
| 1366 | 1376 | ||
| 1367 | /** | 1377 | /** |
| @@ -1374,10 +1384,11 @@ static void jbd2_write_superblock(journal_t *journal, int write_op) | |||
| 1374 | * Update a journal's superblock information about log tail and write it to | 1384 | * Update a journal's superblock information about log tail and write it to |
| 1375 | * disk, waiting for the IO to complete. | 1385 | * disk, waiting for the IO to complete. |
| 1376 | */ | 1386 | */ |
| 1377 | void jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, | 1387 | int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, |
| 1378 | unsigned long tail_block, int write_op) | 1388 | unsigned long tail_block, int write_op) |
| 1379 | { | 1389 | { |
| 1380 | journal_superblock_t *sb = journal->j_superblock; | 1390 | journal_superblock_t *sb = journal->j_superblock; |
| 1391 | int ret; | ||
| 1381 | 1392 | ||
| 1382 | BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); | 1393 | BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); |
| 1383 | jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n", | 1394 | jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n", |
| @@ -1386,13 +1397,18 @@ void jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, | |||
| 1386 | sb->s_sequence = cpu_to_be32(tail_tid); | 1397 | sb->s_sequence = cpu_to_be32(tail_tid); |
| 1387 | sb->s_start = cpu_to_be32(tail_block); | 1398 | sb->s_start = cpu_to_be32(tail_block); |
| 1388 | 1399 | ||
| 1389 | jbd2_write_superblock(journal, write_op); | 1400 | ret = jbd2_write_superblock(journal, write_op); |
| 1401 | if (ret) | ||
| 1402 | goto out; | ||
| 1390 | 1403 | ||
| 1391 | /* Log is no longer empty */ | 1404 | /* Log is no longer empty */ |
| 1392 | write_lock(&journal->j_state_lock); | 1405 | write_lock(&journal->j_state_lock); |
| 1393 | WARN_ON(!sb->s_sequence); | 1406 | WARN_ON(!sb->s_sequence); |
| 1394 | journal->j_flags &= ~JBD2_FLUSHED; | 1407 | journal->j_flags &= ~JBD2_FLUSHED; |
| 1395 | write_unlock(&journal->j_state_lock); | 1408 | write_unlock(&journal->j_state_lock); |
| 1409 | |||
| 1410 | out: | ||
| 1411 | return ret; | ||
| 1396 | } | 1412 | } |
| 1397 | 1413 | ||
| 1398 | /** | 1414 | /** |
| @@ -1941,7 +1957,14 @@ int jbd2_journal_flush(journal_t *journal) | |||
| 1941 | return -EIO; | 1957 | return -EIO; |
| 1942 | 1958 | ||
| 1943 | mutex_lock(&journal->j_checkpoint_mutex); | 1959 | mutex_lock(&journal->j_checkpoint_mutex); |
| 1944 | jbd2_cleanup_journal_tail(journal); | 1960 | if (!err) { |
| 1961 | err = jbd2_cleanup_journal_tail(journal); | ||
| 1962 | if (err < 0) { | ||
| 1963 | mutex_unlock(&journal->j_checkpoint_mutex); | ||
| 1964 | goto out; | ||
| 1965 | } | ||
| 1966 | err = 0; | ||
| 1967 | } | ||
| 1945 | 1968 | ||
| 1946 | /* Finally, mark the journal as really needing no recovery. | 1969 | /* Finally, mark the journal as really needing no recovery. |
| 1947 | * This sets s_start==0 in the underlying superblock, which is | 1970 | * This sets s_start==0 in the underlying superblock, which is |
| @@ -1957,7 +1980,8 @@ int jbd2_journal_flush(journal_t *journal) | |||
| 1957 | J_ASSERT(journal->j_head == journal->j_tail); | 1980 | J_ASSERT(journal->j_head == journal->j_tail); |
| 1958 | J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); | 1981 | J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); |
| 1959 | write_unlock(&journal->j_state_lock); | 1982 | write_unlock(&journal->j_state_lock); |
| 1960 | return 0; | 1983 | out: |
| 1984 | return err; | ||
| 1961 | } | 1985 | } |
| 1962 | 1986 | ||
| 1963 | /** | 1987 | /** |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 20e7f78041c8..edb640ae9a94 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
| @@ -1035,7 +1035,7 @@ struct buffer_head *jbd2_journal_get_descriptor_buffer(journal_t *journal); | |||
| 1035 | int jbd2_journal_next_log_block(journal_t *, unsigned long long *); | 1035 | int jbd2_journal_next_log_block(journal_t *, unsigned long long *); |
| 1036 | int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, | 1036 | int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, |
| 1037 | unsigned long *block); | 1037 | unsigned long *block); |
| 1038 | void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); | 1038 | int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); |
| 1039 | void jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); | 1039 | void jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); |
| 1040 | 1040 | ||
| 1041 | /* Commit management */ | 1041 | /* Commit management */ |
| @@ -1157,7 +1157,7 @@ extern int jbd2_journal_recover (journal_t *journal); | |||
| 1157 | extern int jbd2_journal_wipe (journal_t *, int); | 1157 | extern int jbd2_journal_wipe (journal_t *, int); |
| 1158 | extern int jbd2_journal_skip_recovery (journal_t *); | 1158 | extern int jbd2_journal_skip_recovery (journal_t *); |
| 1159 | extern void jbd2_journal_update_sb_errno(journal_t *); | 1159 | extern void jbd2_journal_update_sb_errno(journal_t *); |
| 1160 | extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t, | 1160 | extern int jbd2_journal_update_sb_log_tail (journal_t *, tid_t, |
| 1161 | unsigned long, int); | 1161 | unsigned long, int); |
| 1162 | extern void __jbd2_journal_abort_hard (journal_t *); | 1162 | extern void __jbd2_journal_abort_hard (journal_t *); |
| 1163 | extern void jbd2_journal_abort (journal_t *, int); | 1163 | extern void jbd2_journal_abort (journal_t *, int); |
