Skip to content

Commit 2dfba3b

Browse files
zhangyi089tytso
authored andcommitted
jbd2: correct the end of the journal recovery scan range
We got a filesystem inconsistency issue below while running generic/475 I/O failure pressure test with fast_commit feature enabled. Symlink /p3/d3/d1c/d6c/dd6/dce/l101 (inode #132605) is invalid. If fast_commit feature is enabled, a special fast_commit journal area is appended to the end of the normal journal area. The journal->j_last point to the first unused block behind the normal journal area instead of the whole log area, and the journal->j_fc_last point to the first unused block behind the fast_commit journal area. While doing journal recovery, do_one_pass(PASS_SCAN) should first scan the normal journal area and turn around to the first block once it meet journal->j_last, but the wrap() macro misuse the journal->j_fc_last, so the recovering could not read the next magic block (commit block perhaps) and would end early mistakenly and missing tN and every transaction after it in the following example. Finally, it could lead to filesystem inconsistency. | normal journal area | fast commit area | +-------------------------------------------------+------------------+ | tN(rere) | tN+1 |~| tN-x |...| tN-1 | tN(front) | .... | +-------------------------------------------------+------------------+ / / / start journal->j_last journal->j_fc_last This patch fix it by use the correct ending journal->j_last. Fixes: 5b849b5 ("jbd2: fast commit recovery path") Cc: [email protected] Reported-by: Theodore Ts'o <[email protected]> Link: https://lore.kernel.org/linux-ext4/[email protected]/ Signed-off-by: Zhang Yi <[email protected]> Reviewed-by: Jan Kara <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent ee5c807 commit 2dfba3b

File tree

1 file changed

+3
-9
lines changed

1 file changed

+3
-9
lines changed

fs/jbd2/recovery.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,8 @@ static int count_tags(journal_t *journal, struct buffer_head *bh)
230230
/* Make sure we wrap around the log correctly! */
231231
#define wrap(journal, var) \
232232
do { \
233-
unsigned long _wrap_last = \
234-
jbd2_has_feature_fast_commit(journal) ? \
235-
(journal)->j_fc_last : (journal)->j_last; \
236-
\
237-
if (var >= _wrap_last) \
238-
var -= (_wrap_last - (journal)->j_first); \
233+
if (var >= (journal)->j_last) \
234+
var -= ((journal)->j_last - (journal)->j_first); \
239235
} while (0)
240236

241237
static int fc_do_one_pass(journal_t *journal,
@@ -524,9 +520,7 @@ static int do_one_pass(journal_t *journal,
524520
break;
525521

526522
jbd2_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
527-
next_commit_ID, next_log_block,
528-
jbd2_has_feature_fast_commit(journal) ?
529-
journal->j_fc_last : journal->j_last);
523+
next_commit_ID, next_log_block, journal->j_last);
530524

531525
/* Skip over each chunk of the transaction looking
532526
* either the next descriptor block or the final commit

0 commit comments

Comments
 (0)