13b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o/* 2e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * linux/fs/jbd/recovery.c 3e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * 43b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Written by Stephen C. Tweedie <sct@redhat.com>, 1999 53b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * 60e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * Copyright 1999-2000 Red Hat Software --- All Rights Reserved 73b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * 83b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * This file is part of the Linux kernel and is made available under 93b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * the terms of the GNU General Public License, version 2, or at your 103b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * option, any later version, incorporated herein by reference. 113b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * 123b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Journal recovery routines for the generic filesystem journaling code; 13e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * part of the ext2fs journaling system. 143b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o */ 153b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 163b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#ifndef __KERNEL__ 170e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o#include "jfs_user.h" 183b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#else 193de085dd4109e6a7049dd6b85abf0313167cab5bTheodore Ts'o#include <linux/time.h> 203b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#include <linux/fs.h> 218cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o#include <linux/jbd.h> 223b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#include <linux/errno.h> 238cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o#include <linux/slab.h> 240e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o#endif 250e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 260e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o/* 270e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * Maintain information about the progress of the recovery job, so that 28e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * the different passes can carry information between them. 290e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o */ 30e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'ostruct recovery_info 310e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o{ 32e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o tid_t start_transaction; 330e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o tid_t end_transaction; 34e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 350e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o int nr_replays; 360e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o int nr_revokes; 370e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o int nr_revoke_hits; 380e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o}; 393b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 400e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'oenum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY}; 418cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'ostatic int do_one_pass(journal_t *journal, 428cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o struct recovery_info *info, enum passtype pass); 438cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'ostatic int scan_revoke_records(journal_t *, struct buffer_head *, 448cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o tid_t, struct recovery_info *); 450e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 460e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o#ifdef __KERNEL__ 473b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 483b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o/* Release readahead buffers after use */ 49e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'ostatic void journal_brelse_array(struct buffer_head *b[], int n) 503b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 513b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o while (--n >= 0) 523b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o brelse (b[n]); 533b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 543b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 553b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 563b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o/* 573b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * When reading from the journal, we are going through the block device 583b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * layer directly and so there is no readahead being done for us. We 593b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * need to implement any readahead ourselves if we want it to happen at 603b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * all. Recovery is basically one long sequential read, so make sure we 613b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * do the IO in reasonably large chunks. 623b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * 633b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * This is not so critical that we need to be enormously clever about 643b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * the readahead size, though. 128K is a purely arbitrary, good-enough 653b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * fixed value. 663b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o */ 673b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 681f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o#define MAXBUF 8 693b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'ostatic int do_readahead(journal_t *journal, unsigned int start) 703b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 713b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int err; 728cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o unsigned int max, nbufs, next; 73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long long blocknr; 743b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct buffer_head *bh; 75e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 763b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct buffer_head * bufs[MAXBUF]; 77e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 783b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* Do up to 128K of readahead */ 793b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o max = start + (128 * 1024 / journal->j_blocksize); 803b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (max > journal->j_maxlen) 813b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o max = journal->j_maxlen; 823b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 833b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* Do the readahead itself. We'll submit MAXBUF buffer_heads at 843b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * a time to the block device IO layer. */ 85e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 863b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o nbufs = 0; 87e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 883b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o for (next = start; next < max; next++) { 898cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o err = journal_bmap(journal, next, &blocknr); 908cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 918cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o if (err) { 928cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o printk (KERN_ERR "JBD: bad block at offset %u\n", 933b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o next); 943b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o goto failed; 953b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 968cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 973de085dd4109e6a7049dd6b85abf0313167cab5bTheodore Ts'o bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); 983b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!bh) { 993b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o err = -ENOMEM; 1003b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o goto failed; 1013b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 1023b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1033b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!buffer_uptodate(bh) && !buffer_locked(bh)) { 1043b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o bufs[nbufs++] = bh; 1053b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (nbufs == MAXBUF) { 1063b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ll_rw_block(READ, nbufs, bufs); 1078cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o journal_brelse_array(bufs, nbufs); 1083b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o nbufs = 0; 1093b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 1103b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } else 1113b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o brelse(bh); 1123b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 1133b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1143b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (nbufs) 1153b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o ll_rw_block(READ, nbufs, bufs); 1163b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o err = 0; 1178cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 118e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'ofailed: 119e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o if (nbufs) 1208cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o journal_brelse_array(bufs, nbufs); 1213b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return err; 1223b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 1230e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 1240e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o#endif /* __KERNEL__ */ 1250e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 1263b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1273b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o/* 1283b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Read a block from the journal 1293b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o */ 1303b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 131e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'ostatic int jread(struct buffer_head **bhp, journal_t *journal, 1323b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o unsigned int offset) 1333b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 1348cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o int err; 135e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long long blocknr; 1363b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct buffer_head *bh; 1373b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1383b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o *bhp = NULL; 1393b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 140e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o if (offset >= journal->j_maxlen) { 141e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o printk(KERN_ERR "JBD: corrupted journal superblock\n"); 142e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o return -EIO; 143e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o } 144e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 1458cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o err = journal_bmap(journal, offset, &blocknr); 1468cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 1478cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o if (err) { 1488cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o printk (KERN_ERR "JBD: bad block at offset %u\n", 1493b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o offset); 1508cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o return err; 1513b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 1528cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 1533de085dd4109e6a7049dd6b85abf0313167cab5bTheodore Ts'o bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); 1543b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!bh) 1553b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return -ENOMEM; 1568cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 1573b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!buffer_uptodate(bh)) { 1583b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* If this is a brand new buffer, start readahead. 1593b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o Otherwise, we assume we are already reading it. */ 1603b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!buffer_req(bh)) 1613b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o do_readahead(journal, offset); 1623b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o wait_on_buffer(bh); 1633b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 1648cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 1653b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!buffer_uptodate(bh)) { 1668cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o printk (KERN_ERR "JBD: Failed to read block at offset %u\n", 1673b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o offset); 1683b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o brelse(bh); 1693b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return -EIO; 1703b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 1718cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 1723b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o *bhp = bh; 1733b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return 0; 1743b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 1753b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1763b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 1773b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o/* 1783b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Count the number of in-use tags in a journal descriptor block. 1793b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o */ 1803b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 181185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'ostatic int count_tags(journal_t *journal, struct buffer_head *bh) 1823b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 1833b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o char * tagp; 1843b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o journal_block_tag_t * tag; 185185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o int nr = 0, size = journal->j_blocksize; 186185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o int tag_bytes = journal_tag_bytes(journal); 1878cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 1883b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o tagp = &bh->b_data[sizeof(journal_header_t)]; 1898cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 190185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o while ((tagp - bh->b_data + tag_bytes) <= size) { 1913b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o tag = (journal_block_tag_t *) tagp; 1928cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 1933b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o nr++; 194185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o tagp += tag_bytes; 195e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o if (!(tag->t_flags & cpu_to_be32(JFS_FLAG_SAME_UUID))) 1963b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o tagp += 16; 1973b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 198e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o if (tag->t_flags & cpu_to_be32(JFS_FLAG_LAST_TAG)) 1993b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o break; 2003b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 2018cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 2023b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return nr; 2033b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 2043b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2053b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2063b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o/* Make sure we wrap around the log correctly! */ 2073b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o#define wrap(journal, var) \ 2083b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'odo { \ 2093b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (var >= (journal)->j_last) \ 2103b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o var -= ((journal)->j_last - (journal)->j_first); \ 2113b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} while (0) 2123b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 2133de085dd4109e6a7049dd6b85abf0313167cab5bTheodore Ts'o/** 214e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * journal_recover - recovers a on-disk journal 2153de085dd4109e6a7049dd6b85abf0313167cab5bTheodore Ts'o * @journal: the journal to recover 2163b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * 2173b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * The primary function for recovering the log contents when mounting a 218e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * journaled device. 219e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * 2200e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * Recovery is done in three passes. In the first pass, we look for the 2210e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * end of the log. In the second, we assemble the list of revoke 2220e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * blocks. In the third and final pass, we replay any un-revoked blocks 223e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * in the log. 2243b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o */ 2253b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'oint journal_recover(journal_t *journal) 2263b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o{ 2270e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o int err; 2280e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o journal_superblock_t * sb; 2290e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 23053ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o struct recovery_info info; 231e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 2321f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o memset(&info, 0, sizeof(info)); 2330e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o sb = journal->j_superblock; 234e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 235e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o /* 2360e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * The journal superblock's s_start field (the current log head) 2370e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * is always zero if, and only if, the journal was cleanly 238e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * unmounted. 2390e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o */ 2400e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 2410e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (!sb->s_start) { 2428cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o jbd_debug(1, "No recovery required, last transaction %d\n", 243e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o be32_to_cpu(sb->s_sequence)); 244e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o journal->j_transaction_sequence = be32_to_cpu(sb->s_sequence) + 1; 2450e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o return 0; 2460e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o } 247e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 2480e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o err = do_one_pass(journal, &info, PASS_SCAN); 2490e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (!err) 2500e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o err = do_one_pass(journal, &info, PASS_REVOKE); 2510e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (!err) 2520e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o err = do_one_pass(journal, &info, PASS_REPLAY); 2530e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 254e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o jbd_debug(1, "JBD: recovery, exit status %d, " 2550e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o "recovered transactions %u to %u\n", 2560e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o err, info.start_transaction, info.end_transaction); 257e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o jbd_debug(1, "JBD: Replayed %d and revoked %d/%d blocks\n", 2580e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o info.nr_replays, info.nr_revoke_hits, info.nr_revokes); 2590e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 2600e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o /* Restart the log at the next transaction ID, thus invalidating 2610e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * any existing commit records in the log. */ 2620e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o journal->j_transaction_sequence = ++info.end_transaction; 263e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 2640e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o journal_clear_revoke(journal); 2653de085dd4109e6a7049dd6b85abf0313167cab5bTheodore Ts'o sync_blockdev(journal->j_fs_dev); 2660e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o return err; 2670e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o} 2680e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 2693de085dd4109e6a7049dd6b85abf0313167cab5bTheodore Ts'o/** 270e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * journal_skip_recovery - Start journal and wipe exiting records 2713de085dd4109e6a7049dd6b85abf0313167cab5bTheodore Ts'o * @journal: journal to startup 2721f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o * 2731f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o * Locate any valid recovery information from the journal and set up the 2741f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o * journal structures in memory to ignore it (presumably because the 275e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * caller has evidence that it is out of date). 2763de085dd4109e6a7049dd6b85abf0313167cab5bTheodore Ts'o * This function does'nt appear to be exorted.. 2771f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o * 2781f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o * We perform one pass over the journal to allow us to tell the user how 2791f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o * much recovery information is being erased, and to let us initialise 280e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * the journal transaction sequence numbers to the next unused ID. 2811f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o */ 2821f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'oint journal_skip_recovery(journal_t *journal) 2831f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o{ 2841f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o int err; 2851f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o struct recovery_info info; 286e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 2878cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o memset (&info, 0, sizeof(info)); 288e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 2891f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o err = do_one_pass(journal, &info, PASS_SCAN); 2901f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o 2911f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o if (err) { 2928cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o printk(KERN_ERR "JBD: error %d scanning journal\n", err); 2931f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o ++journal->j_transaction_sequence; 2941f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o } else { 2958cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o#ifdef CONFIG_JBD_DEBUG 296e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall journal_superblock_t *sb = journal->j_superblock; 297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 298e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence); 2998cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o#endif 300e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o jbd_debug(1, 3018cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o "JBD: ignoring %d transaction%s from the journal.\n", 3021f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o dropped, (dropped == 1) ? "" : "s"); 3031f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o journal->j_transaction_sequence = ++info.end_transaction; 3041f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o } 3051f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o 3061f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o journal->j_tail = 0; 3071f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o return err; 3081f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o} 3091f73503816829b0362957798fbb8cd355337dc6aTheodore Ts'o 310185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'ostatic inline unsigned long long read_tag_block(int tag_bytes, journal_block_tag_t *tag) 311185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o{ 312185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o unsigned long long block = be32_to_cpu(tag->t_blocknr); 313185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o if (tag_bytes > JBD_TAG_SIZE32) 314185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o block |= (__u64)be32_to_cpu(tag->t_blocknr_high) << 32; 315185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o return block; 316185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o} 317185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o 318185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o/* 319185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * calc_chksums calculates the checksums for the blocks described in the 320185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * descriptor block. 321185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o */ 322185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'ostatic int calc_chksums(journal_t *journal, struct buffer_head *bh, 323e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long long *next_log_block, __u32 *crc32_sum) 324185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o{ 325185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o int i, num_blks, err; 326e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long long io_block; 327185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o struct buffer_head *obh; 328185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o 329185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o num_blks = count_tags(journal, bh); 330185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o /* Calculate checksum of the descriptor block. */ 331185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o *crc32_sum = crc32_be(*crc32_sum, (void *)bh->b_data, bh->b_size); 332185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o 333185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o for (i = 0; i < num_blks; i++) { 334185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o io_block = (*next_log_block)++; 335185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o wrap(journal, *next_log_block); 336185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o err = jread(&obh, journal, io_block); 337185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o if (err) { 338185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o printk(KERN_ERR "JBD: IO error %d recovering block " 339e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "%llu in log\n", err, io_block); 340185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o return 1; 341185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o } else { 342185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o *crc32_sum = crc32_be(*crc32_sum, (void *)obh->b_data, 343185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o obh->b_size); 344185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o } 345185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o brelse(obh); 346185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o } 347185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o return 0; 348185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o} 349185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o 3508cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'ostatic int do_one_pass(journal_t *journal, 3518cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o struct recovery_info *info, enum passtype pass) 3520e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o{ 3533b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o unsigned int first_commit_ID, next_commit_ID; 354e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long long next_log_block; 3553b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o int err, success = 0; 3560e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o journal_superblock_t * sb; 357e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o journal_header_t * tmp; 3583b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o struct buffer_head * bh; 3590e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o unsigned int sequence; 3600e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o int blocktype; 361185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o int tag_bytes = journal_tag_bytes(journal); 362185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o __u32 crc32_sum = ~0; /* Transactional Checksums */ 363e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 364e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o /* 3653b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * First thing is to establish what we expect to find in the log 3663b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * (in terms of transaction IDs), and where (in terms of log 367e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * block offsets): query the superblock. 3683b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o */ 3693b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3700e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o sb = journal->j_superblock; 371e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o next_commit_ID = be32_to_cpu(sb->s_sequence); 372e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o next_log_block = be32_to_cpu(sb->s_start); 3733b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3743b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o first_commit_ID = next_commit_ID; 3750e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (pass == PASS_SCAN) 3760e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o info->start_transaction = first_commit_ID; 3778cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 3788cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o jbd_debug(1, "Starting recovery pass %d\n", pass); 3798cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 3803b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* 3813b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * Now we walk through the log, transaction by transaction, 3823b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * making sure that each transaction has a commit block in the 3833b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * expected place. Each complete transaction gets replayed back 384e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * into the main filesystem. 3853b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o */ 3863b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 3870e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o while (1) { 3880e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o int flags; 3890e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o char * tagp; 3900e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o journal_block_tag_t * tag; 3910e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o struct buffer_head * obh; 3920e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o struct buffer_head * nbh; 393e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 394e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o cond_resched(); 395e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 3960e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o /* If we already know where to stop the log traversal, 3970e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * check right now that we haven't gone past the end of 3980e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * the log. */ 399e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 4000e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (pass != PASS_SCAN) 4010e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (tid_geq(next_commit_ID, info->end_transaction)) 4020e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o break; 4038cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 404e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall jbd_debug(2, "Scanning for sequence ID %u at %llu/%lu\n", 4053b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o next_commit_ID, next_log_block, journal->j_last); 4063b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4070e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o /* Skip over each chunk of the transaction looking 4080e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * either the next descriptor block or the final commit 4090e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * record. */ 410e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 411e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall jbd_debug(3, "JBD: checking block %llu\n", next_log_block); 4120e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o err = jread(&bh, journal, next_log_block); 4130e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (err) 4140e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o goto failed; 4158cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 4160e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o next_log_block++; 4170e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o wrap(journal, next_log_block); 418e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 419e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o /* What kind of buffer is it? 420e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o * 4210e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * If it is a descriptor block, check that it has the 4220e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * expected sequence number. Otherwise, we're all done 4230e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * here. */ 4243b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4258cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o tmp = (journal_header_t *)bh->b_data; 426e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 427e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o if (tmp->h_magic != cpu_to_be32(JFS_MAGIC_NUMBER)) { 4283b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o brelse(bh); 4293b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o break; 4303b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 4318cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 432e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o blocktype = be32_to_cpu(tmp->h_blocktype); 433e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o sequence = be32_to_cpu(tmp->h_sequence); 434e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o jbd_debug(3, "Found magic %d, sequence %d\n", 4350e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o blocktype, sequence); 436e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 4370e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (sequence != next_commit_ID) { 4380e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o brelse(bh); 4390e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o break; 4400e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o } 441e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 4420e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o /* OK, we have a valid descriptor block which matches 4430e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * all of the sequence number checks. What are we going 4440e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * to do with it? That depends on the pass... */ 4458cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 4460e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o switch(blocktype) { 4470e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o case JFS_DESCRIPTOR_BLOCK: 4480e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o /* If it is a valid descriptor block, replay it 449185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * in pass REPLAY; if journal_checksums enabled, then 450185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * calculate checksums in PASS_SCAN, otherwise, 451185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * just skip over the blocks it describes. */ 4520e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (pass != PASS_REPLAY) { 453185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o if (pass == PASS_SCAN && 454185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o JFS_HAS_COMPAT_FEATURE(journal, 455185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o JFS_FEATURE_COMPAT_CHECKSUM) && 456185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o !info->end_transaction) { 457185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o if (calc_chksums(journal, bh, 458185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o &next_log_block, 459185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o &crc32_sum)) { 460185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o brelse(bh); 461185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o break; 462185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o } 463185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o brelse(bh); 464185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o continue; 465185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o } 466185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o next_log_block += count_tags(journal, bh); 4670e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o wrap(journal, next_log_block); 4683b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o brelse(bh); 4690e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o continue; 4703b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 4710e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 4723b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* A descriptor block: we can now write all of 4733b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * the data blocks. Yay, useful work is finally 4743b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * getting done here! */ 4753b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 4763b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o tagp = &bh->b_data[sizeof(journal_header_t)]; 477185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o while ((tagp - bh->b_data + tag_bytes) 4783b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o <= journal->j_blocksize) { 479e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long long io_block; 4808cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 4813b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o tag = (journal_block_tag_t *) tagp; 482e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o flags = be32_to_cpu(tag->t_flags); 483e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 4840e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o io_block = next_log_block++; 4853b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o wrap(journal, next_log_block); 4860e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o err = jread(&obh, journal, io_block); 4873b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (err) { 4883b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o /* Recover what we can, but 4893b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o * report failure at the end. */ 4903b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o success = err; 491e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o printk (KERN_ERR 4928cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o "JBD: IO error %d recovering " 493e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "block %llu in log\n", 4940e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o err, io_block); 4953b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } else { 496e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long long blocknr; 497e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 4983b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o J_ASSERT(obh != NULL); 499e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blocknr = read_tag_block(tag_bytes, 500e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall tag); 5010e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 5020e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o /* If the block has been 5030e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * revoked, then we're all done 5040e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * here. */ 5050e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (journal_test_revoke 506e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o (journal, blocknr, 5070e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o next_commit_ID)) { 5080e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o brelse(obh); 5090e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o ++info->nr_revoke_hits; 5100e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o goto skip_write; 5110e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o } 512e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 5130e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o /* Find a buffer for the new 5140e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * data being restored */ 515e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o nbh = __getblk(journal->j_fs_dev, 516e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o blocknr, 517e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o journal->j_blocksize); 5183b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (nbh == NULL) { 519e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o printk(KERN_ERR 5208cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o "JBD: Out of memory " 5213b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o "during recovery.\n"); 5223b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o err = -ENOMEM; 5233b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o brelse(bh); 5243b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o brelse(obh); 5253b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o goto failed; 5263b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 5273b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 5283de085dd4109e6a7049dd6b85abf0313167cab5bTheodore Ts'o lock_buffer(nbh); 5298cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o memcpy(nbh->b_data, obh->b_data, 5308cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o journal->j_blocksize); 5313b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (flags & JFS_FLAG_ESCAPE) { 532c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen journal_header_t *header; 533c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen 534c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen header = (journal_header_t *) &nbh->b_data[0]; 535c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen header->h_magic = cpu_to_be32(JFS_MAGIC_NUMBER); 5363b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 5378cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 5388cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o BUFFER_TRACE(nbh, "marking dirty"); 5393de085dd4109e6a7049dd6b85abf0313167cab5bTheodore Ts'o set_buffer_uptodate(nbh); 5408cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o mark_buffer_dirty(nbh); 5418cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o BUFFER_TRACE(nbh, "marking uptodate"); 5420e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o ++info->nr_replays; 54353ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o /* ll_rw_block(WRITE, 1, &nbh); */ 5443de085dd4109e6a7049dd6b85abf0313167cab5bTheodore Ts'o unlock_buffer(nbh); 5453b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o brelse(obh); 5463b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o brelse(nbh); 5473b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 548e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 5490e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o skip_write: 550185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o tagp += tag_bytes; 5513b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (!(flags & JFS_FLAG_SAME_UUID)) 5523b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o tagp += 16; 5533b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 5543b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o if (flags & JFS_FLAG_LAST_TAG) 5553b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o break; 5560e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o } 557e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 5580e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o brelse(bh); 5590e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o continue; 5608cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 5610e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o case JFS_COMMIT_BLOCK: 562185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o jbd_debug(3, "Commit block for #%u found\n", 563185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o next_commit_ID); 564185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o /* How to differentiate between interrupted commit 565185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * and journal corruption ? 566185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * 567185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * {nth transaction} 568185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * Checksum Verification Failed 569185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * | 570185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * ____________________ 571185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * | | 572185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * async_commit sync_commit 573185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * | | 574185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * | GO TO NEXT "Journal Corruption" 575185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * | TRANSACTION 576185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * | 577185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * {(n+1)th transanction} 578185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * | 579185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * _______|______________ 580185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * | | 581185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * Commit block found Commit block not found 582185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * | | 583185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * "Journal Corruption" | 584185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * _____________|_________ 585185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * | | 586185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * nth trans corrupt OR nth trans 587185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * and (n+1)th interrupted interrupted 588185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * before commit block 589185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * could reach the disk. 590185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * (Cannot find the difference in above 591185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * mentioned conditions. Hence assume 592185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * "Interrupted Commit".) 593185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o */ 594185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o 595185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o /* Found an expected commit block: if checksums 596185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * are present verify them in PASS_SCAN; else not 597185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * much to do other than move on to the next sequence 5980e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * number. */ 599185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o if (pass == PASS_SCAN && 600185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o JFS_HAS_COMPAT_FEATURE(journal, 601185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o JFS_FEATURE_COMPAT_CHECKSUM)) { 602185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o int chksum_err, chksum_seen; 603185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o struct commit_header *cbh = 604185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o (struct commit_header *)bh->b_data; 605185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o unsigned found_chksum = 606185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o be32_to_cpu(cbh->h_chksum[0]); 607185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o 608185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o chksum_err = chksum_seen = 0; 609185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o 610185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o jbd_debug(3, "Checksums %x %x\n", 611185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o crc32_sum, found_chksum); 612185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o if (info->end_transaction) { 613185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o journal->j_failed_commit = 614185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o info->end_transaction; 615185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o brelse(bh); 616185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o break; 617185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o } 618185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o 619185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o if (crc32_sum == found_chksum && 620185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o cbh->h_chksum_type == JBD2_CRC32_CHKSUM && 621185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o cbh->h_chksum_size == 622185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o JBD2_CRC32_CHKSUM_SIZE) 623185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o chksum_seen = 1; 624185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o else if (!(cbh->h_chksum_type == 0 && 625185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o cbh->h_chksum_size == 0 && 626185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o found_chksum == 0 && 627185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o !chksum_seen)) 628185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o /* 629185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * If fs is mounted using an old kernel and then 630185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * kernel with journal_chksum is used then we 631185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * get a situation where the journal flag has 632185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * checksum flag set but checksums are not 633185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * present i.e chksum = 0, in the individual 634185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * commit blocks. 635185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * Hence to avoid checksum failures, in this 636185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o * situation, this extra check is added. 637185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o */ 638185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o chksum_err = 1; 639185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o 640185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o if (chksum_err) { 641185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o info->end_transaction = next_commit_ID; 6422acad6b4895a0e218f9d9eece1ade23c2cf4ffc7Theodore Ts'o jbd_debug(1, "Checksum_err %x %x\n", 6432acad6b4895a0e218f9d9eece1ade23c2cf4ffc7Theodore Ts'o crc32_sum, found_chksum); 644185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o if (!JFS_HAS_INCOMPAT_FEATURE(journal, 645185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o JFS_FEATURE_INCOMPAT_ASYNC_COMMIT)){ 646185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o journal->j_failed_commit = 647185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o next_commit_ID; 648185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o brelse(bh); 649185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o break; 650185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o } 651185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o } 652185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o crc32_sum = ~0; 653185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o } 6540e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o brelse(bh); 6550e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o next_commit_ID++; 6560e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o continue; 6573b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 6580e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o case JFS_REVOKE_BLOCK: 6590e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o /* If we aren't in the REVOKE pass, then we can 6600e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * just skip over this block. */ 6610e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (pass != PASS_REVOKE) { 6620e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o brelse(bh); 6630e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o continue; 6640e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o } 6653b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 6668cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o err = scan_revoke_records(journal, bh, 6670e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o next_commit_ID, info); 6683b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o brelse(bh); 6690e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (err) 6700e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o goto failed; 6710e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o continue; 6720e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 6730e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o default: 6748cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o jbd_debug(3, "Unrecognised magic %d, end of scan.\n", 6750e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o blocktype); 6762aa362f54a9a486ffd495028b95532897551d619Theodore Ts'o brelse(bh); 6770e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o goto done; 6780e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o } 6793b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o } 6803b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 6810e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o done: 682e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o /* 6830e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * We broke out of the log scan loop: either we came to the 6840e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * known end of the log or we found an unexpected block in the 6850e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * log. If the latter happened, then we know that the "current" 6860e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * transaction marks the end of the valid log. 6870e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o */ 688e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 689185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o if (pass == PASS_SCAN) { 690185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o if (!info->end_transaction) 691185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o info->end_transaction = next_commit_ID; 692185c4aeaf23d48375e3506218305031663203d0fTheodore Ts'o } else { 6930e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o /* It's really bad news if different passes end up at 6940e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o * different places (but possible due to IO errors). */ 6950e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (info->end_transaction != next_commit_ID) { 6968cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o printk (KERN_ERR "JBD: recovery pass %d ended at " 6970e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o "transaction %u, expected %u\n", 6980e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o pass, next_commit_ID, info->end_transaction); 6990e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (!success) 7000e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o success = -EIO; 7010e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o } 7020e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o } 7030e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 7040e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o return success; 7053b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o 7060e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o failed: 7073b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o return err; 7083b5386dca8e0008e13351be5de6323576329aa58Theodore Ts'o} 7090e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 7100e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 7110e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o/* Scan a revoke record, marking all blocks mentioned as revoked. */ 7120e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o 713e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'ostatic int scan_revoke_records(journal_t *journal, struct buffer_head *bh, 7140e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o tid_t sequence, struct recovery_info *info) 7150e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o{ 7160e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o journal_revoke_header_t *header; 7170e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o int offset, max; 718e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int record_len = 4; 7198cf93332d180e6929d73cd8c855c3a83d6a6648cTheodore Ts'o 7200e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o header = (journal_revoke_header_t *) bh->b_data; 7210e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o offset = sizeof(journal_revoke_header_t); 722e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o max = be32_to_cpu(header->r_count); 723e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 724e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT)) 725e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall record_len = 8; 726e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 7270e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o while (offset < max) { 728e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long long blocknr; 7290e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o int err; 730e5ea6b14eb93671525e01ec4a6100febe541bf67Theodore Ts'o 731e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (record_len == 4) { 732e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __be32 b; 733e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memcpy(&b, bh->b_data + offset, sizeof(__be32)); 734e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blocknr = ext2fs_be32_to_cpu(b); 735e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 736e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __be64 b; 737e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memcpy(&b, bh->b_data + offset, sizeof(__be64)); 738e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blocknr = ext2fs_be64_to_cpu(b); 739e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 740e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 741e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall offset += record_len; 7420e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o err = journal_set_revoke(journal, blocknr, sequence); 7430e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o if (err) 7440e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o return err; 7450e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o ++info->nr_revokes; 7460e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o } 7470e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o return 0; 7480e8a9560d89dd9cca73037a59efa93e46abdccdaTheodore Ts'o} 749