> On Aug 8, 2019, at 9:45 PM, Harshad Shirwadkar <harshadshirwadkar@xxxxxxxxx> wrote: > > This patch adds fast-commit recovery path changes for JBD2. If we find > a fast commit block that is valid in our recovery phase call file > system specific routine to handle that block. > > We also clear the fast commit flag in jbd2_mark_journal_empty() which > is called after successful recovery as well successful ... as well as after successful ... > checkpointing. This allows JBD2 journal to be compatible with older > versions when there are not fast commit blocks. > > Signed-off-by: Harshad Shirwadkar <harshadshirwadkar@xxxxxxxxx> Reviewed-by: Andreas Dilger <adilger@xxxxxxxxx> > > --- > > Changelog: > > V2: Fixed checkpatch error. > --- > fs/jbd2/journal.c | 12 ++++++++++ > fs/jbd2/recovery.c | 59 +++++++++++++++++++++++++++++++++++++++++++--- > 2 files changed, 68 insertions(+), 3 deletions(-) > > diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c > index 1e15804b2c3c..ae4584a60cc3 100644 > --- a/fs/jbd2/journal.c > +++ b/fs/jbd2/journal.c > @@ -1604,6 +1604,7 @@ int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, > static void jbd2_mark_journal_empty(journal_t *journal, int write_op) > { > journal_superblock_t *sb = journal->j_superblock; > + bool had_fast_commit = false; > > BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); > lock_buffer(journal->j_sb_buffer); > @@ -1617,6 +1618,14 @@ static void jbd2_mark_journal_empty(journal_t *journal, int write_op) > > sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); > sb->s_start = cpu_to_be32(0); > + if (jbd2_has_feature_fast_commit(journal)) { > + /* > + * When journal is clean, no need to commit fast commit flag and > + * make file system incompatible with older kernels. > + */ > + jbd2_clear_feature_fast_commit(journal); > + had_fast_commit = true; > + } > > jbd2_write_superblock(journal, write_op); > > @@ -1624,6 +1633,9 @@ static void jbd2_mark_journal_empty(journal_t *journal, int write_op) > write_lock(&journal->j_state_lock); > journal->j_flags |= JBD2_FLUSHED; > write_unlock(&journal->j_state_lock); > + > + if (had_fast_commit) > + jbd2_set_feature_fast_commit(journal); > } > > > diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c > index a4967b27ffb6..3a6cd1497504 100644 > --- a/fs/jbd2/recovery.c > +++ b/fs/jbd2/recovery.c > @@ -225,8 +225,12 @@ static int count_tags(journal_t *journal, struct buffer_head *bh) > /* Make sure we wrap around the log correctly! */ > #define wrap(journal, var) \ > do { \ > - if (var >= (journal)->j_last) \ > - var -= ((journal)->j_last - (journal)->j_first); \ > + unsigned long _wrap_last = \ > + jbd2_has_feature_fast_commit(journal) ? \ > + (journal)->j_last_fc : (journal)->j_last; \ > + \ > + if (var >= _wrap_last) \ > + var -= (_wrap_last - (journal)->j_first); \ > } while (0) > > /** > @@ -413,6 +417,49 @@ static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag, > return tag->t_checksum == cpu_to_be16(csum32); > } > > +static int fc_do_one_pass(journal_t *journal, > + struct recovery_info *info, enum passtype pass) > +{ > + unsigned int expected_commit_id = info->end_transaction; > + unsigned long next_fc_block; > + struct buffer_head *bh; > + unsigned int seq; > + journal_header_t *jhdr; > + int err = 0; > + > + next_fc_block = journal->j_first_fc; > + > + while (next_fc_block != journal->j_last_fc) { > + jbd_debug(3, "Fast commit replay: next block %lld", > + next_fc_block); > + err = jread(&bh, journal, next_fc_block); > + if (err) > + break; > + > + jhdr = (journal_header_t *)bh->b_data; > + seq = be32_to_cpu(jhdr->h_sequence); > + if (be32_to_cpu(jhdr->h_magic) != JBD2_MAGIC_NUMBER || > + seq != expected_commit_id) { > + break; > + } > + jbd_debug(3, "Processing fast commit blk with seq %d", > + seq); > + if (pass == PASS_REPLAY && > + journal->j_fc_replay_callback) { > + err = journal->j_fc_replay_callback(journal, > + bh); > + if (err) > + break; > + } > + next_fc_block++; > + } > + > + if (err) > + jbd_debug(3, "Fast commit replay failed, err = %d\n", err); > + > + return err; > +} > + > static int do_one_pass(journal_t *journal, > struct recovery_info *info, enum passtype pass) > { > @@ -470,7 +517,7 @@ static int do_one_pass(journal_t *journal, > break; > > jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n", > - next_commit_ID, next_log_block, journal->j_last); > + next_commit_ID, next_log_block, journal->j_last_fc); > > /* Skip over each chunk of the transaction looking > * either the next descriptor block or the final commit > @@ -768,6 +815,8 @@ static int do_one_pass(journal_t *journal, > if (err) > goto failed; > continue; > + case JBD2_FC_BLOCK: > + continue; > > default: > jbd_debug(3, "Unrecognised magic %d, end of scan.\n", > @@ -799,6 +848,10 @@ static int do_one_pass(journal_t *journal, > success = -EIO; > } > } > + > + if (jbd2_has_feature_fast_commit(journal) && pass == PASS_REPLAY) > + fc_do_one_pass(journal, info, pass); > + > if (block_error && success == 0) > success = -EIO; > return success; > -- > 2.23.0.rc1.153.gdeed80330f-goog > Cheers, Andreas
Attachment:
signature.asc
Description: Message signed with OpenPGP