From 03d9afb5ecac41a3f14c11de646e8d51056f699d Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 19 Jun 2015 10:51:19 -0400 Subject: [PATCH] Fix bug which caused ext4/306 to fail. --- ...-corrupt-when-updating-journal-superblock-fails | 78 ++++++++++------------ 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/fix-ocfs2-corrupt-when-updating-journal-superblock-fails b/fix-ocfs2-corrupt-when-updating-journal-superblock-fails index 3a641b31..4cf08c1c 100644 --- a/fix-ocfs2-corrupt-when-updating-journal-superblock-fails +++ b/fix-ocfs2-corrupt-when-updating-journal-superblock-fails @@ -17,6 +17,10 @@ The issue discussion mail can be found at: https://oss.oracle.com/pipermail/ocfs2-devel/2015-June/010856.html http://comments.gmane.org/gmane.comp.file-systems.ext4/48841 +[ Fixed bug in patch which allowed a non-negative error return from + jbd2_cleanup_journal_tail() to leak out of jbd2_fjournal_flush(); this + was causing xfstests ext4/306 to fail. -- Ted ] + Reported-by: Yiwen Jiang Signed-off-by: Joseph Qi Signed-off-by: Theodore Ts'o @@ -25,38 +29,38 @@ Cc: Junxiao Bi Cc: --- fs/jbd2/checkpoint.c | 5 ++--- - fs/jbd2/journal.c | 37 ++++++++++++++++++++++++++++++------- + fs/jbd2/journal.c | 38 +++++++++++++++++++++++++++++++------- include/linux/jbd2.h | 4 ++-- - 3 files changed, 34 insertions(+), 12 deletions(-) + 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c -index 988b32e..82e5b7d 100644 +index 6b7b73a..4227dc4 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -390,7 +390,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) unsigned long blocknr; - + if (is_journal_aborted(journal)) - return 1; + return -EIO; - + if (!jbd2_journal_get_log_tail(journal, &first_tid, &blocknr)) return 1; @@ -407,8 +407,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) if (journal->j_flags & JBD2_BARRIER) - blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); - + blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL); + - __jbd2_update_log_tail(journal, first_tid, blocknr); - return 0; + return __jbd2_update_log_tail(journal, first_tid, blocknr); } - - + + diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c -index b96bd80..6b33a42 100644 +index 303ccd9..5804466 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c -@@ -885,9 +885,10 @@ int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, +@@ -876,9 +876,10 @@ int jbd2_journal_get_log_tail(journal_t *journal, tid_t *tid, * * Requires j_checkpoint_mutex */ @@ -65,10 +69,10 @@ index b96bd80..6b33a42 100644 { unsigned long freed; + int ret; - + BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); - -@@ -897,7 +898,10 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) + +@@ -888,7 +889,10 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) * space and if we lose sb update during power failure we'd replay * old transaction with possibly newly overwritten data. */ @@ -80,7 +84,7 @@ index b96bd80..6b33a42 100644 write_lock(&journal->j_state_lock); freed = block - journal->j_tail; if (block < journal->j_tail) -@@ -913,6 +917,9 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) +@@ -904,6 +908,9 @@ void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block) journal->j_tail_sequence = tid; journal->j_tail = block; write_unlock(&journal->j_state_lock); @@ -88,18 +92,18 @@ index b96bd80..6b33a42 100644 +out: + return ret; } - + /* -@@ -1331,7 +1338,7 @@ static int journal_reset(journal_t *journal) +@@ -1322,7 +1329,7 @@ static int journal_reset(journal_t *journal) return jbd2_journal_start_thread(journal); } - + -static void jbd2_write_superblock(journal_t *journal, int write_op) +static int jbd2_write_superblock(journal_t *journal, int write_op) { struct buffer_head *bh = journal->j_sb_buffer; journal_superblock_t *sb = journal->j_superblock; -@@ -1370,7 +1377,10 @@ static void jbd2_write_superblock(journal_t *journal, int write_op) +@@ -1361,7 +1368,10 @@ static void jbd2_write_superblock(journal_t *journal, int write_op) printk(KERN_ERR "JBD2: Error %d detected when updating " "journal superblock for %s.\n", ret, journal->j_devname); @@ -108,9 +112,9 @@ index b96bd80..6b33a42 100644 + + return ret; } - + /** -@@ -1383,10 +1393,11 @@ static void jbd2_write_superblock(journal_t *journal, int write_op) +@@ -1374,10 +1384,11 @@ static void jbd2_write_superblock(journal_t *journal, int write_op) * Update a journal's superblock information about log tail and write it to * disk, waiting for the IO to complete. */ @@ -120,18 +124,18 @@ index b96bd80..6b33a42 100644 { journal_superblock_t *sb = journal->j_superblock; + int ret; - + BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n", -@@ -1395,13 +1406,18 @@ void jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, +@@ -1386,13 +1397,18 @@ void jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, sb->s_sequence = cpu_to_be32(tail_tid); sb->s_start = cpu_to_be32(tail_block); - + - jbd2_write_superblock(journal, write_op); + ret = jbd2_write_superblock(journal, write_op); + if (ret) + goto out; - + /* Log is no longer empty */ write_lock(&journal->j_state_lock); WARN_ON(!sb->s_sequence); @@ -141,11 +145,11 @@ index b96bd80..6b33a42 100644 +out: + return ret; } - + /** -@@ -1950,7 +1966,13 @@ int jbd2_journal_flush(journal_t *journal) +@@ -1941,7 +1957,14 @@ int jbd2_journal_flush(journal_t *journal) return -EIO; - + mutex_lock(&journal->j_checkpoint_mutex); - jbd2_cleanup_journal_tail(journal); + if (!err) { @@ -154,11 +158,12 @@ index b96bd80..6b33a42 100644 + mutex_unlock(&journal->j_checkpoint_mutex); + goto out; + } ++ err = 0; + } - + /* Finally, mark the journal as really needing no recovery. * This sets s_start==0 in the underlying superblock, which is -@@ -1966,7 +1988,8 @@ int jbd2_journal_flush(journal_t *journal) +@@ -1957,7 +1980,8 @@ int jbd2_journal_flush(journal_t *journal) J_ASSERT(journal->j_head == journal->j_tail); J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); write_unlock(&journal->j_state_lock); @@ -166,7 +171,7 @@ index b96bd80..6b33a42 100644 +out: + return err; } - + /** diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 20e7f78..edb640a 100644 @@ -179,7 +184,7 @@ index 20e7f78..edb640a 100644 -void __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); +int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); void jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block); - + /* Commit management */ @@ -1157,7 +1157,7 @@ extern int jbd2_journal_recover (journal_t *journal); extern int jbd2_journal_wipe (journal_t *, int); @@ -190,12 +195,3 @@ index 20e7f78..edb640a 100644 unsigned long, int); extern void __jbd2_journal_abort_hard (journal_t *); extern void jbd2_journal_abort (journal_t *, int); --- -1.8.4.3 - - --- -To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html - -- 2.11.4.GIT