Skip to content

Commit 5b849b5

Browse files
harshadjstytso
authored andcommitted
jbd2: fast commit recovery path
This patch adds fast commit recovery support in JBD2. Signed-off-by: Harshad Shirwadkar <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent aa75f4d commit 5b849b5

File tree

3 files changed

+88
-4
lines changed

3 files changed

+88
-4
lines changed

fs/ext4/fast_commit.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,8 +1188,23 @@ static void ext4_fc_cleanup(journal_t *journal, int full)
11881188
trace_ext4_fc_stats(sb);
11891189
}
11901190

1191+
/*
1192+
* Main recovery path entry point.
1193+
*/
1194+
static int ext4_fc_replay(journal_t *journal, struct buffer_head *bh,
1195+
enum passtype pass, int off, tid_t expected_tid)
1196+
{
1197+
return 0;
1198+
}
1199+
11911200
void ext4_fc_init(struct super_block *sb, journal_t *journal)
11921201
{
1202+
/*
1203+
* We set replay callback even if fast commit disabled because we may
1204+
* could still have fast commit blocks that need to be replayed even if
1205+
* fast commit has now been turned off.
1206+
*/
1207+
journal->j_fc_replay_callback = ext4_fc_replay;
11931208
if (!test_opt2(sb, JOURNAL_FAST_COMMIT))
11941209
return;
11951210
journal->j_fc_cleanup_callback = ext4_fc_cleanup;

fs/jbd2/recovery.c

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ struct recovery_info
3535
int nr_revoke_hits;
3636
};
3737

38-
enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
3938
static int do_one_pass(journal_t *journal,
4039
struct recovery_info *info, enum passtype pass);
4140
static int scan_revoke_records(journal_t *, struct buffer_head *,
@@ -225,10 +224,51 @@ static int count_tags(journal_t *journal, struct buffer_head *bh)
225224
/* Make sure we wrap around the log correctly! */
226225
#define wrap(journal, var) \
227226
do { \
228-
if (var >= (journal)->j_last) \
229-
var -= ((journal)->j_last - (journal)->j_first); \
227+
unsigned long _wrap_last = \
228+
jbd2_has_feature_fast_commit(journal) ? \
229+
(journal)->j_fc_last : (journal)->j_last; \
230+
\
231+
if (var >= _wrap_last) \
232+
var -= (_wrap_last - (journal)->j_first); \
230233
} while (0)
231234

235+
static int fc_do_one_pass(journal_t *journal,
236+
struct recovery_info *info, enum passtype pass)
237+
{
238+
unsigned int expected_commit_id = info->end_transaction;
239+
unsigned long next_fc_block;
240+
struct buffer_head *bh;
241+
int err = 0;
242+
243+
next_fc_block = journal->j_fc_first;
244+
if (!journal->j_fc_replay_callback)
245+
return 0;
246+
247+
while (next_fc_block <= journal->j_fc_last) {
248+
jbd_debug(3, "Fast commit replay: next block %ld",
249+
next_fc_block);
250+
err = jread(&bh, journal, next_fc_block);
251+
if (err) {
252+
jbd_debug(3, "Fast commit replay: read error");
253+
break;
254+
}
255+
256+
jbd_debug(3, "Processing fast commit blk with seq %d");
257+
err = journal->j_fc_replay_callback(journal, bh, pass,
258+
next_fc_block - journal->j_fc_first,
259+
expected_commit_id);
260+
next_fc_block++;
261+
if (err < 0 || err == JBD2_FC_REPLAY_STOP)
262+
break;
263+
err = 0;
264+
}
265+
266+
if (err)
267+
jbd_debug(3, "Fast commit replay failed, err = %d\n", err);
268+
269+
return err;
270+
}
271+
232272
/**
233273
* jbd2_journal_recover - recovers a on-disk journal
234274
* @journal: the journal to recover
@@ -472,7 +512,9 @@ static int do_one_pass(journal_t *journal,
472512
break;
473513

474514
jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
475-
next_commit_ID, next_log_block, journal->j_last);
515+
next_commit_ID, next_log_block,
516+
jbd2_has_feature_fast_commit(journal) ?
517+
journal->j_fc_last : journal->j_last);
476518

477519
/* Skip over each chunk of the transaction looking
478520
* either the next descriptor block or the final commit
@@ -834,6 +876,13 @@ static int do_one_pass(journal_t *journal,
834876
success = -EIO;
835877
}
836878
}
879+
880+
if (jbd2_has_feature_fast_commit(journal) && pass != PASS_REVOKE) {
881+
err = fc_do_one_pass(journal, info, pass);
882+
if (err)
883+
success = err;
884+
}
885+
837886
if (block_error && success == 0)
838887
success = -EIO;
839888
return success;

include/linux/jbd2.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,11 @@ jbd2_time_diff(unsigned long start, unsigned long end)
751751

752752
#define JBD2_NR_BATCH 64
753753

754+
enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
755+
756+
#define JBD2_FC_REPLAY_STOP 0
757+
#define JBD2_FC_REPLAY_CONTINUE 1
758+
754759
/**
755760
* struct journal_s - The journal_s type is the concrete type associated with
756761
* journal_t.
@@ -1248,6 +1253,21 @@ struct journal_s
12481253
*/
12491254
void (*j_fc_cleanup_callback)(struct journal_s *journal, int);
12501255

1256+
/*
1257+
* @j_fc_replay_callback:
1258+
*
1259+
* File-system specific function that performs replay of a fast
1260+
* commit. JBD2 calls this function for each fast commit block found in
1261+
* the journal. This function should return JBD2_FC_REPLAY_CONTINUE
1262+
* to indicate that the block was processed correctly and more fast
1263+
* commit replay should continue. Return value of JBD2_FC_REPLAY_STOP
1264+
* indicates the end of replay (no more blocks remaining). A negative
1265+
* return value indicates error.
1266+
*/
1267+
int (*j_fc_replay_callback)(struct journal_s *journal,
1268+
struct buffer_head *bh,
1269+
enum passtype pass, int off,
1270+
tid_t expected_commit_id);
12511271
};
12521272

12531273
#define jbd2_might_wait_for_commit(j) \

0 commit comments

Comments
 (0)