10f3e1c7fSRyusuke Konishi /* 20f3e1c7fSRyusuke Konishi * recovery.c - NILFS recovery logic 30f3e1c7fSRyusuke Konishi * 40f3e1c7fSRyusuke Konishi * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. 50f3e1c7fSRyusuke Konishi * 60f3e1c7fSRyusuke Konishi * This program is free software; you can redistribute it and/or modify 70f3e1c7fSRyusuke Konishi * it under the terms of the GNU General Public License as published by 80f3e1c7fSRyusuke Konishi * the Free Software Foundation; either version 2 of the License, or 90f3e1c7fSRyusuke Konishi * (at your option) any later version. 100f3e1c7fSRyusuke Konishi * 110f3e1c7fSRyusuke Konishi * This program is distributed in the hope that it will be useful, 120f3e1c7fSRyusuke Konishi * but WITHOUT ANY WARRANTY; without even the implied warranty of 130f3e1c7fSRyusuke Konishi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 140f3e1c7fSRyusuke Konishi * GNU General Public License for more details. 150f3e1c7fSRyusuke Konishi * 160f3e1c7fSRyusuke Konishi * You should have received a copy of the GNU General Public License 170f3e1c7fSRyusuke Konishi * along with this program; if not, write to the Free Software 180f3e1c7fSRyusuke Konishi * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 190f3e1c7fSRyusuke Konishi * 200f3e1c7fSRyusuke Konishi * Written by Ryusuke Konishi <ryusuke@osrg.net> 210f3e1c7fSRyusuke Konishi */ 220f3e1c7fSRyusuke Konishi 230f3e1c7fSRyusuke Konishi #include <linux/buffer_head.h> 240f3e1c7fSRyusuke Konishi #include <linux/blkdev.h> 250f3e1c7fSRyusuke Konishi #include <linux/swap.h> 260f3e1c7fSRyusuke Konishi #include <linux/crc32.h> 270f3e1c7fSRyusuke Konishi #include "nilfs.h" 280f3e1c7fSRyusuke Konishi #include "segment.h" 290f3e1c7fSRyusuke Konishi #include "sufile.h" 300f3e1c7fSRyusuke Konishi #include "page.h" 310f3e1c7fSRyusuke Konishi #include "segbuf.h" 320f3e1c7fSRyusuke Konishi 330f3e1c7fSRyusuke Konishi /* 340f3e1c7fSRyusuke Konishi * Segment check result 350f3e1c7fSRyusuke Konishi */ 360f3e1c7fSRyusuke Konishi enum { 370f3e1c7fSRyusuke Konishi NILFS_SEG_VALID, 380f3e1c7fSRyusuke Konishi NILFS_SEG_NO_SUPER_ROOT, 390f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_IO, 400f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_MAGIC, 410f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_SEQ, 420f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_CHECKSUM_SEGSUM, 430f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT, 440f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_CHECKSUM_FULL, 450f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_CONSISTENCY, 460f3e1c7fSRyusuke Konishi }; 470f3e1c7fSRyusuke Konishi 480f3e1c7fSRyusuke Konishi /* work structure for recovery */ 490f3e1c7fSRyusuke Konishi struct nilfs_recovery_block { 500f3e1c7fSRyusuke Konishi ino_t ino; /* Inode number of the file that this block 510f3e1c7fSRyusuke Konishi belongs to */ 520f3e1c7fSRyusuke Konishi sector_t blocknr; /* block number */ 530f3e1c7fSRyusuke Konishi __u64 vblocknr; /* virtual block number */ 540f3e1c7fSRyusuke Konishi unsigned long blkoff; /* File offset of the data block (per block) */ 550f3e1c7fSRyusuke Konishi struct list_head list; 560f3e1c7fSRyusuke Konishi }; 570f3e1c7fSRyusuke Konishi 580f3e1c7fSRyusuke Konishi 590f3e1c7fSRyusuke Konishi static int nilfs_warn_segment_error(int err) 600f3e1c7fSRyusuke Konishi { 610f3e1c7fSRyusuke Konishi switch (err) { 620f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_IO: 630f3e1c7fSRyusuke Konishi printk(KERN_WARNING 640f3e1c7fSRyusuke Konishi "NILFS warning: I/O error on loading last segment\n"); 650f3e1c7fSRyusuke Konishi return -EIO; 660f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_MAGIC: 670f3e1c7fSRyusuke Konishi printk(KERN_WARNING 680f3e1c7fSRyusuke Konishi "NILFS warning: Segment magic number invalid\n"); 690f3e1c7fSRyusuke Konishi break; 700f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_SEQ: 710f3e1c7fSRyusuke Konishi printk(KERN_WARNING 720f3e1c7fSRyusuke Konishi "NILFS warning: Sequence number mismatch\n"); 730f3e1c7fSRyusuke Konishi break; 740f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_CHECKSUM_SEGSUM: 750f3e1c7fSRyusuke Konishi printk(KERN_WARNING 760f3e1c7fSRyusuke Konishi "NILFS warning: Checksum error in segment summary\n"); 770f3e1c7fSRyusuke Konishi break; 780f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT: 790f3e1c7fSRyusuke Konishi printk(KERN_WARNING 800f3e1c7fSRyusuke Konishi "NILFS warning: Checksum error in super root\n"); 810f3e1c7fSRyusuke Konishi break; 820f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_CHECKSUM_FULL: 830f3e1c7fSRyusuke Konishi printk(KERN_WARNING 840f3e1c7fSRyusuke Konishi "NILFS warning: Checksum error in segment payload\n"); 850f3e1c7fSRyusuke Konishi break; 860f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_CONSISTENCY: 870f3e1c7fSRyusuke Konishi printk(KERN_WARNING 880f3e1c7fSRyusuke Konishi "NILFS warning: Inconsistent segment\n"); 890f3e1c7fSRyusuke Konishi break; 900f3e1c7fSRyusuke Konishi case NILFS_SEG_NO_SUPER_ROOT: 910f3e1c7fSRyusuke Konishi printk(KERN_WARNING 920f3e1c7fSRyusuke Konishi "NILFS warning: No super root in the last segment\n"); 930f3e1c7fSRyusuke Konishi break; 940f3e1c7fSRyusuke Konishi } 950f3e1c7fSRyusuke Konishi return -EINVAL; 960f3e1c7fSRyusuke Konishi } 970f3e1c7fSRyusuke Konishi 980f3e1c7fSRyusuke Konishi static void store_segsum_info(struct nilfs_segsum_info *ssi, 990f3e1c7fSRyusuke Konishi struct nilfs_segment_summary *sum, 1000f3e1c7fSRyusuke Konishi unsigned int blocksize) 1010f3e1c7fSRyusuke Konishi { 1020f3e1c7fSRyusuke Konishi ssi->flags = le16_to_cpu(sum->ss_flags); 1030f3e1c7fSRyusuke Konishi ssi->seg_seq = le64_to_cpu(sum->ss_seq); 1040f3e1c7fSRyusuke Konishi ssi->ctime = le64_to_cpu(sum->ss_create); 1050f3e1c7fSRyusuke Konishi ssi->next = le64_to_cpu(sum->ss_next); 1060f3e1c7fSRyusuke Konishi ssi->nblocks = le32_to_cpu(sum->ss_nblocks); 1070f3e1c7fSRyusuke Konishi ssi->nfinfo = le32_to_cpu(sum->ss_nfinfo); 1080f3e1c7fSRyusuke Konishi ssi->sumbytes = le32_to_cpu(sum->ss_sumbytes); 1090f3e1c7fSRyusuke Konishi 1100f3e1c7fSRyusuke Konishi ssi->nsumblk = DIV_ROUND_UP(ssi->sumbytes, blocksize); 1110f3e1c7fSRyusuke Konishi ssi->nfileblk = ssi->nblocks - ssi->nsumblk - !!NILFS_SEG_HAS_SR(ssi); 1120f3e1c7fSRyusuke Konishi } 1130f3e1c7fSRyusuke Konishi 1140f3e1c7fSRyusuke Konishi /** 1150f3e1c7fSRyusuke Konishi * calc_crc_cont - check CRC of blocks continuously 1160f3e1c7fSRyusuke Konishi * @sbi: nilfs_sb_info 1170f3e1c7fSRyusuke Konishi * @bhs: buffer head of start block 1180f3e1c7fSRyusuke Konishi * @sum: place to store result 1190f3e1c7fSRyusuke Konishi * @offset: offset bytes in the first block 1200f3e1c7fSRyusuke Konishi * @check_bytes: number of bytes to be checked 1210f3e1c7fSRyusuke Konishi * @start: DBN of start block 1220f3e1c7fSRyusuke Konishi * @nblock: number of blocks to be checked 1230f3e1c7fSRyusuke Konishi */ 1240f3e1c7fSRyusuke Konishi static int calc_crc_cont(struct nilfs_sb_info *sbi, struct buffer_head *bhs, 1250f3e1c7fSRyusuke Konishi u32 *sum, unsigned long offset, u64 check_bytes, 1260f3e1c7fSRyusuke Konishi sector_t start, unsigned long nblock) 1270f3e1c7fSRyusuke Konishi { 1280f3e1c7fSRyusuke Konishi unsigned long blocksize = sbi->s_super->s_blocksize; 1290f3e1c7fSRyusuke Konishi unsigned long size; 1300f3e1c7fSRyusuke Konishi u32 crc; 1310f3e1c7fSRyusuke Konishi 1320f3e1c7fSRyusuke Konishi BUG_ON(offset >= blocksize); 1330f3e1c7fSRyusuke Konishi check_bytes -= offset; 1340f3e1c7fSRyusuke Konishi size = min_t(u64, check_bytes, blocksize - offset); 1350f3e1c7fSRyusuke Konishi crc = crc32_le(sbi->s_nilfs->ns_crc_seed, 1360f3e1c7fSRyusuke Konishi (unsigned char *)bhs->b_data + offset, size); 1370f3e1c7fSRyusuke Konishi if (--nblock > 0) { 1380f3e1c7fSRyusuke Konishi do { 1390f3e1c7fSRyusuke Konishi struct buffer_head *bh 1400f3e1c7fSRyusuke Konishi = sb_bread(sbi->s_super, ++start); 1410f3e1c7fSRyusuke Konishi if (!bh) 1420f3e1c7fSRyusuke Konishi return -EIO; 1430f3e1c7fSRyusuke Konishi check_bytes -= size; 1440f3e1c7fSRyusuke Konishi size = min_t(u64, check_bytes, blocksize); 1450f3e1c7fSRyusuke Konishi crc = crc32_le(crc, bh->b_data, size); 1460f3e1c7fSRyusuke Konishi brelse(bh); 1470f3e1c7fSRyusuke Konishi } while (--nblock > 0); 1480f3e1c7fSRyusuke Konishi } 1490f3e1c7fSRyusuke Konishi *sum = crc; 1500f3e1c7fSRyusuke Konishi return 0; 1510f3e1c7fSRyusuke Konishi } 1520f3e1c7fSRyusuke Konishi 1530f3e1c7fSRyusuke Konishi /** 1540f3e1c7fSRyusuke Konishi * nilfs_read_super_root_block - read super root block 1550f3e1c7fSRyusuke Konishi * @sb: super_block 1560f3e1c7fSRyusuke Konishi * @sr_block: disk block number of the super root block 1570f3e1c7fSRyusuke Konishi * @pbh: address of a buffer_head pointer to return super root buffer 1580f3e1c7fSRyusuke Konishi * @check: CRC check flag 1590f3e1c7fSRyusuke Konishi */ 1600f3e1c7fSRyusuke Konishi int nilfs_read_super_root_block(struct super_block *sb, sector_t sr_block, 1610f3e1c7fSRyusuke Konishi struct buffer_head **pbh, int check) 1620f3e1c7fSRyusuke Konishi { 1630f3e1c7fSRyusuke Konishi struct buffer_head *bh_sr; 1640f3e1c7fSRyusuke Konishi struct nilfs_super_root *sr; 1650f3e1c7fSRyusuke Konishi u32 crc; 1660f3e1c7fSRyusuke Konishi int ret; 1670f3e1c7fSRyusuke Konishi 1680f3e1c7fSRyusuke Konishi *pbh = NULL; 1690f3e1c7fSRyusuke Konishi bh_sr = sb_bread(sb, sr_block); 1700f3e1c7fSRyusuke Konishi if (unlikely(!bh_sr)) { 1710f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_IO; 1720f3e1c7fSRyusuke Konishi goto failed; 1730f3e1c7fSRyusuke Konishi } 1740f3e1c7fSRyusuke Konishi 1750f3e1c7fSRyusuke Konishi sr = (struct nilfs_super_root *)bh_sr->b_data; 1760f3e1c7fSRyusuke Konishi if (check) { 1770f3e1c7fSRyusuke Konishi unsigned bytes = le16_to_cpu(sr->sr_bytes); 1780f3e1c7fSRyusuke Konishi 1790f3e1c7fSRyusuke Konishi if (bytes == 0 || bytes > sb->s_blocksize) { 1800f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT; 1810f3e1c7fSRyusuke Konishi goto failed_bh; 1820f3e1c7fSRyusuke Konishi } 1830f3e1c7fSRyusuke Konishi if (calc_crc_cont(NILFS_SB(sb), bh_sr, &crc, 1840f3e1c7fSRyusuke Konishi sizeof(sr->sr_sum), bytes, sr_block, 1)) { 1850f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_IO; 1860f3e1c7fSRyusuke Konishi goto failed_bh; 1870f3e1c7fSRyusuke Konishi } 1880f3e1c7fSRyusuke Konishi if (crc != le32_to_cpu(sr->sr_sum)) { 1890f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT; 1900f3e1c7fSRyusuke Konishi goto failed_bh; 1910f3e1c7fSRyusuke Konishi } 1920f3e1c7fSRyusuke Konishi } 1930f3e1c7fSRyusuke Konishi *pbh = bh_sr; 1940f3e1c7fSRyusuke Konishi return 0; 1950f3e1c7fSRyusuke Konishi 1960f3e1c7fSRyusuke Konishi failed_bh: 1970f3e1c7fSRyusuke Konishi brelse(bh_sr); 1980f3e1c7fSRyusuke Konishi 1990f3e1c7fSRyusuke Konishi failed: 2000f3e1c7fSRyusuke Konishi return nilfs_warn_segment_error(ret); 2010f3e1c7fSRyusuke Konishi } 2020f3e1c7fSRyusuke Konishi 2030f3e1c7fSRyusuke Konishi /** 2040f3e1c7fSRyusuke Konishi * load_segment_summary - read segment summary of the specified partial segment 2050f3e1c7fSRyusuke Konishi * @sbi: nilfs_sb_info 2060f3e1c7fSRyusuke Konishi * @pseg_start: start disk block number of partial segment 2070f3e1c7fSRyusuke Konishi * @seg_seq: sequence number requested 2080f3e1c7fSRyusuke Konishi * @ssi: pointer to nilfs_segsum_info struct to store information 2090f3e1c7fSRyusuke Konishi * @full_check: full check flag 2100f3e1c7fSRyusuke Konishi * (0: only checks segment summary CRC, 1: data CRC) 2110f3e1c7fSRyusuke Konishi */ 2120f3e1c7fSRyusuke Konishi static int 2130f3e1c7fSRyusuke Konishi load_segment_summary(struct nilfs_sb_info *sbi, sector_t pseg_start, 2140f3e1c7fSRyusuke Konishi u64 seg_seq, struct nilfs_segsum_info *ssi, 2150f3e1c7fSRyusuke Konishi int full_check) 2160f3e1c7fSRyusuke Konishi { 2170f3e1c7fSRyusuke Konishi struct buffer_head *bh_sum; 2180f3e1c7fSRyusuke Konishi struct nilfs_segment_summary *sum; 2190f3e1c7fSRyusuke Konishi unsigned long offset, nblock; 2200f3e1c7fSRyusuke Konishi u64 check_bytes; 2210f3e1c7fSRyusuke Konishi u32 crc, crc_sum; 2220f3e1c7fSRyusuke Konishi int ret = NILFS_SEG_FAIL_IO; 2230f3e1c7fSRyusuke Konishi 2240f3e1c7fSRyusuke Konishi bh_sum = sb_bread(sbi->s_super, pseg_start); 2250f3e1c7fSRyusuke Konishi if (!bh_sum) 2260f3e1c7fSRyusuke Konishi goto out; 2270f3e1c7fSRyusuke Konishi 2280f3e1c7fSRyusuke Konishi sum = (struct nilfs_segment_summary *)bh_sum->b_data; 2290f3e1c7fSRyusuke Konishi 2300f3e1c7fSRyusuke Konishi /* Check consistency of segment summary */ 2310f3e1c7fSRyusuke Konishi if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC) { 2320f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_MAGIC; 2330f3e1c7fSRyusuke Konishi goto failed; 2340f3e1c7fSRyusuke Konishi } 2350f3e1c7fSRyusuke Konishi store_segsum_info(ssi, sum, sbi->s_super->s_blocksize); 2360f3e1c7fSRyusuke Konishi if (seg_seq != ssi->seg_seq) { 2370f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_SEQ; 2380f3e1c7fSRyusuke Konishi goto failed; 2390f3e1c7fSRyusuke Konishi } 2400f3e1c7fSRyusuke Konishi if (full_check) { 2410f3e1c7fSRyusuke Konishi offset = sizeof(sum->ss_datasum); 2420f3e1c7fSRyusuke Konishi check_bytes = 2430f3e1c7fSRyusuke Konishi ((u64)ssi->nblocks << sbi->s_super->s_blocksize_bits); 2440f3e1c7fSRyusuke Konishi nblock = ssi->nblocks; 2450f3e1c7fSRyusuke Konishi crc_sum = le32_to_cpu(sum->ss_datasum); 2460f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CHECKSUM_FULL; 2470f3e1c7fSRyusuke Konishi } else { /* only checks segment summary */ 2480f3e1c7fSRyusuke Konishi offset = sizeof(sum->ss_datasum) + sizeof(sum->ss_sumsum); 2490f3e1c7fSRyusuke Konishi check_bytes = ssi->sumbytes; 2500f3e1c7fSRyusuke Konishi nblock = ssi->nsumblk; 2510f3e1c7fSRyusuke Konishi crc_sum = le32_to_cpu(sum->ss_sumsum); 2520f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CHECKSUM_SEGSUM; 2530f3e1c7fSRyusuke Konishi } 2540f3e1c7fSRyusuke Konishi 2550f3e1c7fSRyusuke Konishi if (unlikely(nblock == 0 || 2560f3e1c7fSRyusuke Konishi nblock > sbi->s_nilfs->ns_blocks_per_segment)) { 2570f3e1c7fSRyusuke Konishi /* This limits the number of blocks read in the CRC check */ 2580f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CONSISTENCY; 2590f3e1c7fSRyusuke Konishi goto failed; 2600f3e1c7fSRyusuke Konishi } 2610f3e1c7fSRyusuke Konishi if (calc_crc_cont(sbi, bh_sum, &crc, offset, check_bytes, 2620f3e1c7fSRyusuke Konishi pseg_start, nblock)) { 2630f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_IO; 2640f3e1c7fSRyusuke Konishi goto failed; 2650f3e1c7fSRyusuke Konishi } 2660f3e1c7fSRyusuke Konishi if (crc == crc_sum) 2670f3e1c7fSRyusuke Konishi ret = 0; 2680f3e1c7fSRyusuke Konishi failed: 2690f3e1c7fSRyusuke Konishi brelse(bh_sum); 2700f3e1c7fSRyusuke Konishi out: 2710f3e1c7fSRyusuke Konishi return ret; 2720f3e1c7fSRyusuke Konishi } 2730f3e1c7fSRyusuke Konishi 2740f3e1c7fSRyusuke Konishi static void *segsum_get(struct super_block *sb, struct buffer_head **pbh, 2750f3e1c7fSRyusuke Konishi unsigned int *offset, unsigned int bytes) 2760f3e1c7fSRyusuke Konishi { 2770f3e1c7fSRyusuke Konishi void *ptr; 2780f3e1c7fSRyusuke Konishi sector_t blocknr; 2790f3e1c7fSRyusuke Konishi 2800f3e1c7fSRyusuke Konishi BUG_ON((*pbh)->b_size < *offset); 2810f3e1c7fSRyusuke Konishi if (bytes > (*pbh)->b_size - *offset) { 2820f3e1c7fSRyusuke Konishi blocknr = (*pbh)->b_blocknr; 2830f3e1c7fSRyusuke Konishi brelse(*pbh); 2840f3e1c7fSRyusuke Konishi *pbh = sb_bread(sb, blocknr + 1); 2850f3e1c7fSRyusuke Konishi if (unlikely(!*pbh)) 2860f3e1c7fSRyusuke Konishi return NULL; 2870f3e1c7fSRyusuke Konishi *offset = 0; 2880f3e1c7fSRyusuke Konishi } 2890f3e1c7fSRyusuke Konishi ptr = (*pbh)->b_data + *offset; 2900f3e1c7fSRyusuke Konishi *offset += bytes; 2910f3e1c7fSRyusuke Konishi return ptr; 2920f3e1c7fSRyusuke Konishi } 2930f3e1c7fSRyusuke Konishi 2940f3e1c7fSRyusuke Konishi static void segsum_skip(struct super_block *sb, struct buffer_head **pbh, 2950f3e1c7fSRyusuke Konishi unsigned int *offset, unsigned int bytes, 2960f3e1c7fSRyusuke Konishi unsigned long count) 2970f3e1c7fSRyusuke Konishi { 2980f3e1c7fSRyusuke Konishi unsigned int rest_item_in_current_block 2990f3e1c7fSRyusuke Konishi = ((*pbh)->b_size - *offset) / bytes; 3000f3e1c7fSRyusuke Konishi 3010f3e1c7fSRyusuke Konishi if (count <= rest_item_in_current_block) { 3020f3e1c7fSRyusuke Konishi *offset += bytes * count; 3030f3e1c7fSRyusuke Konishi } else { 3040f3e1c7fSRyusuke Konishi sector_t blocknr = (*pbh)->b_blocknr; 3050f3e1c7fSRyusuke Konishi unsigned int nitem_per_block = (*pbh)->b_size / bytes; 3060f3e1c7fSRyusuke Konishi unsigned int bcnt; 3070f3e1c7fSRyusuke Konishi 3080f3e1c7fSRyusuke Konishi count -= rest_item_in_current_block; 3090f3e1c7fSRyusuke Konishi bcnt = DIV_ROUND_UP(count, nitem_per_block); 3100f3e1c7fSRyusuke Konishi *offset = bytes * (count - (bcnt - 1) * nitem_per_block); 3110f3e1c7fSRyusuke Konishi 3120f3e1c7fSRyusuke Konishi brelse(*pbh); 3130f3e1c7fSRyusuke Konishi *pbh = sb_bread(sb, blocknr + bcnt); 3140f3e1c7fSRyusuke Konishi } 3150f3e1c7fSRyusuke Konishi } 3160f3e1c7fSRyusuke Konishi 3170f3e1c7fSRyusuke Konishi static int 3180f3e1c7fSRyusuke Konishi collect_blocks_from_segsum(struct nilfs_sb_info *sbi, sector_t sum_blocknr, 3190f3e1c7fSRyusuke Konishi struct nilfs_segsum_info *ssi, 3200f3e1c7fSRyusuke Konishi struct list_head *head) 3210f3e1c7fSRyusuke Konishi { 3220f3e1c7fSRyusuke Konishi struct buffer_head *bh; 3230f3e1c7fSRyusuke Konishi unsigned int offset; 3240f3e1c7fSRyusuke Konishi unsigned long nfinfo = ssi->nfinfo; 3250f3e1c7fSRyusuke Konishi sector_t blocknr = sum_blocknr + ssi->nsumblk; 3260f3e1c7fSRyusuke Konishi ino_t ino; 3270f3e1c7fSRyusuke Konishi int err = -EIO; 3280f3e1c7fSRyusuke Konishi 3290f3e1c7fSRyusuke Konishi if (!nfinfo) 3300f3e1c7fSRyusuke Konishi return 0; 3310f3e1c7fSRyusuke Konishi 3320f3e1c7fSRyusuke Konishi bh = sb_bread(sbi->s_super, sum_blocknr); 3330f3e1c7fSRyusuke Konishi if (unlikely(!bh)) 3340f3e1c7fSRyusuke Konishi goto out; 3350f3e1c7fSRyusuke Konishi 3360f3e1c7fSRyusuke Konishi offset = le16_to_cpu( 3370f3e1c7fSRyusuke Konishi ((struct nilfs_segment_summary *)bh->b_data)->ss_bytes); 3380f3e1c7fSRyusuke Konishi for (;;) { 3390f3e1c7fSRyusuke Konishi unsigned long nblocks, ndatablk, nnodeblk; 3400f3e1c7fSRyusuke Konishi struct nilfs_finfo *finfo; 3410f3e1c7fSRyusuke Konishi 3420f3e1c7fSRyusuke Konishi finfo = segsum_get(sbi->s_super, &bh, &offset, sizeof(*finfo)); 3430f3e1c7fSRyusuke Konishi if (unlikely(!finfo)) 3440f3e1c7fSRyusuke Konishi goto out; 3450f3e1c7fSRyusuke Konishi 3460f3e1c7fSRyusuke Konishi ino = le64_to_cpu(finfo->fi_ino); 3470f3e1c7fSRyusuke Konishi nblocks = le32_to_cpu(finfo->fi_nblocks); 3480f3e1c7fSRyusuke Konishi ndatablk = le32_to_cpu(finfo->fi_ndatablk); 3490f3e1c7fSRyusuke Konishi nnodeblk = nblocks - ndatablk; 3500f3e1c7fSRyusuke Konishi 3510f3e1c7fSRyusuke Konishi while (ndatablk-- > 0) { 3520f3e1c7fSRyusuke Konishi struct nilfs_recovery_block *rb; 3530f3e1c7fSRyusuke Konishi struct nilfs_binfo_v *binfo; 3540f3e1c7fSRyusuke Konishi 3550f3e1c7fSRyusuke Konishi binfo = segsum_get(sbi->s_super, &bh, &offset, 3560f3e1c7fSRyusuke Konishi sizeof(*binfo)); 3570f3e1c7fSRyusuke Konishi if (unlikely(!binfo)) 3580f3e1c7fSRyusuke Konishi goto out; 3590f3e1c7fSRyusuke Konishi 3600f3e1c7fSRyusuke Konishi rb = kmalloc(sizeof(*rb), GFP_NOFS); 3610f3e1c7fSRyusuke Konishi if (unlikely(!rb)) { 3620f3e1c7fSRyusuke Konishi err = -ENOMEM; 3630f3e1c7fSRyusuke Konishi goto out; 3640f3e1c7fSRyusuke Konishi } 3650f3e1c7fSRyusuke Konishi rb->ino = ino; 3660f3e1c7fSRyusuke Konishi rb->blocknr = blocknr++; 3670f3e1c7fSRyusuke Konishi rb->vblocknr = le64_to_cpu(binfo->bi_vblocknr); 3680f3e1c7fSRyusuke Konishi rb->blkoff = le64_to_cpu(binfo->bi_blkoff); 3690f3e1c7fSRyusuke Konishi /* INIT_LIST_HEAD(&rb->list); */ 3700f3e1c7fSRyusuke Konishi list_add_tail(&rb->list, head); 3710f3e1c7fSRyusuke Konishi } 3720f3e1c7fSRyusuke Konishi if (--nfinfo == 0) 3730f3e1c7fSRyusuke Konishi break; 3740f3e1c7fSRyusuke Konishi blocknr += nnodeblk; /* always 0 for the data sync segments */ 3750f3e1c7fSRyusuke Konishi segsum_skip(sbi->s_super, &bh, &offset, sizeof(__le64), 3760f3e1c7fSRyusuke Konishi nnodeblk); 3770f3e1c7fSRyusuke Konishi if (unlikely(!bh)) 3780f3e1c7fSRyusuke Konishi goto out; 3790f3e1c7fSRyusuke Konishi } 3800f3e1c7fSRyusuke Konishi err = 0; 3810f3e1c7fSRyusuke Konishi out: 3820f3e1c7fSRyusuke Konishi brelse(bh); /* brelse(NULL) is just ignored */ 3830f3e1c7fSRyusuke Konishi return err; 3840f3e1c7fSRyusuke Konishi } 3850f3e1c7fSRyusuke Konishi 3860f3e1c7fSRyusuke Konishi static void dispose_recovery_list(struct list_head *head) 3870f3e1c7fSRyusuke Konishi { 3880f3e1c7fSRyusuke Konishi while (!list_empty(head)) { 3890f3e1c7fSRyusuke Konishi struct nilfs_recovery_block *rb 3900f3e1c7fSRyusuke Konishi = list_entry(head->next, 3910f3e1c7fSRyusuke Konishi struct nilfs_recovery_block, list); 3920f3e1c7fSRyusuke Konishi list_del(&rb->list); 3930f3e1c7fSRyusuke Konishi kfree(rb); 3940f3e1c7fSRyusuke Konishi } 3950f3e1c7fSRyusuke Konishi } 3960f3e1c7fSRyusuke Konishi 397654137ddSRyusuke Konishi struct nilfs_segment_entry { 398654137ddSRyusuke Konishi struct list_head list; 399654137ddSRyusuke Konishi __u64 segnum; 400654137ddSRyusuke Konishi }; 401654137ddSRyusuke Konishi 402654137ddSRyusuke Konishi static int nilfs_segment_list_add(struct list_head *head, __u64 segnum) 403654137ddSRyusuke Konishi { 404654137ddSRyusuke Konishi struct nilfs_segment_entry *ent = kmalloc(sizeof(*ent), GFP_NOFS); 405654137ddSRyusuke Konishi 406654137ddSRyusuke Konishi if (unlikely(!ent)) 407654137ddSRyusuke Konishi return -ENOMEM; 408654137ddSRyusuke Konishi 409654137ddSRyusuke Konishi ent->segnum = segnum; 410654137ddSRyusuke Konishi INIT_LIST_HEAD(&ent->list); 411654137ddSRyusuke Konishi list_add_tail(&ent->list, head); 412654137ddSRyusuke Konishi return 0; 413654137ddSRyusuke Konishi } 414654137ddSRyusuke Konishi 4150f3e1c7fSRyusuke Konishi void nilfs_dispose_segment_list(struct list_head *head) 4160f3e1c7fSRyusuke Konishi { 4170f3e1c7fSRyusuke Konishi while (!list_empty(head)) { 4180f3e1c7fSRyusuke Konishi struct nilfs_segment_entry *ent 4190f3e1c7fSRyusuke Konishi = list_entry(head->next, 4200f3e1c7fSRyusuke Konishi struct nilfs_segment_entry, list); 4210f3e1c7fSRyusuke Konishi list_del(&ent->list); 422654137ddSRyusuke Konishi kfree(ent); 4230f3e1c7fSRyusuke Konishi } 4240f3e1c7fSRyusuke Konishi } 4250f3e1c7fSRyusuke Konishi 4260f3e1c7fSRyusuke Konishi static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, 42785c2a74fSRyusuke Konishi struct nilfs_sb_info *sbi, 4280f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 4290f3e1c7fSRyusuke Konishi { 4300f3e1c7fSRyusuke Konishi struct list_head *head = &ri->ri_used_segments; 4310f3e1c7fSRyusuke Konishi struct nilfs_segment_entry *ent, *n; 4320f3e1c7fSRyusuke Konishi struct inode *sufile = nilfs->ns_sufile; 4330f3e1c7fSRyusuke Konishi __u64 segnum[4]; 4340f3e1c7fSRyusuke Konishi int err; 4350f3e1c7fSRyusuke Konishi int i; 4360f3e1c7fSRyusuke Konishi 4370f3e1c7fSRyusuke Konishi segnum[0] = nilfs->ns_segnum; 4380f3e1c7fSRyusuke Konishi segnum[1] = nilfs->ns_nextnum; 4390f3e1c7fSRyusuke Konishi segnum[2] = ri->ri_segnum; 4400f3e1c7fSRyusuke Konishi segnum[3] = ri->ri_nextnum; 4410f3e1c7fSRyusuke Konishi 44285c2a74fSRyusuke Konishi nilfs_attach_writer(nilfs, sbi); 4430f3e1c7fSRyusuke Konishi /* 4440f3e1c7fSRyusuke Konishi * Releasing the next segment of the latest super root. 4450f3e1c7fSRyusuke Konishi * The next segment is invalidated by this recovery. 4460f3e1c7fSRyusuke Konishi */ 4470f3e1c7fSRyusuke Konishi err = nilfs_sufile_free(sufile, segnum[1]); 4480f3e1c7fSRyusuke Konishi if (unlikely(err)) 4490f3e1c7fSRyusuke Konishi goto failed; 4500f3e1c7fSRyusuke Konishi 4510f3e1c7fSRyusuke Konishi for (i = 1; i < 4; i++) { 452654137ddSRyusuke Konishi err = nilfs_segment_list_add(head, segnum[i]); 453654137ddSRyusuke Konishi if (unlikely(err)) 4540f3e1c7fSRyusuke Konishi goto failed; 4550f3e1c7fSRyusuke Konishi } 4560f3e1c7fSRyusuke Konishi 4570f3e1c7fSRyusuke Konishi /* 4580f3e1c7fSRyusuke Konishi * Collecting segments written after the latest super root. 4592c2e52fcSRyusuke Konishi * These are marked dirty to avoid being reallocated in the next write. 4600f3e1c7fSRyusuke Konishi */ 4610f3e1c7fSRyusuke Konishi list_for_each_entry_safe(ent, n, head, list) { 462c85399c2SRyusuke Konishi if (ent->segnum != segnum[0]) { 463c85399c2SRyusuke Konishi err = nilfs_sufile_scrap(sufile, ent->segnum); 4640f3e1c7fSRyusuke Konishi if (unlikely(err)) 4650f3e1c7fSRyusuke Konishi goto failed; 4662c2e52fcSRyusuke Konishi } 4670f3e1c7fSRyusuke Konishi list_del(&ent->list); 468654137ddSRyusuke Konishi kfree(ent); 4690f3e1c7fSRyusuke Konishi } 4700f3e1c7fSRyusuke Konishi 4710f3e1c7fSRyusuke Konishi /* Allocate new segments for recovery */ 4720f3e1c7fSRyusuke Konishi err = nilfs_sufile_alloc(sufile, &segnum[0]); 4730f3e1c7fSRyusuke Konishi if (unlikely(err)) 4740f3e1c7fSRyusuke Konishi goto failed; 4750f3e1c7fSRyusuke Konishi 4760f3e1c7fSRyusuke Konishi nilfs->ns_pseg_offset = 0; 4770f3e1c7fSRyusuke Konishi nilfs->ns_seg_seq = ri->ri_seq + 2; 4780f3e1c7fSRyusuke Konishi nilfs->ns_nextnum = nilfs->ns_segnum = segnum[0]; 4790f3e1c7fSRyusuke Konishi 4800f3e1c7fSRyusuke Konishi failed: 4810f3e1c7fSRyusuke Konishi /* No need to recover sufile because it will be destroyed on error */ 48285c2a74fSRyusuke Konishi nilfs_detach_writer(nilfs, sbi); 4830f3e1c7fSRyusuke Konishi return err; 4840f3e1c7fSRyusuke Konishi } 4850f3e1c7fSRyusuke Konishi 4860f3e1c7fSRyusuke Konishi static int nilfs_recovery_copy_block(struct nilfs_sb_info *sbi, 4870f3e1c7fSRyusuke Konishi struct nilfs_recovery_block *rb, 4880f3e1c7fSRyusuke Konishi struct page *page) 4890f3e1c7fSRyusuke Konishi { 4900f3e1c7fSRyusuke Konishi struct buffer_head *bh_org; 4910f3e1c7fSRyusuke Konishi void *kaddr; 4920f3e1c7fSRyusuke Konishi 4930f3e1c7fSRyusuke Konishi bh_org = sb_bread(sbi->s_super, rb->blocknr); 4940f3e1c7fSRyusuke Konishi if (unlikely(!bh_org)) 4950f3e1c7fSRyusuke Konishi return -EIO; 4960f3e1c7fSRyusuke Konishi 4970f3e1c7fSRyusuke Konishi kaddr = kmap_atomic(page, KM_USER0); 4980f3e1c7fSRyusuke Konishi memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size); 4990f3e1c7fSRyusuke Konishi kunmap_atomic(kaddr, KM_USER0); 5000f3e1c7fSRyusuke Konishi brelse(bh_org); 5010f3e1c7fSRyusuke Konishi return 0; 5020f3e1c7fSRyusuke Konishi } 5030f3e1c7fSRyusuke Konishi 5040f3e1c7fSRyusuke Konishi static int recover_dsync_blocks(struct nilfs_sb_info *sbi, 5050f3e1c7fSRyusuke Konishi struct list_head *head, 5060f3e1c7fSRyusuke Konishi unsigned long *nr_salvaged_blocks) 5070f3e1c7fSRyusuke Konishi { 5080f3e1c7fSRyusuke Konishi struct inode *inode; 5090f3e1c7fSRyusuke Konishi struct nilfs_recovery_block *rb, *n; 5100f3e1c7fSRyusuke Konishi unsigned blocksize = sbi->s_super->s_blocksize; 5110f3e1c7fSRyusuke Konishi struct page *page; 5120f3e1c7fSRyusuke Konishi loff_t pos; 5130f3e1c7fSRyusuke Konishi int err = 0, err2 = 0; 5140f3e1c7fSRyusuke Konishi 5150f3e1c7fSRyusuke Konishi list_for_each_entry_safe(rb, n, head, list) { 5160f3e1c7fSRyusuke Konishi inode = nilfs_iget(sbi->s_super, rb->ino); 5170f3e1c7fSRyusuke Konishi if (IS_ERR(inode)) { 5180f3e1c7fSRyusuke Konishi err = PTR_ERR(inode); 5190f3e1c7fSRyusuke Konishi inode = NULL; 5200f3e1c7fSRyusuke Konishi goto failed_inode; 5210f3e1c7fSRyusuke Konishi } 5220f3e1c7fSRyusuke Konishi 5230f3e1c7fSRyusuke Konishi pos = rb->blkoff << inode->i_blkbits; 5240f3e1c7fSRyusuke Konishi page = NULL; 5250f3e1c7fSRyusuke Konishi err = block_write_begin(NULL, inode->i_mapping, pos, blocksize, 5260f3e1c7fSRyusuke Konishi 0, &page, NULL, nilfs_get_block); 5270f3e1c7fSRyusuke Konishi if (unlikely(err)) 5280f3e1c7fSRyusuke Konishi goto failed_inode; 5290f3e1c7fSRyusuke Konishi 5300f3e1c7fSRyusuke Konishi err = nilfs_recovery_copy_block(sbi, rb, page); 5310f3e1c7fSRyusuke Konishi if (unlikely(err)) 5320f3e1c7fSRyusuke Konishi goto failed_page; 5330f3e1c7fSRyusuke Konishi 5340f3e1c7fSRyusuke Konishi err = nilfs_set_file_dirty(sbi, inode, 1); 5350f3e1c7fSRyusuke Konishi if (unlikely(err)) 5360f3e1c7fSRyusuke Konishi goto failed_page; 5370f3e1c7fSRyusuke Konishi 5380f3e1c7fSRyusuke Konishi block_write_end(NULL, inode->i_mapping, pos, blocksize, 5390f3e1c7fSRyusuke Konishi blocksize, page, NULL); 5400f3e1c7fSRyusuke Konishi 5410f3e1c7fSRyusuke Konishi unlock_page(page); 5420f3e1c7fSRyusuke Konishi page_cache_release(page); 5430f3e1c7fSRyusuke Konishi 5440f3e1c7fSRyusuke Konishi (*nr_salvaged_blocks)++; 5450f3e1c7fSRyusuke Konishi goto next; 5460f3e1c7fSRyusuke Konishi 5470f3e1c7fSRyusuke Konishi failed_page: 5480f3e1c7fSRyusuke Konishi unlock_page(page); 5490f3e1c7fSRyusuke Konishi page_cache_release(page); 5500f3e1c7fSRyusuke Konishi 5510f3e1c7fSRyusuke Konishi failed_inode: 5520f3e1c7fSRyusuke Konishi printk(KERN_WARNING 5530f3e1c7fSRyusuke Konishi "NILFS warning: error recovering data block " 5540f3e1c7fSRyusuke Konishi "(err=%d, ino=%lu, block-offset=%llu)\n", 555b5696e5eSHeiko Carstens err, (unsigned long)rb->ino, 556b5696e5eSHeiko Carstens (unsigned long long)rb->blkoff); 5570f3e1c7fSRyusuke Konishi if (!err2) 5580f3e1c7fSRyusuke Konishi err2 = err; 5590f3e1c7fSRyusuke Konishi next: 5600f3e1c7fSRyusuke Konishi iput(inode); /* iput(NULL) is just ignored */ 5610f3e1c7fSRyusuke Konishi list_del_init(&rb->list); 5620f3e1c7fSRyusuke Konishi kfree(rb); 5630f3e1c7fSRyusuke Konishi } 5640f3e1c7fSRyusuke Konishi return err2; 5650f3e1c7fSRyusuke Konishi } 5660f3e1c7fSRyusuke Konishi 5670f3e1c7fSRyusuke Konishi /** 5680f3e1c7fSRyusuke Konishi * nilfs_do_roll_forward - salvage logical segments newer than the latest 5690f3e1c7fSRyusuke Konishi * checkpoint 5700f3e1c7fSRyusuke Konishi * @sbi: nilfs_sb_info 5710f3e1c7fSRyusuke Konishi * @nilfs: the_nilfs 5720f3e1c7fSRyusuke Konishi * @ri: pointer to a nilfs_recovery_info 5730f3e1c7fSRyusuke Konishi */ 5740f3e1c7fSRyusuke Konishi static int nilfs_do_roll_forward(struct the_nilfs *nilfs, 5750f3e1c7fSRyusuke Konishi struct nilfs_sb_info *sbi, 5760f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 5770f3e1c7fSRyusuke Konishi { 5780f3e1c7fSRyusuke Konishi struct nilfs_segsum_info ssi; 5790f3e1c7fSRyusuke Konishi sector_t pseg_start; 5800f3e1c7fSRyusuke Konishi sector_t seg_start, seg_end; /* Starting/ending DBN of full segment */ 5810f3e1c7fSRyusuke Konishi unsigned long nsalvaged_blocks = 0; 5820f3e1c7fSRyusuke Konishi u64 seg_seq; 5830f3e1c7fSRyusuke Konishi __u64 segnum, nextnum = 0; 5840f3e1c7fSRyusuke Konishi int empty_seg = 0; 5850f3e1c7fSRyusuke Konishi int err = 0, ret; 5860f3e1c7fSRyusuke Konishi LIST_HEAD(dsync_blocks); /* list of data blocks to be recovered */ 5870f3e1c7fSRyusuke Konishi enum { 5880f3e1c7fSRyusuke Konishi RF_INIT_ST, 5890f3e1c7fSRyusuke Konishi RF_DSYNC_ST, /* scanning data-sync segments */ 5900f3e1c7fSRyusuke Konishi }; 5910f3e1c7fSRyusuke Konishi int state = RF_INIT_ST; 5920f3e1c7fSRyusuke Konishi 5930f3e1c7fSRyusuke Konishi nilfs_attach_writer(nilfs, sbi); 5940f3e1c7fSRyusuke Konishi pseg_start = ri->ri_lsegs_start; 5950f3e1c7fSRyusuke Konishi seg_seq = ri->ri_lsegs_start_seq; 5960f3e1c7fSRyusuke Konishi segnum = nilfs_get_segnum_of_block(nilfs, pseg_start); 5970f3e1c7fSRyusuke Konishi nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); 5980f3e1c7fSRyusuke Konishi 5990f3e1c7fSRyusuke Konishi while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) { 6000f3e1c7fSRyusuke Konishi 6010f3e1c7fSRyusuke Konishi ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi, 1); 6020f3e1c7fSRyusuke Konishi if (ret) { 6030f3e1c7fSRyusuke Konishi if (ret == NILFS_SEG_FAIL_IO) { 6040f3e1c7fSRyusuke Konishi err = -EIO; 6050f3e1c7fSRyusuke Konishi goto failed; 6060f3e1c7fSRyusuke Konishi } 6070f3e1c7fSRyusuke Konishi goto strayed; 6080f3e1c7fSRyusuke Konishi } 6090f3e1c7fSRyusuke Konishi if (unlikely(NILFS_SEG_HAS_SR(&ssi))) 6100f3e1c7fSRyusuke Konishi goto confused; 6110f3e1c7fSRyusuke Konishi 6120f3e1c7fSRyusuke Konishi /* Found a valid partial segment; do recovery actions */ 6130f3e1c7fSRyusuke Konishi nextnum = nilfs_get_segnum_of_block(nilfs, ssi.next); 6140f3e1c7fSRyusuke Konishi empty_seg = 0; 6150f3e1c7fSRyusuke Konishi nilfs->ns_ctime = ssi.ctime; 6160f3e1c7fSRyusuke Konishi if (!(ssi.flags & NILFS_SS_GC)) 6170f3e1c7fSRyusuke Konishi nilfs->ns_nongc_ctime = ssi.ctime; 6180f3e1c7fSRyusuke Konishi 6190f3e1c7fSRyusuke Konishi switch (state) { 6200f3e1c7fSRyusuke Konishi case RF_INIT_ST: 6210f3e1c7fSRyusuke Konishi if (!NILFS_SEG_LOGBGN(&ssi) || !NILFS_SEG_DSYNC(&ssi)) 6220f3e1c7fSRyusuke Konishi goto try_next_pseg; 6230f3e1c7fSRyusuke Konishi state = RF_DSYNC_ST; 6240f3e1c7fSRyusuke Konishi /* Fall through */ 6250f3e1c7fSRyusuke Konishi case RF_DSYNC_ST: 6260f3e1c7fSRyusuke Konishi if (!NILFS_SEG_DSYNC(&ssi)) 6270f3e1c7fSRyusuke Konishi goto confused; 6280f3e1c7fSRyusuke Konishi 6290f3e1c7fSRyusuke Konishi err = collect_blocks_from_segsum( 6300f3e1c7fSRyusuke Konishi sbi, pseg_start, &ssi, &dsync_blocks); 6310f3e1c7fSRyusuke Konishi if (unlikely(err)) 6320f3e1c7fSRyusuke Konishi goto failed; 6330f3e1c7fSRyusuke Konishi if (NILFS_SEG_LOGEND(&ssi)) { 6340f3e1c7fSRyusuke Konishi err = recover_dsync_blocks( 6350f3e1c7fSRyusuke Konishi sbi, &dsync_blocks, &nsalvaged_blocks); 6360f3e1c7fSRyusuke Konishi if (unlikely(err)) 6370f3e1c7fSRyusuke Konishi goto failed; 6380f3e1c7fSRyusuke Konishi state = RF_INIT_ST; 6390f3e1c7fSRyusuke Konishi } 6400f3e1c7fSRyusuke Konishi break; /* Fall through to try_next_pseg */ 6410f3e1c7fSRyusuke Konishi } 6420f3e1c7fSRyusuke Konishi 6430f3e1c7fSRyusuke Konishi try_next_pseg: 6440f3e1c7fSRyusuke Konishi if (pseg_start == ri->ri_lsegs_end) 6450f3e1c7fSRyusuke Konishi break; 6460f3e1c7fSRyusuke Konishi pseg_start += ssi.nblocks; 6470f3e1c7fSRyusuke Konishi if (pseg_start < seg_end) 6480f3e1c7fSRyusuke Konishi continue; 6490f3e1c7fSRyusuke Konishi goto feed_segment; 6500f3e1c7fSRyusuke Konishi 6510f3e1c7fSRyusuke Konishi strayed: 6520f3e1c7fSRyusuke Konishi if (pseg_start == ri->ri_lsegs_end) 6530f3e1c7fSRyusuke Konishi break; 6540f3e1c7fSRyusuke Konishi 6550f3e1c7fSRyusuke Konishi feed_segment: 6560f3e1c7fSRyusuke Konishi /* Looking to the next full segment */ 6570f3e1c7fSRyusuke Konishi if (empty_seg++) 6580f3e1c7fSRyusuke Konishi break; 6590f3e1c7fSRyusuke Konishi seg_seq++; 6600f3e1c7fSRyusuke Konishi segnum = nextnum; 6610f3e1c7fSRyusuke Konishi nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); 6620f3e1c7fSRyusuke Konishi pseg_start = seg_start; 6630f3e1c7fSRyusuke Konishi } 6640f3e1c7fSRyusuke Konishi 6650f3e1c7fSRyusuke Konishi if (nsalvaged_blocks) { 6660f3e1c7fSRyusuke Konishi printk(KERN_INFO "NILFS (device %s): salvaged %lu blocks\n", 6670f3e1c7fSRyusuke Konishi sbi->s_super->s_id, nsalvaged_blocks); 6680f3e1c7fSRyusuke Konishi ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; 6690f3e1c7fSRyusuke Konishi } 6700f3e1c7fSRyusuke Konishi out: 6710f3e1c7fSRyusuke Konishi dispose_recovery_list(&dsync_blocks); 6720f3e1c7fSRyusuke Konishi nilfs_detach_writer(sbi->s_nilfs, sbi); 6730f3e1c7fSRyusuke Konishi return err; 6740f3e1c7fSRyusuke Konishi 6750f3e1c7fSRyusuke Konishi confused: 6760f3e1c7fSRyusuke Konishi err = -EINVAL; 6770f3e1c7fSRyusuke Konishi failed: 6780f3e1c7fSRyusuke Konishi printk(KERN_ERR 6790f3e1c7fSRyusuke Konishi "NILFS (device %s): Error roll-forwarding " 6800f3e1c7fSRyusuke Konishi "(err=%d, pseg block=%llu). ", 6810f3e1c7fSRyusuke Konishi sbi->s_super->s_id, err, (unsigned long long)pseg_start); 6820f3e1c7fSRyusuke Konishi goto out; 6830f3e1c7fSRyusuke Konishi } 6840f3e1c7fSRyusuke Konishi 6850f3e1c7fSRyusuke Konishi static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, 6860f3e1c7fSRyusuke Konishi struct nilfs_sb_info *sbi, 6870f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 6880f3e1c7fSRyusuke Konishi { 6890f3e1c7fSRyusuke Konishi struct buffer_head *bh; 6900f3e1c7fSRyusuke Konishi int err; 6910f3e1c7fSRyusuke Konishi 6920f3e1c7fSRyusuke Konishi if (nilfs_get_segnum_of_block(nilfs, ri->ri_lsegs_start) != 6930f3e1c7fSRyusuke Konishi nilfs_get_segnum_of_block(nilfs, ri->ri_super_root)) 6940f3e1c7fSRyusuke Konishi return; 6950f3e1c7fSRyusuke Konishi 6960f3e1c7fSRyusuke Konishi bh = sb_getblk(sbi->s_super, ri->ri_lsegs_start); 6970f3e1c7fSRyusuke Konishi BUG_ON(!bh); 6980f3e1c7fSRyusuke Konishi memset(bh->b_data, 0, bh->b_size); 6990f3e1c7fSRyusuke Konishi set_buffer_dirty(bh); 7000f3e1c7fSRyusuke Konishi err = sync_dirty_buffer(bh); 7010f3e1c7fSRyusuke Konishi if (unlikely(err)) 7020f3e1c7fSRyusuke Konishi printk(KERN_WARNING 7030f3e1c7fSRyusuke Konishi "NILFS warning: buffer sync write failed during " 7040f3e1c7fSRyusuke Konishi "post-cleaning of recovery.\n"); 7050f3e1c7fSRyusuke Konishi brelse(bh); 7060f3e1c7fSRyusuke Konishi } 7070f3e1c7fSRyusuke Konishi 7080f3e1c7fSRyusuke Konishi /** 7090f3e1c7fSRyusuke Konishi * nilfs_recover_logical_segments - salvage logical segments written after 7100f3e1c7fSRyusuke Konishi * the latest super root 7110f3e1c7fSRyusuke Konishi * @nilfs: the_nilfs 7120f3e1c7fSRyusuke Konishi * @sbi: nilfs_sb_info 7130f3e1c7fSRyusuke Konishi * @ri: pointer to a nilfs_recovery_info struct to store search results. 7140f3e1c7fSRyusuke Konishi * 7150f3e1c7fSRyusuke Konishi * Return Value: On success, 0 is returned. On error, one of the following 7160f3e1c7fSRyusuke Konishi * negative error code is returned. 7170f3e1c7fSRyusuke Konishi * 7180f3e1c7fSRyusuke Konishi * %-EINVAL - Inconsistent filesystem state. 7190f3e1c7fSRyusuke Konishi * 7200f3e1c7fSRyusuke Konishi * %-EIO - I/O error 7210f3e1c7fSRyusuke Konishi * 7220f3e1c7fSRyusuke Konishi * %-ENOSPC - No space left on device (only in a panic state). 7230f3e1c7fSRyusuke Konishi * 7240f3e1c7fSRyusuke Konishi * %-ERESTARTSYS - Interrupted. 7250f3e1c7fSRyusuke Konishi * 7260f3e1c7fSRyusuke Konishi * %-ENOMEM - Insufficient memory available. 7270f3e1c7fSRyusuke Konishi */ 7280f3e1c7fSRyusuke Konishi int nilfs_recover_logical_segments(struct the_nilfs *nilfs, 7290f3e1c7fSRyusuke Konishi struct nilfs_sb_info *sbi, 7300f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 7310f3e1c7fSRyusuke Konishi { 7320f3e1c7fSRyusuke Konishi int err; 7330f3e1c7fSRyusuke Konishi 7340f3e1c7fSRyusuke Konishi if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0) 7350f3e1c7fSRyusuke Konishi return 0; 7360f3e1c7fSRyusuke Konishi 7370f3e1c7fSRyusuke Konishi err = nilfs_attach_checkpoint(sbi, ri->ri_cno); 7380f3e1c7fSRyusuke Konishi if (unlikely(err)) { 7390f3e1c7fSRyusuke Konishi printk(KERN_ERR 7400f3e1c7fSRyusuke Konishi "NILFS: error loading the latest checkpoint.\n"); 7410f3e1c7fSRyusuke Konishi return err; 7420f3e1c7fSRyusuke Konishi } 7430f3e1c7fSRyusuke Konishi 7440f3e1c7fSRyusuke Konishi err = nilfs_do_roll_forward(nilfs, sbi, ri); 7450f3e1c7fSRyusuke Konishi if (unlikely(err)) 7460f3e1c7fSRyusuke Konishi goto failed; 7470f3e1c7fSRyusuke Konishi 7480f3e1c7fSRyusuke Konishi if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) { 74985c2a74fSRyusuke Konishi err = nilfs_prepare_segment_for_recovery(nilfs, sbi, ri); 7500f3e1c7fSRyusuke Konishi if (unlikely(err)) { 7510f3e1c7fSRyusuke Konishi printk(KERN_ERR "NILFS: Error preparing segments for " 7520f3e1c7fSRyusuke Konishi "recovery.\n"); 7530f3e1c7fSRyusuke Konishi goto failed; 7540f3e1c7fSRyusuke Konishi } 7550f3e1c7fSRyusuke Konishi 756cece5520SRyusuke Konishi err = nilfs_attach_segment_constructor(sbi); 7570f3e1c7fSRyusuke Konishi if (unlikely(err)) 7580f3e1c7fSRyusuke Konishi goto failed; 7590f3e1c7fSRyusuke Konishi 7600f3e1c7fSRyusuke Konishi set_nilfs_discontinued(nilfs); 7610f3e1c7fSRyusuke Konishi err = nilfs_construct_segment(sbi->s_super); 7620f3e1c7fSRyusuke Konishi nilfs_detach_segment_constructor(sbi); 7630f3e1c7fSRyusuke Konishi 7640f3e1c7fSRyusuke Konishi if (unlikely(err)) { 7650f3e1c7fSRyusuke Konishi printk(KERN_ERR "NILFS: Oops! recovery failed. " 7660f3e1c7fSRyusuke Konishi "(err=%d)\n", err); 7670f3e1c7fSRyusuke Konishi goto failed; 7680f3e1c7fSRyusuke Konishi } 7690f3e1c7fSRyusuke Konishi 7700f3e1c7fSRyusuke Konishi nilfs_finish_roll_forward(nilfs, sbi, ri); 7710f3e1c7fSRyusuke Konishi } 7720f3e1c7fSRyusuke Konishi 7730f3e1c7fSRyusuke Konishi nilfs_detach_checkpoint(sbi); 7740f3e1c7fSRyusuke Konishi return 0; 7750f3e1c7fSRyusuke Konishi 7760f3e1c7fSRyusuke Konishi failed: 7770f3e1c7fSRyusuke Konishi nilfs_detach_checkpoint(sbi); 7780f3e1c7fSRyusuke Konishi nilfs_mdt_clear(nilfs->ns_cpfile); 7790f3e1c7fSRyusuke Konishi nilfs_mdt_clear(nilfs->ns_sufile); 7800f3e1c7fSRyusuke Konishi nilfs_mdt_clear(nilfs->ns_dat); 7810f3e1c7fSRyusuke Konishi return err; 7820f3e1c7fSRyusuke Konishi } 7830f3e1c7fSRyusuke Konishi 7840f3e1c7fSRyusuke Konishi /** 7850f3e1c7fSRyusuke Konishi * nilfs_search_super_root - search the latest valid super root 7860f3e1c7fSRyusuke Konishi * @nilfs: the_nilfs 7870f3e1c7fSRyusuke Konishi * @sbi: nilfs_sb_info 7880f3e1c7fSRyusuke Konishi * @ri: pointer to a nilfs_recovery_info struct to store search results. 7890f3e1c7fSRyusuke Konishi * 7900f3e1c7fSRyusuke Konishi * nilfs_search_super_root() looks for the latest super-root from a partial 7910f3e1c7fSRyusuke Konishi * segment pointed by the superblock. It sets up struct the_nilfs through 7920f3e1c7fSRyusuke Konishi * this search. It fills nilfs_recovery_info (ri) required for recovery. 7930f3e1c7fSRyusuke Konishi * 7940f3e1c7fSRyusuke Konishi * Return Value: On success, 0 is returned. On error, one of the following 7950f3e1c7fSRyusuke Konishi * negative error code is returned. 7960f3e1c7fSRyusuke Konishi * 7970f3e1c7fSRyusuke Konishi * %-EINVAL - No valid segment found 7980f3e1c7fSRyusuke Konishi * 7990f3e1c7fSRyusuke Konishi * %-EIO - I/O error 8000f3e1c7fSRyusuke Konishi */ 8010f3e1c7fSRyusuke Konishi int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, 8020f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 8030f3e1c7fSRyusuke Konishi { 8040f3e1c7fSRyusuke Konishi struct nilfs_segsum_info ssi; 8050f3e1c7fSRyusuke Konishi sector_t pseg_start, pseg_end, sr_pseg_start = 0; 8060f3e1c7fSRyusuke Konishi sector_t seg_start, seg_end; /* range of full segment (block number) */ 8070f3e1c7fSRyusuke Konishi u64 seg_seq; 8080f3e1c7fSRyusuke Konishi __u64 segnum, nextnum = 0; 8090f3e1c7fSRyusuke Konishi __u64 cno; 8100f3e1c7fSRyusuke Konishi LIST_HEAD(segments); 8110f3e1c7fSRyusuke Konishi int empty_seg = 0, scan_newer = 0; 8120f3e1c7fSRyusuke Konishi int ret; 8130f3e1c7fSRyusuke Konishi 8140f3e1c7fSRyusuke Konishi pseg_start = nilfs->ns_last_pseg; 8150f3e1c7fSRyusuke Konishi seg_seq = nilfs->ns_last_seq; 8160f3e1c7fSRyusuke Konishi cno = nilfs->ns_last_cno; 8170f3e1c7fSRyusuke Konishi segnum = nilfs_get_segnum_of_block(nilfs, pseg_start); 8180f3e1c7fSRyusuke Konishi 8190f3e1c7fSRyusuke Konishi /* Calculate range of segment */ 8200f3e1c7fSRyusuke Konishi nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); 8210f3e1c7fSRyusuke Konishi 8220f3e1c7fSRyusuke Konishi for (;;) { 8230f3e1c7fSRyusuke Konishi /* Load segment summary */ 8240f3e1c7fSRyusuke Konishi ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi, 1); 8250f3e1c7fSRyusuke Konishi if (ret) { 8260f3e1c7fSRyusuke Konishi if (ret == NILFS_SEG_FAIL_IO) 8270f3e1c7fSRyusuke Konishi goto failed; 8280f3e1c7fSRyusuke Konishi goto strayed; 8290f3e1c7fSRyusuke Konishi } 8300f3e1c7fSRyusuke Konishi pseg_end = pseg_start + ssi.nblocks - 1; 8310f3e1c7fSRyusuke Konishi if (unlikely(pseg_end > seg_end)) { 8320f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CONSISTENCY; 8330f3e1c7fSRyusuke Konishi goto strayed; 8340f3e1c7fSRyusuke Konishi } 8350f3e1c7fSRyusuke Konishi 8360f3e1c7fSRyusuke Konishi /* A valid partial segment */ 8370f3e1c7fSRyusuke Konishi ri->ri_pseg_start = pseg_start; 8380f3e1c7fSRyusuke Konishi ri->ri_seq = seg_seq; 8390f3e1c7fSRyusuke Konishi ri->ri_segnum = segnum; 8400f3e1c7fSRyusuke Konishi nextnum = nilfs_get_segnum_of_block(nilfs, ssi.next); 8410f3e1c7fSRyusuke Konishi ri->ri_nextnum = nextnum; 8420f3e1c7fSRyusuke Konishi empty_seg = 0; 8430f3e1c7fSRyusuke Konishi 8440f3e1c7fSRyusuke Konishi if (!NILFS_SEG_HAS_SR(&ssi)) { 8450f3e1c7fSRyusuke Konishi if (!scan_newer) { 8460f3e1c7fSRyusuke Konishi /* This will never happen because a superblock 8470f3e1c7fSRyusuke Konishi (last_segment) always points to a pseg 8480f3e1c7fSRyusuke Konishi having a super root. */ 8490f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CONSISTENCY; 8500f3e1c7fSRyusuke Konishi goto failed; 8510f3e1c7fSRyusuke Konishi } 8520f3e1c7fSRyusuke Konishi if (!ri->ri_lsegs_start && NILFS_SEG_LOGBGN(&ssi)) { 8530f3e1c7fSRyusuke Konishi ri->ri_lsegs_start = pseg_start; 8540f3e1c7fSRyusuke Konishi ri->ri_lsegs_start_seq = seg_seq; 8550f3e1c7fSRyusuke Konishi } 8560f3e1c7fSRyusuke Konishi if (NILFS_SEG_LOGEND(&ssi)) 8570f3e1c7fSRyusuke Konishi ri->ri_lsegs_end = pseg_start; 8580f3e1c7fSRyusuke Konishi goto try_next_pseg; 8590f3e1c7fSRyusuke Konishi } 8600f3e1c7fSRyusuke Konishi 8610f3e1c7fSRyusuke Konishi /* A valid super root was found. */ 8620f3e1c7fSRyusuke Konishi ri->ri_cno = cno++; 8630f3e1c7fSRyusuke Konishi ri->ri_super_root = pseg_end; 8640f3e1c7fSRyusuke Konishi ri->ri_lsegs_start = ri->ri_lsegs_end = 0; 8650f3e1c7fSRyusuke Konishi 8660f3e1c7fSRyusuke Konishi nilfs_dispose_segment_list(&segments); 8670f3e1c7fSRyusuke Konishi nilfs->ns_pseg_offset = (sr_pseg_start = pseg_start) 8680f3e1c7fSRyusuke Konishi + ssi.nblocks - seg_start; 8690f3e1c7fSRyusuke Konishi nilfs->ns_seg_seq = seg_seq; 8700f3e1c7fSRyusuke Konishi nilfs->ns_segnum = segnum; 8710f3e1c7fSRyusuke Konishi nilfs->ns_cno = cno; /* nilfs->ns_cno = ri->ri_cno + 1 */ 8720f3e1c7fSRyusuke Konishi nilfs->ns_ctime = ssi.ctime; 8730f3e1c7fSRyusuke Konishi nilfs->ns_nextnum = nextnum; 8740f3e1c7fSRyusuke Konishi 8750f3e1c7fSRyusuke Konishi if (scan_newer) 8760f3e1c7fSRyusuke Konishi ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED; 8772c2e52fcSRyusuke Konishi else { 8782c2e52fcSRyusuke Konishi if (nilfs->ns_mount_state & NILFS_VALID_FS) 8790f3e1c7fSRyusuke Konishi goto super_root_found; 8800f3e1c7fSRyusuke Konishi scan_newer = 1; 8812c2e52fcSRyusuke Konishi } 8820f3e1c7fSRyusuke Konishi 8830f3e1c7fSRyusuke Konishi /* reset region for roll-forward */ 8840f3e1c7fSRyusuke Konishi pseg_start += ssi.nblocks; 8850f3e1c7fSRyusuke Konishi if (pseg_start < seg_end) 8860f3e1c7fSRyusuke Konishi continue; 8870f3e1c7fSRyusuke Konishi goto feed_segment; 8880f3e1c7fSRyusuke Konishi 8890f3e1c7fSRyusuke Konishi try_next_pseg: 8900f3e1c7fSRyusuke Konishi /* Standing on a course, or met an inconsistent state */ 8910f3e1c7fSRyusuke Konishi pseg_start += ssi.nblocks; 8920f3e1c7fSRyusuke Konishi if (pseg_start < seg_end) 8930f3e1c7fSRyusuke Konishi continue; 8940f3e1c7fSRyusuke Konishi goto feed_segment; 8950f3e1c7fSRyusuke Konishi 8960f3e1c7fSRyusuke Konishi strayed: 8970f3e1c7fSRyusuke Konishi /* Off the trail */ 8980f3e1c7fSRyusuke Konishi if (!scan_newer) 8990f3e1c7fSRyusuke Konishi /* 9000f3e1c7fSRyusuke Konishi * This can happen if a checkpoint was written without 9010f3e1c7fSRyusuke Konishi * barriers, or as a result of an I/O failure. 9020f3e1c7fSRyusuke Konishi */ 9030f3e1c7fSRyusuke Konishi goto failed; 9040f3e1c7fSRyusuke Konishi 9050f3e1c7fSRyusuke Konishi feed_segment: 9060f3e1c7fSRyusuke Konishi /* Looking to the next full segment */ 9070f3e1c7fSRyusuke Konishi if (empty_seg++) 9080f3e1c7fSRyusuke Konishi goto super_root_found; /* found a valid super root */ 9090f3e1c7fSRyusuke Konishi 910654137ddSRyusuke Konishi ret = nilfs_segment_list_add(&segments, segnum); 911654137ddSRyusuke Konishi if (unlikely(ret)) 9120f3e1c7fSRyusuke Konishi goto failed; 9130f3e1c7fSRyusuke Konishi 9140f3e1c7fSRyusuke Konishi seg_seq++; 9150f3e1c7fSRyusuke Konishi segnum = nextnum; 9160f3e1c7fSRyusuke Konishi nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); 9170f3e1c7fSRyusuke Konishi pseg_start = seg_start; 9180f3e1c7fSRyusuke Konishi } 9190f3e1c7fSRyusuke Konishi 9200f3e1c7fSRyusuke Konishi super_root_found: 9210f3e1c7fSRyusuke Konishi /* Updating pointers relating to the latest checkpoint */ 9220f3e1c7fSRyusuke Konishi list_splice(&segments, ri->ri_used_segments.prev); 9230f3e1c7fSRyusuke Konishi nilfs->ns_last_pseg = sr_pseg_start; 9240f3e1c7fSRyusuke Konishi nilfs->ns_last_seq = nilfs->ns_seg_seq; 9250f3e1c7fSRyusuke Konishi nilfs->ns_last_cno = ri->ri_cno; 9260f3e1c7fSRyusuke Konishi return 0; 9270f3e1c7fSRyusuke Konishi 9280f3e1c7fSRyusuke Konishi failed: 9290f3e1c7fSRyusuke Konishi nilfs_dispose_segment_list(&segments); 9300f3e1c7fSRyusuke Konishi return (ret < 0) ? ret : nilfs_warn_segment_error(ret); 9310f3e1c7fSRyusuke Konishi } 932