1 jbd2: load jmap from journal
3 If the lazy journal feature is enabled, instead of replaying the
4 journal, read the journal into journal map.
6 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
8 fs/jbd2/journal.c | 27 +++++++++---------------
9 fs/jbd2/recovery.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
10 2 files changed, 90 insertions(+), 42 deletions(-)
12 diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
13 index 9c097ddfe63f..8060ab4805eb 100644
14 --- a/fs/jbd2/journal.c
15 +++ b/fs/jbd2/journal.c
16 @@ -1276,31 +1276,24 @@ static void journal_fail_superblock (journal_t *journal)
19 * Given a journal_t structure, initialise the various fields for
20 - * startup of a new journaling session. We use this both when creating
21 - * a journal, and after recovering an old journal to reset it for
23 + * startup of a new journaling session.
26 static int journal_reset(journal_t *journal)
28 journal_superblock_t *sb = journal->j_superblock;
29 - unsigned long long first, last;
32 - first = be32_to_cpu(sb->s_first);
33 - last = be32_to_cpu(sb->s_maxlen);
34 - if (first + JBD2_MIN_JOURNAL_BLOCKS > last + 1) {
35 - printk(KERN_ERR "JBD2: Journal too short (blocks %llu-%llu).\n",
37 + if (journal->j_first + JBD2_MIN_JOURNAL_BLOCKS > journal->j_last + 1) {
38 + printk(KERN_ERR "JBD2: Journal too short (blocks %lu-%lu).\n",
39 + journal->j_first, journal->j_last);
40 journal_fail_superblock(journal);
44 - journal->j_first = first;
45 - journal->j_last = last;
47 - journal->j_head = first;
48 - journal->j_tail = first;
49 - journal->j_free = last - first;
50 + free = journal->j_tail - journal->j_head;
52 + free += journal->j_last - journal->j_first;
53 + journal->j_free = free;
55 journal->j_tail_sequence = journal->j_transaction_sequence;
56 journal->j_commit_sequence = journal->j_transaction_sequence - 1;
57 @@ -1320,7 +1313,7 @@ static int journal_reset(journal_t *journal)
58 journal->j_tail, journal->j_tail_sequence,
60 journal->j_flags |= JBD2_FLUSHED;
62 + } else if ((journal->j_flags & JBD2_LAZY) == 0) {
63 /* Lock here to make assertions happy... */
64 mutex_lock_io(&journal->j_checkpoint_mutex);
66 diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
67 index da100044566c..7a74ea1860a9 100644
68 --- a/fs/jbd2/recovery.c
69 +++ b/fs/jbd2/recovery.c
71 #include <linux/errno.h>
72 #include <linux/crc32.h>
73 #include <linux/blkdev.h>
78 @@ -32,17 +33,18 @@ struct recovery_info
80 tid_t start_transaction;
81 tid_t end_transaction;
89 -enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
90 +enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY, PASS_JMAP};
91 static int do_one_pass(journal_t *journal,
92 struct recovery_info *info, enum passtype pass);
93 -static int scan_revoke_records(journal_t *, struct buffer_head *,
94 - tid_t, struct recovery_info *);
95 +static int scan_revoke_records(journal_t *, struct buffer_head *, enum passtype,
96 + tid_t, struct recovery_info *);
100 @@ -255,11 +257,16 @@ int jbd2_journal_recover(journal_t *journal)
101 sb = journal->j_superblock;
104 + * Initialize journal's head and tail assuming the recovery
105 + * was successful and we're not doing lazy journalling.
107 + journal->j_head = journal->j_tail = journal->j_first;
110 * The journal superblock's s_start field (the current log head)
111 * is always zero if, and only if, the journal was cleanly
116 jbd_debug(1, "No recovery required, last transaction %d\n",
117 be32_to_cpu(sb->s_sequence));
118 @@ -267,11 +274,15 @@ int jbd2_journal_recover(journal_t *journal)
122 - err = do_one_pass(journal, &info, PASS_SCAN);
124 - err = do_one_pass(journal, &info, PASS_REVOKE);
126 - err = do_one_pass(journal, &info, PASS_REPLAY);
127 + if (journal->j_flags & JBD2_LAZY)
128 + err = do_one_pass(journal, &info, PASS_JMAP);
130 + err = do_one_pass(journal, &info, PASS_SCAN);
132 + err = do_one_pass(journal, &info, PASS_REVOKE);
134 + err = do_one_pass(journal, &info, PASS_REPLAY);
137 jbd_debug(1, "JBD2: recovery, exit status %d, "
138 "recovered transactions %u to %u\n",
139 @@ -279,10 +290,22 @@ int jbd2_journal_recover(journal_t *journal)
140 jbd_debug(1, "JBD2: Replayed %d and revoked %d/%d blocks\n",
141 info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
143 - /* Restart the log at the next transaction ID, thus invalidating
144 - * any existing commit records in the log. */
145 + /* Restart the log at the next transaction ID */
146 journal->j_transaction_sequence = info.end_transaction;
149 + * In lazy journalling mode, we need to preserve the existing
150 + * contents of the journal, so set j_head and j_tail
153 + if (journal->j_flags & JBD2_LAZY) {
156 + journal->j_head = info.head_block;
157 + journal->j_tail = be32_to_cpu(sb->s_start);
161 jbd2_journal_clear_revoke(journal);
162 err2 = sync_blockdev(journal->j_fs_dev);
164 @@ -431,6 +454,7 @@ static int do_one_pass(journal_t *journal,
165 __u32 crc32_sum = ~0; /* Transactional Checksums */
166 int descr_csum_size = 0;
171 * First thing is to establish what we expect to find in the log
172 @@ -443,7 +467,7 @@ static int do_one_pass(journal_t *journal,
173 next_log_block = be32_to_cpu(sb->s_start);
175 first_commit_ID = next_commit_ID;
176 - if (pass == PASS_SCAN)
177 + if (pass == PASS_SCAN || pass == PASS_JMAP)
178 info->start_transaction = first_commit_ID;
180 jbd_debug(1, "Starting recovery pass %d\n", pass);
181 @@ -468,7 +492,7 @@ static int do_one_pass(journal_t *journal,
182 * check right now that we haven't gone past the end of
185 - if (pass != PASS_SCAN)
186 + if (pass != PASS_SCAN && pass != PASS_JMAP)
187 if (tid_geq(next_commit_ID, info->end_transaction))
190 @@ -484,9 +508,6 @@ static int do_one_pass(journal_t *journal,
195 - wrap(journal, next_log_block);
197 /* What kind of buffer is it?
199 * If it is a descriptor block, check that it has the
200 @@ -510,6 +531,14 @@ static int do_one_pass(journal_t *journal,
204 + if ((pass == PASS_JMAP) && new_txn) {
205 + jbd2_add_new_transaction_infos(journal, sequence, next_log_block);
210 + wrap(journal, next_log_block);
212 /* OK, we have a valid descriptor block which matches
213 * all of the sequence number checks. What are we going
214 * to do with it? That depends on the pass... */
215 @@ -535,7 +564,7 @@ static int do_one_pass(journal_t *journal,
216 * in pass REPLAY; if journal_checksums enabled, then
217 * calculate checksums in PASS_SCAN, otherwise,
218 * just skip over the blocks it describes. */
219 - if (pass != PASS_REPLAY) {
220 + if ((pass != PASS_REPLAY) && (pass != PASS_JMAP)) {
221 if (pass == PASS_SCAN &&
222 jbd2_has_feature_checksum(journal) &&
223 !info->end_transaction) {
224 @@ -562,12 +591,28 @@ static int do_one_pass(journal_t *journal,
225 while ((tagp - bh->b_data + tag_bytes)
226 <= journal->j_blocksize - descr_csum_size) {
227 unsigned long io_block;
228 + unsigned long long log_block;
230 tag = (journal_block_tag_t *) tagp;
231 flags = be16_to_cpu(tag->t_flags);
233 io_block = next_log_block++;
234 wrap(journal, next_log_block);
235 + if (pass == PASS_JMAP) {
236 + struct blk_mapping map;
238 + err = jbd2_journal_bmap(journal,
243 + map.fsblk = read_tag_block(journal, tag);
244 + map.logblk = log_block;
245 + err = jbd2_add_mapping(journal, &map);
250 err = jread(&obh, journal, io_block);
252 /* Recover what we can, but
253 @@ -753,6 +798,10 @@ static int do_one_pass(journal_t *journal,
257 + if (pass == PASS_JMAP) {
258 + jbd2_finish_transaction_infos(journal);
264 @@ -760,12 +809,12 @@ static int do_one_pass(journal_t *journal,
265 case JBD2_REVOKE_BLOCK:
266 /* If we aren't in the REVOKE pass, then we can
267 * just skip over this block. */
268 - if (pass != PASS_REVOKE) {
269 + if (pass != PASS_REVOKE && pass != PASS_JMAP) {
274 - err = scan_revoke_records(journal, bh,
275 + err = scan_revoke_records(journal, bh, pass,
276 next_commit_ID, info);
279 @@ -788,9 +837,10 @@ static int do_one_pass(journal_t *journal,
280 * transaction marks the end of the valid log.
283 - if (pass == PASS_SCAN) {
284 + if (pass == PASS_SCAN || pass == PASS_JMAP) {
285 if (!info->end_transaction)
286 info->end_transaction = next_commit_ID;
287 + info->head_block = next_log_block;
289 /* It's really bad news if different passes end up at
290 * different places (but possible due to IO errors). */
291 @@ -813,7 +863,8 @@ static int do_one_pass(journal_t *journal,
292 /* Scan a revoke record, marking all blocks mentioned as revoked. */
294 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
295 - tid_t sequence, struct recovery_info *info)
296 + enum passtype pass, tid_t sequence,
297 + struct recovery_info *info)
299 jbd2_journal_revoke_header_t *header;
301 @@ -839,16 +890,20 @@ static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
303 while (offset + record_len <= max) {
304 unsigned long long blocknr;
308 blocknr = be32_to_cpu(* ((__be32 *) (bh->b_data+offset)));
310 blocknr = be64_to_cpu(* ((__be64 *) (bh->b_data+offset)));
311 offset += record_len;
312 - err = jbd2_journal_set_revoke(journal, blocknr, sequence);
315 + if (pass == PASS_JMAP)
316 + jbd2_jmap_revoke(journal, blocknr);
318 + int err = jbd2_journal_set_revoke(journal, blocknr,