162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/fs/jbd2/recovery.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Written by Stephen C. Tweedie <sct@redhat.com>, 1999 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright 1999-2000 Red Hat Software --- All Rights Reserved 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Journal recovery routines for the generic filesystem journaling code; 1062306a36Sopenharmony_ci * part of the ext2fs journaling system. 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#ifndef __KERNEL__ 1462306a36Sopenharmony_ci#include "jfs_user.h" 1562306a36Sopenharmony_ci#else 1662306a36Sopenharmony_ci#include <linux/time.h> 1762306a36Sopenharmony_ci#include <linux/fs.h> 1862306a36Sopenharmony_ci#include <linux/jbd2.h> 1962306a36Sopenharmony_ci#include <linux/errno.h> 2062306a36Sopenharmony_ci#include <linux/crc32.h> 2162306a36Sopenharmony_ci#include <linux/blkdev.h> 2262306a36Sopenharmony_ci#endif 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* 2562306a36Sopenharmony_ci * Maintain information about the progress of the recovery job, so that 2662306a36Sopenharmony_ci * the different passes can carry information between them. 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_cistruct recovery_info 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci tid_t start_transaction; 3162306a36Sopenharmony_ci tid_t end_transaction; 3262306a36Sopenharmony_ci unsigned long head_block; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci int nr_replays; 3562306a36Sopenharmony_ci int nr_revokes; 3662306a36Sopenharmony_ci int nr_revoke_hits; 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic int do_one_pass(journal_t *journal, 4062306a36Sopenharmony_ci struct recovery_info *info, enum passtype pass); 4162306a36Sopenharmony_cistatic int scan_revoke_records(journal_t *, struct buffer_head *, 4262306a36Sopenharmony_ci tid_t, struct recovery_info *); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#ifdef __KERNEL__ 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* Release readahead buffers after use */ 4762306a36Sopenharmony_cistatic void journal_brelse_array(struct buffer_head *b[], int n) 4862306a36Sopenharmony_ci{ 4962306a36Sopenharmony_ci while (--n >= 0) 5062306a36Sopenharmony_ci brelse (b[n]); 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* 5562306a36Sopenharmony_ci * When reading from the journal, we are going through the block device 5662306a36Sopenharmony_ci * layer directly and so there is no readahead being done for us. We 5762306a36Sopenharmony_ci * need to implement any readahead ourselves if we want it to happen at 5862306a36Sopenharmony_ci * all. Recovery is basically one long sequential read, so make sure we 5962306a36Sopenharmony_ci * do the IO in reasonably large chunks. 6062306a36Sopenharmony_ci * 6162306a36Sopenharmony_ci * This is not so critical that we need to be enormously clever about 6262306a36Sopenharmony_ci * the readahead size, though. 128K is a purely arbitrary, good-enough 6362306a36Sopenharmony_ci * fixed value. 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define MAXBUF 8 6762306a36Sopenharmony_cistatic int do_readahead(journal_t *journal, unsigned int start) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci int err; 7062306a36Sopenharmony_ci unsigned int max, nbufs, next; 7162306a36Sopenharmony_ci unsigned long long blocknr; 7262306a36Sopenharmony_ci struct buffer_head *bh; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci struct buffer_head * bufs[MAXBUF]; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci /* Do up to 128K of readahead */ 7762306a36Sopenharmony_ci max = start + (128 * 1024 / journal->j_blocksize); 7862306a36Sopenharmony_ci if (max > journal->j_total_len) 7962306a36Sopenharmony_ci max = journal->j_total_len; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci /* Do the readahead itself. We'll submit MAXBUF buffer_heads at 8262306a36Sopenharmony_ci * a time to the block device IO layer. */ 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci nbufs = 0; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci for (next = start; next < max; next++) { 8762306a36Sopenharmony_ci err = jbd2_journal_bmap(journal, next, &blocknr); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (err) { 9062306a36Sopenharmony_ci printk(KERN_ERR "JBD2: bad block at offset %u\n", 9162306a36Sopenharmony_ci next); 9262306a36Sopenharmony_ci goto failed; 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); 9662306a36Sopenharmony_ci if (!bh) { 9762306a36Sopenharmony_ci err = -ENOMEM; 9862306a36Sopenharmony_ci goto failed; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (!buffer_uptodate(bh) && !buffer_locked(bh)) { 10262306a36Sopenharmony_ci bufs[nbufs++] = bh; 10362306a36Sopenharmony_ci if (nbufs == MAXBUF) { 10462306a36Sopenharmony_ci bh_readahead_batch(nbufs, bufs, 0); 10562306a36Sopenharmony_ci journal_brelse_array(bufs, nbufs); 10662306a36Sopenharmony_ci nbufs = 0; 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci } else 10962306a36Sopenharmony_ci brelse(bh); 11062306a36Sopenharmony_ci } 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci if (nbufs) 11362306a36Sopenharmony_ci bh_readahead_batch(nbufs, bufs, 0); 11462306a36Sopenharmony_ci err = 0; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_cifailed: 11762306a36Sopenharmony_ci if (nbufs) 11862306a36Sopenharmony_ci journal_brelse_array(bufs, nbufs); 11962306a36Sopenharmony_ci return err; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#endif /* __KERNEL__ */ 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/* 12662306a36Sopenharmony_ci * Read a block from the journal 12762306a36Sopenharmony_ci */ 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic int jread(struct buffer_head **bhp, journal_t *journal, 13062306a36Sopenharmony_ci unsigned int offset) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci int err; 13362306a36Sopenharmony_ci unsigned long long blocknr; 13462306a36Sopenharmony_ci struct buffer_head *bh; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci *bhp = NULL; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci if (offset >= journal->j_total_len) { 13962306a36Sopenharmony_ci printk(KERN_ERR "JBD2: corrupted journal superblock\n"); 14062306a36Sopenharmony_ci return -EFSCORRUPTED; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci err = jbd2_journal_bmap(journal, offset, &blocknr); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci if (err) { 14662306a36Sopenharmony_ci printk(KERN_ERR "JBD2: bad block at offset %u\n", 14762306a36Sopenharmony_ci offset); 14862306a36Sopenharmony_ci return err; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); 15262306a36Sopenharmony_ci if (!bh) 15362306a36Sopenharmony_ci return -ENOMEM; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci if (!buffer_uptodate(bh)) { 15662306a36Sopenharmony_ci /* 15762306a36Sopenharmony_ci * If this is a brand new buffer, start readahead. 15862306a36Sopenharmony_ci * Otherwise, we assume we are already reading it. 15962306a36Sopenharmony_ci */ 16062306a36Sopenharmony_ci bool need_readahead = !buffer_req(bh); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci bh_read_nowait(bh, 0); 16362306a36Sopenharmony_ci if (need_readahead) 16462306a36Sopenharmony_ci do_readahead(journal, offset); 16562306a36Sopenharmony_ci wait_on_buffer(bh); 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (!buffer_uptodate(bh)) { 16962306a36Sopenharmony_ci printk(KERN_ERR "JBD2: Failed to read block at offset %u\n", 17062306a36Sopenharmony_ci offset); 17162306a36Sopenharmony_ci brelse(bh); 17262306a36Sopenharmony_ci return -EIO; 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci *bhp = bh; 17662306a36Sopenharmony_ci return 0; 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic int jbd2_descriptor_block_csum_verify(journal_t *j, void *buf) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci struct jbd2_journal_block_tail *tail; 18262306a36Sopenharmony_ci __be32 provided; 18362306a36Sopenharmony_ci __u32 calculated; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci if (!jbd2_journal_has_csum_v2or3(j)) 18662306a36Sopenharmony_ci return 1; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci tail = (struct jbd2_journal_block_tail *)((char *)buf + 18962306a36Sopenharmony_ci j->j_blocksize - sizeof(struct jbd2_journal_block_tail)); 19062306a36Sopenharmony_ci provided = tail->t_checksum; 19162306a36Sopenharmony_ci tail->t_checksum = 0; 19262306a36Sopenharmony_ci calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize); 19362306a36Sopenharmony_ci tail->t_checksum = provided; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci return provided == cpu_to_be32(calculated); 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci/* 19962306a36Sopenharmony_ci * Count the number of in-use tags in a journal descriptor block. 20062306a36Sopenharmony_ci */ 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_cistatic int count_tags(journal_t *journal, struct buffer_head *bh) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci char * tagp; 20562306a36Sopenharmony_ci journal_block_tag_t tag; 20662306a36Sopenharmony_ci int nr = 0, size = journal->j_blocksize; 20762306a36Sopenharmony_ci int tag_bytes = journal_tag_bytes(journal); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci if (jbd2_journal_has_csum_v2or3(journal)) 21062306a36Sopenharmony_ci size -= sizeof(struct jbd2_journal_block_tail); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci tagp = &bh->b_data[sizeof(journal_header_t)]; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci while ((tagp - bh->b_data + tag_bytes) <= size) { 21562306a36Sopenharmony_ci memcpy(&tag, tagp, sizeof(tag)); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci nr++; 21862306a36Sopenharmony_ci tagp += tag_bytes; 21962306a36Sopenharmony_ci if (!(tag.t_flags & cpu_to_be16(JBD2_FLAG_SAME_UUID))) 22062306a36Sopenharmony_ci tagp += 16; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci if (tag.t_flags & cpu_to_be16(JBD2_FLAG_LAST_TAG)) 22362306a36Sopenharmony_ci break; 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci return nr; 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci/* Make sure we wrap around the log correctly! */ 23162306a36Sopenharmony_ci#define wrap(journal, var) \ 23262306a36Sopenharmony_cido { \ 23362306a36Sopenharmony_ci if (var >= (journal)->j_last) \ 23462306a36Sopenharmony_ci var -= ((journal)->j_last - (journal)->j_first); \ 23562306a36Sopenharmony_ci} while (0) 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic int fc_do_one_pass(journal_t *journal, 23862306a36Sopenharmony_ci struct recovery_info *info, enum passtype pass) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci unsigned int expected_commit_id = info->end_transaction; 24162306a36Sopenharmony_ci unsigned long next_fc_block; 24262306a36Sopenharmony_ci struct buffer_head *bh; 24362306a36Sopenharmony_ci int err = 0; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci next_fc_block = journal->j_fc_first; 24662306a36Sopenharmony_ci if (!journal->j_fc_replay_callback) 24762306a36Sopenharmony_ci return 0; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci while (next_fc_block <= journal->j_fc_last) { 25062306a36Sopenharmony_ci jbd2_debug(3, "Fast commit replay: next block %ld\n", 25162306a36Sopenharmony_ci next_fc_block); 25262306a36Sopenharmony_ci err = jread(&bh, journal, next_fc_block); 25362306a36Sopenharmony_ci if (err) { 25462306a36Sopenharmony_ci jbd2_debug(3, "Fast commit replay: read error\n"); 25562306a36Sopenharmony_ci break; 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci err = journal->j_fc_replay_callback(journal, bh, pass, 25962306a36Sopenharmony_ci next_fc_block - journal->j_fc_first, 26062306a36Sopenharmony_ci expected_commit_id); 26162306a36Sopenharmony_ci brelse(bh); 26262306a36Sopenharmony_ci next_fc_block++; 26362306a36Sopenharmony_ci if (err < 0 || err == JBD2_FC_REPLAY_STOP) 26462306a36Sopenharmony_ci break; 26562306a36Sopenharmony_ci err = 0; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci if (err) 26962306a36Sopenharmony_ci jbd2_debug(3, "Fast commit replay failed, err = %d\n", err); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci return err; 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci/** 27562306a36Sopenharmony_ci * jbd2_journal_recover - recovers a on-disk journal 27662306a36Sopenharmony_ci * @journal: the journal to recover 27762306a36Sopenharmony_ci * 27862306a36Sopenharmony_ci * The primary function for recovering the log contents when mounting a 27962306a36Sopenharmony_ci * journaled device. 28062306a36Sopenharmony_ci * 28162306a36Sopenharmony_ci * Recovery is done in three passes. In the first pass, we look for the 28262306a36Sopenharmony_ci * end of the log. In the second, we assemble the list of revoke 28362306a36Sopenharmony_ci * blocks. In the third and final pass, we replay any un-revoked blocks 28462306a36Sopenharmony_ci * in the log. 28562306a36Sopenharmony_ci */ 28662306a36Sopenharmony_ciint jbd2_journal_recover(journal_t *journal) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci int err, err2; 28962306a36Sopenharmony_ci journal_superblock_t * sb; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci struct recovery_info info; 29262306a36Sopenharmony_ci errseq_t wb_err; 29362306a36Sopenharmony_ci struct address_space *mapping; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci memset(&info, 0, sizeof(info)); 29662306a36Sopenharmony_ci sb = journal->j_superblock; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* 29962306a36Sopenharmony_ci * The journal superblock's s_start field (the current log head) 30062306a36Sopenharmony_ci * is always zero if, and only if, the journal was cleanly 30162306a36Sopenharmony_ci * unmounted. 30262306a36Sopenharmony_ci */ 30362306a36Sopenharmony_ci if (!sb->s_start) { 30462306a36Sopenharmony_ci jbd2_debug(1, "No recovery required, last transaction %d, head block %u\n", 30562306a36Sopenharmony_ci be32_to_cpu(sb->s_sequence), be32_to_cpu(sb->s_head)); 30662306a36Sopenharmony_ci journal->j_transaction_sequence = be32_to_cpu(sb->s_sequence) + 1; 30762306a36Sopenharmony_ci journal->j_head = be32_to_cpu(sb->s_head); 30862306a36Sopenharmony_ci return 0; 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci wb_err = 0; 31262306a36Sopenharmony_ci mapping = journal->j_fs_dev->bd_inode->i_mapping; 31362306a36Sopenharmony_ci errseq_check_and_advance(&mapping->wb_err, &wb_err); 31462306a36Sopenharmony_ci err = do_one_pass(journal, &info, PASS_SCAN); 31562306a36Sopenharmony_ci if (!err) 31662306a36Sopenharmony_ci err = do_one_pass(journal, &info, PASS_REVOKE); 31762306a36Sopenharmony_ci if (!err) 31862306a36Sopenharmony_ci err = do_one_pass(journal, &info, PASS_REPLAY); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci jbd2_debug(1, "JBD2: recovery, exit status %d, " 32162306a36Sopenharmony_ci "recovered transactions %u to %u\n", 32262306a36Sopenharmony_ci err, info.start_transaction, info.end_transaction); 32362306a36Sopenharmony_ci jbd2_debug(1, "JBD2: Replayed %d and revoked %d/%d blocks\n", 32462306a36Sopenharmony_ci info.nr_replays, info.nr_revoke_hits, info.nr_revokes); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci /* Restart the log at the next transaction ID, thus invalidating 32762306a36Sopenharmony_ci * any existing commit records in the log. */ 32862306a36Sopenharmony_ci journal->j_transaction_sequence = ++info.end_transaction; 32962306a36Sopenharmony_ci journal->j_head = info.head_block; 33062306a36Sopenharmony_ci jbd2_debug(1, "JBD2: last transaction %d, head block %lu\n", 33162306a36Sopenharmony_ci journal->j_transaction_sequence, journal->j_head); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci jbd2_journal_clear_revoke(journal); 33462306a36Sopenharmony_ci err2 = sync_blockdev(journal->j_fs_dev); 33562306a36Sopenharmony_ci if (!err) 33662306a36Sopenharmony_ci err = err2; 33762306a36Sopenharmony_ci err2 = errseq_check_and_advance(&mapping->wb_err, &wb_err); 33862306a36Sopenharmony_ci if (!err) 33962306a36Sopenharmony_ci err = err2; 34062306a36Sopenharmony_ci /* Make sure all replayed data is on permanent storage */ 34162306a36Sopenharmony_ci if (journal->j_flags & JBD2_BARRIER) { 34262306a36Sopenharmony_ci err2 = blkdev_issue_flush(journal->j_fs_dev); 34362306a36Sopenharmony_ci if (!err) 34462306a36Sopenharmony_ci err = err2; 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci return err; 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci/** 35062306a36Sopenharmony_ci * jbd2_journal_skip_recovery - Start journal and wipe exiting records 35162306a36Sopenharmony_ci * @journal: journal to startup 35262306a36Sopenharmony_ci * 35362306a36Sopenharmony_ci * Locate any valid recovery information from the journal and set up the 35462306a36Sopenharmony_ci * journal structures in memory to ignore it (presumably because the 35562306a36Sopenharmony_ci * caller has evidence that it is out of date). 35662306a36Sopenharmony_ci * This function doesn't appear to be exported.. 35762306a36Sopenharmony_ci * 35862306a36Sopenharmony_ci * We perform one pass over the journal to allow us to tell the user how 35962306a36Sopenharmony_ci * much recovery information is being erased, and to let us initialise 36062306a36Sopenharmony_ci * the journal transaction sequence numbers to the next unused ID. 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_ciint jbd2_journal_skip_recovery(journal_t *journal) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci int err; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci struct recovery_info info; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci memset (&info, 0, sizeof(info)); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci err = do_one_pass(journal, &info, PASS_SCAN); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci if (err) { 37362306a36Sopenharmony_ci printk(KERN_ERR "JBD2: error %d scanning journal\n", err); 37462306a36Sopenharmony_ci ++journal->j_transaction_sequence; 37562306a36Sopenharmony_ci journal->j_head = journal->j_first; 37662306a36Sopenharmony_ci } else { 37762306a36Sopenharmony_ci#ifdef CONFIG_JBD2_DEBUG 37862306a36Sopenharmony_ci int dropped = info.end_transaction - 37962306a36Sopenharmony_ci be32_to_cpu(journal->j_superblock->s_sequence); 38062306a36Sopenharmony_ci jbd2_debug(1, 38162306a36Sopenharmony_ci "JBD2: ignoring %d transaction%s from the journal.\n", 38262306a36Sopenharmony_ci dropped, (dropped == 1) ? "" : "s"); 38362306a36Sopenharmony_ci#endif 38462306a36Sopenharmony_ci journal->j_transaction_sequence = ++info.end_transaction; 38562306a36Sopenharmony_ci journal->j_head = info.head_block; 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci journal->j_tail = 0; 38962306a36Sopenharmony_ci return err; 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic inline unsigned long long read_tag_block(journal_t *journal, 39362306a36Sopenharmony_ci journal_block_tag_t *tag) 39462306a36Sopenharmony_ci{ 39562306a36Sopenharmony_ci unsigned long long block = be32_to_cpu(tag->t_blocknr); 39662306a36Sopenharmony_ci if (jbd2_has_feature_64bit(journal)) 39762306a36Sopenharmony_ci block |= (u64)be32_to_cpu(tag->t_blocknr_high) << 32; 39862306a36Sopenharmony_ci return block; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci/* 40262306a36Sopenharmony_ci * calc_chksums calculates the checksums for the blocks described in the 40362306a36Sopenharmony_ci * descriptor block. 40462306a36Sopenharmony_ci */ 40562306a36Sopenharmony_cistatic int calc_chksums(journal_t *journal, struct buffer_head *bh, 40662306a36Sopenharmony_ci unsigned long *next_log_block, __u32 *crc32_sum) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci int i, num_blks, err; 40962306a36Sopenharmony_ci unsigned long io_block; 41062306a36Sopenharmony_ci struct buffer_head *obh; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci num_blks = count_tags(journal, bh); 41362306a36Sopenharmony_ci /* Calculate checksum of the descriptor block. */ 41462306a36Sopenharmony_ci *crc32_sum = crc32_be(*crc32_sum, (void *)bh->b_data, bh->b_size); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci for (i = 0; i < num_blks; i++) { 41762306a36Sopenharmony_ci io_block = (*next_log_block)++; 41862306a36Sopenharmony_ci wrap(journal, *next_log_block); 41962306a36Sopenharmony_ci err = jread(&obh, journal, io_block); 42062306a36Sopenharmony_ci if (err) { 42162306a36Sopenharmony_ci printk(KERN_ERR "JBD2: IO error %d recovering block " 42262306a36Sopenharmony_ci "%lu in log\n", err, io_block); 42362306a36Sopenharmony_ci return 1; 42462306a36Sopenharmony_ci } else { 42562306a36Sopenharmony_ci *crc32_sum = crc32_be(*crc32_sum, (void *)obh->b_data, 42662306a36Sopenharmony_ci obh->b_size); 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci put_bh(obh); 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci return 0; 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cistatic int jbd2_commit_block_csum_verify(journal_t *j, void *buf) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci struct commit_header *h; 43662306a36Sopenharmony_ci __be32 provided; 43762306a36Sopenharmony_ci __u32 calculated; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci if (!jbd2_journal_has_csum_v2or3(j)) 44062306a36Sopenharmony_ci return 1; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci h = buf; 44362306a36Sopenharmony_ci provided = h->h_chksum[0]; 44462306a36Sopenharmony_ci h->h_chksum[0] = 0; 44562306a36Sopenharmony_ci calculated = jbd2_chksum(j, j->j_csum_seed, buf, j->j_blocksize); 44662306a36Sopenharmony_ci h->h_chksum[0] = provided; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci return provided == cpu_to_be32(calculated); 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_cistatic int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag, 45262306a36Sopenharmony_ci journal_block_tag3_t *tag3, 45362306a36Sopenharmony_ci void *buf, __u32 sequence) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci __u32 csum32; 45662306a36Sopenharmony_ci __be32 seq; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci if (!jbd2_journal_has_csum_v2or3(j)) 45962306a36Sopenharmony_ci return 1; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci seq = cpu_to_be32(sequence); 46262306a36Sopenharmony_ci csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq)); 46362306a36Sopenharmony_ci csum32 = jbd2_chksum(j, csum32, buf, j->j_blocksize); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci if (jbd2_has_feature_csum3(j)) 46662306a36Sopenharmony_ci return tag3->t_checksum == cpu_to_be32(csum32); 46762306a36Sopenharmony_ci else 46862306a36Sopenharmony_ci return tag->t_checksum == cpu_to_be16(csum32); 46962306a36Sopenharmony_ci} 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic int do_one_pass(journal_t *journal, 47262306a36Sopenharmony_ci struct recovery_info *info, enum passtype pass) 47362306a36Sopenharmony_ci{ 47462306a36Sopenharmony_ci unsigned int first_commit_ID, next_commit_ID; 47562306a36Sopenharmony_ci unsigned long next_log_block, head_block; 47662306a36Sopenharmony_ci int err, success = 0; 47762306a36Sopenharmony_ci journal_superblock_t * sb; 47862306a36Sopenharmony_ci journal_header_t * tmp; 47962306a36Sopenharmony_ci struct buffer_head * bh; 48062306a36Sopenharmony_ci unsigned int sequence; 48162306a36Sopenharmony_ci int blocktype; 48262306a36Sopenharmony_ci int tag_bytes = journal_tag_bytes(journal); 48362306a36Sopenharmony_ci __u32 crc32_sum = ~0; /* Transactional Checksums */ 48462306a36Sopenharmony_ci int descr_csum_size = 0; 48562306a36Sopenharmony_ci int block_error = 0; 48662306a36Sopenharmony_ci bool need_check_commit_time = false; 48762306a36Sopenharmony_ci __u64 last_trans_commit_time = 0, commit_time; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci /* 49062306a36Sopenharmony_ci * First thing is to establish what we expect to find in the log 49162306a36Sopenharmony_ci * (in terms of transaction IDs), and where (in terms of log 49262306a36Sopenharmony_ci * block offsets): query the superblock. 49362306a36Sopenharmony_ci */ 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci sb = journal->j_superblock; 49662306a36Sopenharmony_ci next_commit_ID = be32_to_cpu(sb->s_sequence); 49762306a36Sopenharmony_ci next_log_block = be32_to_cpu(sb->s_start); 49862306a36Sopenharmony_ci head_block = next_log_block; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci first_commit_ID = next_commit_ID; 50162306a36Sopenharmony_ci if (pass == PASS_SCAN) 50262306a36Sopenharmony_ci info->start_transaction = first_commit_ID; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci jbd2_debug(1, "Starting recovery pass %d\n", pass); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci /* 50762306a36Sopenharmony_ci * Now we walk through the log, transaction by transaction, 50862306a36Sopenharmony_ci * making sure that each transaction has a commit block in the 50962306a36Sopenharmony_ci * expected place. Each complete transaction gets replayed back 51062306a36Sopenharmony_ci * into the main filesystem. 51162306a36Sopenharmony_ci */ 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci while (1) { 51462306a36Sopenharmony_ci int flags; 51562306a36Sopenharmony_ci char * tagp; 51662306a36Sopenharmony_ci journal_block_tag_t tag; 51762306a36Sopenharmony_ci struct buffer_head * obh; 51862306a36Sopenharmony_ci struct buffer_head * nbh; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci cond_resched(); 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci /* If we already know where to stop the log traversal, 52362306a36Sopenharmony_ci * check right now that we haven't gone past the end of 52462306a36Sopenharmony_ci * the log. */ 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci if (pass != PASS_SCAN) 52762306a36Sopenharmony_ci if (tid_geq(next_commit_ID, info->end_transaction)) 52862306a36Sopenharmony_ci break; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci jbd2_debug(2, "Scanning for sequence ID %u at %lu/%lu\n", 53162306a36Sopenharmony_ci next_commit_ID, next_log_block, journal->j_last); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci /* Skip over each chunk of the transaction looking 53462306a36Sopenharmony_ci * either the next descriptor block or the final commit 53562306a36Sopenharmony_ci * record. */ 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci jbd2_debug(3, "JBD2: checking block %ld\n", next_log_block); 53862306a36Sopenharmony_ci err = jread(&bh, journal, next_log_block); 53962306a36Sopenharmony_ci if (err) 54062306a36Sopenharmony_ci goto failed; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci next_log_block++; 54362306a36Sopenharmony_ci wrap(journal, next_log_block); 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci /* What kind of buffer is it? 54662306a36Sopenharmony_ci * 54762306a36Sopenharmony_ci * If it is a descriptor block, check that it has the 54862306a36Sopenharmony_ci * expected sequence number. Otherwise, we're all done 54962306a36Sopenharmony_ci * here. */ 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci tmp = (journal_header_t *)bh->b_data; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci if (tmp->h_magic != cpu_to_be32(JBD2_MAGIC_NUMBER)) { 55462306a36Sopenharmony_ci brelse(bh); 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci blocktype = be32_to_cpu(tmp->h_blocktype); 55962306a36Sopenharmony_ci sequence = be32_to_cpu(tmp->h_sequence); 56062306a36Sopenharmony_ci jbd2_debug(3, "Found magic %d, sequence %d\n", 56162306a36Sopenharmony_ci blocktype, sequence); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci if (sequence != next_commit_ID) { 56462306a36Sopenharmony_ci brelse(bh); 56562306a36Sopenharmony_ci break; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci /* OK, we have a valid descriptor block which matches 56962306a36Sopenharmony_ci * all of the sequence number checks. What are we going 57062306a36Sopenharmony_ci * to do with it? That depends on the pass... */ 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci switch(blocktype) { 57362306a36Sopenharmony_ci case JBD2_DESCRIPTOR_BLOCK: 57462306a36Sopenharmony_ci /* Verify checksum first */ 57562306a36Sopenharmony_ci if (jbd2_journal_has_csum_v2or3(journal)) 57662306a36Sopenharmony_ci descr_csum_size = 57762306a36Sopenharmony_ci sizeof(struct jbd2_journal_block_tail); 57862306a36Sopenharmony_ci if (descr_csum_size > 0 && 57962306a36Sopenharmony_ci !jbd2_descriptor_block_csum_verify(journal, 58062306a36Sopenharmony_ci bh->b_data)) { 58162306a36Sopenharmony_ci /* 58262306a36Sopenharmony_ci * PASS_SCAN can see stale blocks due to lazy 58362306a36Sopenharmony_ci * journal init. Don't error out on those yet. 58462306a36Sopenharmony_ci */ 58562306a36Sopenharmony_ci if (pass != PASS_SCAN) { 58662306a36Sopenharmony_ci pr_err("JBD2: Invalid checksum recovering block %lu in log\n", 58762306a36Sopenharmony_ci next_log_block); 58862306a36Sopenharmony_ci err = -EFSBADCRC; 58962306a36Sopenharmony_ci brelse(bh); 59062306a36Sopenharmony_ci goto failed; 59162306a36Sopenharmony_ci } 59262306a36Sopenharmony_ci need_check_commit_time = true; 59362306a36Sopenharmony_ci jbd2_debug(1, 59462306a36Sopenharmony_ci "invalid descriptor block found in %lu\n", 59562306a36Sopenharmony_ci next_log_block); 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci /* If it is a valid descriptor block, replay it 59962306a36Sopenharmony_ci * in pass REPLAY; if journal_checksums enabled, then 60062306a36Sopenharmony_ci * calculate checksums in PASS_SCAN, otherwise, 60162306a36Sopenharmony_ci * just skip over the blocks it describes. */ 60262306a36Sopenharmony_ci if (pass != PASS_REPLAY) { 60362306a36Sopenharmony_ci if (pass == PASS_SCAN && 60462306a36Sopenharmony_ci jbd2_has_feature_checksum(journal) && 60562306a36Sopenharmony_ci !need_check_commit_time && 60662306a36Sopenharmony_ci !info->end_transaction) { 60762306a36Sopenharmony_ci if (calc_chksums(journal, bh, 60862306a36Sopenharmony_ci &next_log_block, 60962306a36Sopenharmony_ci &crc32_sum)) { 61062306a36Sopenharmony_ci put_bh(bh); 61162306a36Sopenharmony_ci break; 61262306a36Sopenharmony_ci } 61362306a36Sopenharmony_ci put_bh(bh); 61462306a36Sopenharmony_ci continue; 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci next_log_block += count_tags(journal, bh); 61762306a36Sopenharmony_ci wrap(journal, next_log_block); 61862306a36Sopenharmony_ci put_bh(bh); 61962306a36Sopenharmony_ci continue; 62062306a36Sopenharmony_ci } 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci /* A descriptor block: we can now write all of 62362306a36Sopenharmony_ci * the data blocks. Yay, useful work is finally 62462306a36Sopenharmony_ci * getting done here! */ 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci tagp = &bh->b_data[sizeof(journal_header_t)]; 62762306a36Sopenharmony_ci while ((tagp - bh->b_data + tag_bytes) 62862306a36Sopenharmony_ci <= journal->j_blocksize - descr_csum_size) { 62962306a36Sopenharmony_ci unsigned long io_block; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci memcpy(&tag, tagp, sizeof(tag)); 63262306a36Sopenharmony_ci flags = be16_to_cpu(tag.t_flags); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci io_block = next_log_block++; 63562306a36Sopenharmony_ci wrap(journal, next_log_block); 63662306a36Sopenharmony_ci err = jread(&obh, journal, io_block); 63762306a36Sopenharmony_ci if (err) { 63862306a36Sopenharmony_ci /* Recover what we can, but 63962306a36Sopenharmony_ci * report failure at the end. */ 64062306a36Sopenharmony_ci success = err; 64162306a36Sopenharmony_ci printk(KERN_ERR 64262306a36Sopenharmony_ci "JBD2: IO error %d recovering " 64362306a36Sopenharmony_ci "block %ld in log\n", 64462306a36Sopenharmony_ci err, io_block); 64562306a36Sopenharmony_ci } else { 64662306a36Sopenharmony_ci unsigned long long blocknr; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci J_ASSERT(obh != NULL); 64962306a36Sopenharmony_ci blocknr = read_tag_block(journal, 65062306a36Sopenharmony_ci &tag); 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci /* If the block has been 65362306a36Sopenharmony_ci * revoked, then we're all done 65462306a36Sopenharmony_ci * here. */ 65562306a36Sopenharmony_ci if (jbd2_journal_test_revoke 65662306a36Sopenharmony_ci (journal, blocknr, 65762306a36Sopenharmony_ci next_commit_ID)) { 65862306a36Sopenharmony_ci brelse(obh); 65962306a36Sopenharmony_ci ++info->nr_revoke_hits; 66062306a36Sopenharmony_ci goto skip_write; 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci /* Look for block corruption */ 66462306a36Sopenharmony_ci if (!jbd2_block_tag_csum_verify( 66562306a36Sopenharmony_ci journal, &tag, (journal_block_tag3_t *)tagp, 66662306a36Sopenharmony_ci obh->b_data, be32_to_cpu(tmp->h_sequence))) { 66762306a36Sopenharmony_ci brelse(obh); 66862306a36Sopenharmony_ci success = -EFSBADCRC; 66962306a36Sopenharmony_ci printk(KERN_ERR "JBD2: Invalid " 67062306a36Sopenharmony_ci "checksum recovering " 67162306a36Sopenharmony_ci "data block %llu in " 67262306a36Sopenharmony_ci "log\n", blocknr); 67362306a36Sopenharmony_ci block_error = 1; 67462306a36Sopenharmony_ci goto skip_write; 67562306a36Sopenharmony_ci } 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci /* Find a buffer for the new 67862306a36Sopenharmony_ci * data being restored */ 67962306a36Sopenharmony_ci nbh = __getblk(journal->j_fs_dev, 68062306a36Sopenharmony_ci blocknr, 68162306a36Sopenharmony_ci journal->j_blocksize); 68262306a36Sopenharmony_ci if (nbh == NULL) { 68362306a36Sopenharmony_ci printk(KERN_ERR 68462306a36Sopenharmony_ci "JBD2: Out of memory " 68562306a36Sopenharmony_ci "during recovery.\n"); 68662306a36Sopenharmony_ci err = -ENOMEM; 68762306a36Sopenharmony_ci brelse(bh); 68862306a36Sopenharmony_ci brelse(obh); 68962306a36Sopenharmony_ci goto failed; 69062306a36Sopenharmony_ci } 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci lock_buffer(nbh); 69362306a36Sopenharmony_ci memcpy(nbh->b_data, obh->b_data, 69462306a36Sopenharmony_ci journal->j_blocksize); 69562306a36Sopenharmony_ci if (flags & JBD2_FLAG_ESCAPE) { 69662306a36Sopenharmony_ci *((__be32 *)nbh->b_data) = 69762306a36Sopenharmony_ci cpu_to_be32(JBD2_MAGIC_NUMBER); 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci BUFFER_TRACE(nbh, "marking dirty"); 70162306a36Sopenharmony_ci set_buffer_uptodate(nbh); 70262306a36Sopenharmony_ci mark_buffer_dirty(nbh); 70362306a36Sopenharmony_ci BUFFER_TRACE(nbh, "marking uptodate"); 70462306a36Sopenharmony_ci ++info->nr_replays; 70562306a36Sopenharmony_ci unlock_buffer(nbh); 70662306a36Sopenharmony_ci brelse(obh); 70762306a36Sopenharmony_ci brelse(nbh); 70862306a36Sopenharmony_ci } 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci skip_write: 71162306a36Sopenharmony_ci tagp += tag_bytes; 71262306a36Sopenharmony_ci if (!(flags & JBD2_FLAG_SAME_UUID)) 71362306a36Sopenharmony_ci tagp += 16; 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci if (flags & JBD2_FLAG_LAST_TAG) 71662306a36Sopenharmony_ci break; 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci brelse(bh); 72062306a36Sopenharmony_ci continue; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci case JBD2_COMMIT_BLOCK: 72362306a36Sopenharmony_ci /* How to differentiate between interrupted commit 72462306a36Sopenharmony_ci * and journal corruption ? 72562306a36Sopenharmony_ci * 72662306a36Sopenharmony_ci * {nth transaction} 72762306a36Sopenharmony_ci * Checksum Verification Failed 72862306a36Sopenharmony_ci * | 72962306a36Sopenharmony_ci * ____________________ 73062306a36Sopenharmony_ci * | | 73162306a36Sopenharmony_ci * async_commit sync_commit 73262306a36Sopenharmony_ci * | | 73362306a36Sopenharmony_ci * | GO TO NEXT "Journal Corruption" 73462306a36Sopenharmony_ci * | TRANSACTION 73562306a36Sopenharmony_ci * | 73662306a36Sopenharmony_ci * {(n+1)th transanction} 73762306a36Sopenharmony_ci * | 73862306a36Sopenharmony_ci * _______|______________ 73962306a36Sopenharmony_ci * | | 74062306a36Sopenharmony_ci * Commit block found Commit block not found 74162306a36Sopenharmony_ci * | | 74262306a36Sopenharmony_ci * "Journal Corruption" | 74362306a36Sopenharmony_ci * _____________|_________ 74462306a36Sopenharmony_ci * | | 74562306a36Sopenharmony_ci * nth trans corrupt OR nth trans 74662306a36Sopenharmony_ci * and (n+1)th interrupted interrupted 74762306a36Sopenharmony_ci * before commit block 74862306a36Sopenharmony_ci * could reach the disk. 74962306a36Sopenharmony_ci * (Cannot find the difference in above 75062306a36Sopenharmony_ci * mentioned conditions. Hence assume 75162306a36Sopenharmony_ci * "Interrupted Commit".) 75262306a36Sopenharmony_ci */ 75362306a36Sopenharmony_ci commit_time = be64_to_cpu( 75462306a36Sopenharmony_ci ((struct commit_header *)bh->b_data)->h_commit_sec); 75562306a36Sopenharmony_ci /* 75662306a36Sopenharmony_ci * If need_check_commit_time is set, it means we are in 75762306a36Sopenharmony_ci * PASS_SCAN and csum verify failed before. If 75862306a36Sopenharmony_ci * commit_time is increasing, it's the same journal, 75962306a36Sopenharmony_ci * otherwise it is stale journal block, just end this 76062306a36Sopenharmony_ci * recovery. 76162306a36Sopenharmony_ci */ 76262306a36Sopenharmony_ci if (need_check_commit_time) { 76362306a36Sopenharmony_ci if (commit_time >= last_trans_commit_time) { 76462306a36Sopenharmony_ci pr_err("JBD2: Invalid checksum found in transaction %u\n", 76562306a36Sopenharmony_ci next_commit_ID); 76662306a36Sopenharmony_ci err = -EFSBADCRC; 76762306a36Sopenharmony_ci brelse(bh); 76862306a36Sopenharmony_ci goto failed; 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci ignore_crc_mismatch: 77162306a36Sopenharmony_ci /* 77262306a36Sopenharmony_ci * It likely does not belong to same journal, 77362306a36Sopenharmony_ci * just end this recovery with success. 77462306a36Sopenharmony_ci */ 77562306a36Sopenharmony_ci jbd2_debug(1, "JBD2: Invalid checksum ignored in transaction %u, likely stale data\n", 77662306a36Sopenharmony_ci next_commit_ID); 77762306a36Sopenharmony_ci brelse(bh); 77862306a36Sopenharmony_ci goto done; 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci /* 78262306a36Sopenharmony_ci * Found an expected commit block: if checksums 78362306a36Sopenharmony_ci * are present, verify them in PASS_SCAN; else not 78462306a36Sopenharmony_ci * much to do other than move on to the next sequence 78562306a36Sopenharmony_ci * number. 78662306a36Sopenharmony_ci */ 78762306a36Sopenharmony_ci if (pass == PASS_SCAN && 78862306a36Sopenharmony_ci jbd2_has_feature_checksum(journal)) { 78962306a36Sopenharmony_ci struct commit_header *cbh = 79062306a36Sopenharmony_ci (struct commit_header *)bh->b_data; 79162306a36Sopenharmony_ci unsigned found_chksum = 79262306a36Sopenharmony_ci be32_to_cpu(cbh->h_chksum[0]); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci if (info->end_transaction) { 79562306a36Sopenharmony_ci journal->j_failed_commit = 79662306a36Sopenharmony_ci info->end_transaction; 79762306a36Sopenharmony_ci brelse(bh); 79862306a36Sopenharmony_ci break; 79962306a36Sopenharmony_ci } 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci /* Neither checksum match nor unused? */ 80262306a36Sopenharmony_ci if (!((crc32_sum == found_chksum && 80362306a36Sopenharmony_ci cbh->h_chksum_type == 80462306a36Sopenharmony_ci JBD2_CRC32_CHKSUM && 80562306a36Sopenharmony_ci cbh->h_chksum_size == 80662306a36Sopenharmony_ci JBD2_CRC32_CHKSUM_SIZE) || 80762306a36Sopenharmony_ci (cbh->h_chksum_type == 0 && 80862306a36Sopenharmony_ci cbh->h_chksum_size == 0 && 80962306a36Sopenharmony_ci found_chksum == 0))) 81062306a36Sopenharmony_ci goto chksum_error; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci crc32_sum = ~0; 81362306a36Sopenharmony_ci } 81462306a36Sopenharmony_ci if (pass == PASS_SCAN && 81562306a36Sopenharmony_ci !jbd2_commit_block_csum_verify(journal, 81662306a36Sopenharmony_ci bh->b_data)) { 81762306a36Sopenharmony_ci chksum_error: 81862306a36Sopenharmony_ci if (commit_time < last_trans_commit_time) 81962306a36Sopenharmony_ci goto ignore_crc_mismatch; 82062306a36Sopenharmony_ci info->end_transaction = next_commit_ID; 82162306a36Sopenharmony_ci info->head_block = head_block; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci if (!jbd2_has_feature_async_commit(journal)) { 82462306a36Sopenharmony_ci journal->j_failed_commit = 82562306a36Sopenharmony_ci next_commit_ID; 82662306a36Sopenharmony_ci brelse(bh); 82762306a36Sopenharmony_ci break; 82862306a36Sopenharmony_ci } 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci if (pass == PASS_SCAN) { 83162306a36Sopenharmony_ci last_trans_commit_time = commit_time; 83262306a36Sopenharmony_ci head_block = next_log_block; 83362306a36Sopenharmony_ci } 83462306a36Sopenharmony_ci brelse(bh); 83562306a36Sopenharmony_ci next_commit_ID++; 83662306a36Sopenharmony_ci continue; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci case JBD2_REVOKE_BLOCK: 83962306a36Sopenharmony_ci /* 84062306a36Sopenharmony_ci * Check revoke block crc in pass_scan, if csum verify 84162306a36Sopenharmony_ci * failed, check commit block time later. 84262306a36Sopenharmony_ci */ 84362306a36Sopenharmony_ci if (pass == PASS_SCAN && 84462306a36Sopenharmony_ci !jbd2_descriptor_block_csum_verify(journal, 84562306a36Sopenharmony_ci bh->b_data)) { 84662306a36Sopenharmony_ci jbd2_debug(1, "JBD2: invalid revoke block found in %lu\n", 84762306a36Sopenharmony_ci next_log_block); 84862306a36Sopenharmony_ci need_check_commit_time = true; 84962306a36Sopenharmony_ci } 85062306a36Sopenharmony_ci /* If we aren't in the REVOKE pass, then we can 85162306a36Sopenharmony_ci * just skip over this block. */ 85262306a36Sopenharmony_ci if (pass != PASS_REVOKE) { 85362306a36Sopenharmony_ci brelse(bh); 85462306a36Sopenharmony_ci continue; 85562306a36Sopenharmony_ci } 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci err = scan_revoke_records(journal, bh, 85862306a36Sopenharmony_ci next_commit_ID, info); 85962306a36Sopenharmony_ci brelse(bh); 86062306a36Sopenharmony_ci if (err) 86162306a36Sopenharmony_ci goto failed; 86262306a36Sopenharmony_ci continue; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci default: 86562306a36Sopenharmony_ci jbd2_debug(3, "Unrecognised magic %d, end of scan.\n", 86662306a36Sopenharmony_ci blocktype); 86762306a36Sopenharmony_ci brelse(bh); 86862306a36Sopenharmony_ci goto done; 86962306a36Sopenharmony_ci } 87062306a36Sopenharmony_ci } 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci done: 87362306a36Sopenharmony_ci /* 87462306a36Sopenharmony_ci * We broke out of the log scan loop: either we came to the 87562306a36Sopenharmony_ci * known end of the log or we found an unexpected block in the 87662306a36Sopenharmony_ci * log. If the latter happened, then we know that the "current" 87762306a36Sopenharmony_ci * transaction marks the end of the valid log. 87862306a36Sopenharmony_ci */ 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci if (pass == PASS_SCAN) { 88162306a36Sopenharmony_ci if (!info->end_transaction) 88262306a36Sopenharmony_ci info->end_transaction = next_commit_ID; 88362306a36Sopenharmony_ci if (!info->head_block) 88462306a36Sopenharmony_ci info->head_block = head_block; 88562306a36Sopenharmony_ci } else { 88662306a36Sopenharmony_ci /* It's really bad news if different passes end up at 88762306a36Sopenharmony_ci * different places (but possible due to IO errors). */ 88862306a36Sopenharmony_ci if (info->end_transaction != next_commit_ID) { 88962306a36Sopenharmony_ci printk(KERN_ERR "JBD2: recovery pass %d ended at " 89062306a36Sopenharmony_ci "transaction %u, expected %u\n", 89162306a36Sopenharmony_ci pass, next_commit_ID, info->end_transaction); 89262306a36Sopenharmony_ci if (!success) 89362306a36Sopenharmony_ci success = -EIO; 89462306a36Sopenharmony_ci } 89562306a36Sopenharmony_ci } 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci if (jbd2_has_feature_fast_commit(journal) && pass != PASS_REVOKE) { 89862306a36Sopenharmony_ci err = fc_do_one_pass(journal, info, pass); 89962306a36Sopenharmony_ci if (err) 90062306a36Sopenharmony_ci success = err; 90162306a36Sopenharmony_ci } 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci if (block_error && success == 0) 90462306a36Sopenharmony_ci success = -EIO; 90562306a36Sopenharmony_ci return success; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci failed: 90862306a36Sopenharmony_ci return err; 90962306a36Sopenharmony_ci} 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci/* Scan a revoke record, marking all blocks mentioned as revoked. */ 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_cistatic int scan_revoke_records(journal_t *journal, struct buffer_head *bh, 91462306a36Sopenharmony_ci tid_t sequence, struct recovery_info *info) 91562306a36Sopenharmony_ci{ 91662306a36Sopenharmony_ci jbd2_journal_revoke_header_t *header; 91762306a36Sopenharmony_ci int offset, max; 91862306a36Sopenharmony_ci unsigned csum_size = 0; 91962306a36Sopenharmony_ci __u32 rcount; 92062306a36Sopenharmony_ci int record_len = 4; 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci header = (jbd2_journal_revoke_header_t *) bh->b_data; 92362306a36Sopenharmony_ci offset = sizeof(jbd2_journal_revoke_header_t); 92462306a36Sopenharmony_ci rcount = be32_to_cpu(header->r_count); 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci if (jbd2_journal_has_csum_v2or3(journal)) 92762306a36Sopenharmony_ci csum_size = sizeof(struct jbd2_journal_block_tail); 92862306a36Sopenharmony_ci if (rcount > journal->j_blocksize - csum_size) 92962306a36Sopenharmony_ci return -EINVAL; 93062306a36Sopenharmony_ci max = rcount; 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci if (jbd2_has_feature_64bit(journal)) 93362306a36Sopenharmony_ci record_len = 8; 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci while (offset + record_len <= max) { 93662306a36Sopenharmony_ci unsigned long long blocknr; 93762306a36Sopenharmony_ci int err; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci if (record_len == 4) 94062306a36Sopenharmony_ci blocknr = be32_to_cpu(* ((__be32 *) (bh->b_data+offset))); 94162306a36Sopenharmony_ci else 94262306a36Sopenharmony_ci blocknr = be64_to_cpu(* ((__be64 *) (bh->b_data+offset))); 94362306a36Sopenharmony_ci offset += record_len; 94462306a36Sopenharmony_ci err = jbd2_journal_set_revoke(journal, blocknr, sequence); 94562306a36Sopenharmony_ci if (err) 94662306a36Sopenharmony_ci return err; 94762306a36Sopenharmony_ci ++info->nr_revokes; 94862306a36Sopenharmony_ci } 94962306a36Sopenharmony_ci return 0; 95062306a36Sopenharmony_ci} 951