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 * 164b420ab4SRyusuke Konishi * Written by Ryusuke Konishi. 170f3e1c7fSRyusuke Konishi */ 180f3e1c7fSRyusuke Konishi 190f3e1c7fSRyusuke Konishi #include <linux/buffer_head.h> 200f3e1c7fSRyusuke Konishi #include <linux/blkdev.h> 210f3e1c7fSRyusuke Konishi #include <linux/swap.h> 225a0e3ad6STejun Heo #include <linux/slab.h> 230f3e1c7fSRyusuke Konishi #include <linux/crc32.h> 240f3e1c7fSRyusuke Konishi #include "nilfs.h" 250f3e1c7fSRyusuke Konishi #include "segment.h" 260f3e1c7fSRyusuke Konishi #include "sufile.h" 270f3e1c7fSRyusuke Konishi #include "page.h" 280f3e1c7fSRyusuke Konishi #include "segbuf.h" 290f3e1c7fSRyusuke Konishi 300f3e1c7fSRyusuke Konishi /* 310f3e1c7fSRyusuke Konishi * Segment check result 320f3e1c7fSRyusuke Konishi */ 330f3e1c7fSRyusuke Konishi enum { 340f3e1c7fSRyusuke Konishi NILFS_SEG_VALID, 350f3e1c7fSRyusuke Konishi NILFS_SEG_NO_SUPER_ROOT, 360f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_IO, 370f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_MAGIC, 380f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_SEQ, 390f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT, 400f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_CHECKSUM_FULL, 410f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_CONSISTENCY, 420f3e1c7fSRyusuke Konishi }; 430f3e1c7fSRyusuke Konishi 440f3e1c7fSRyusuke Konishi /* work structure for recovery */ 450f3e1c7fSRyusuke Konishi struct nilfs_recovery_block { 46076a378bSRyusuke Konishi ino_t ino; /* 47076a378bSRyusuke Konishi * Inode number of the file that this block 48076a378bSRyusuke Konishi * belongs to 49076a378bSRyusuke Konishi */ 500f3e1c7fSRyusuke Konishi sector_t blocknr; /* block number */ 510f3e1c7fSRyusuke Konishi __u64 vblocknr; /* virtual block number */ 520f3e1c7fSRyusuke Konishi unsigned long blkoff; /* File offset of the data block (per block) */ 530f3e1c7fSRyusuke Konishi struct list_head list; 540f3e1c7fSRyusuke Konishi }; 550f3e1c7fSRyusuke Konishi 560f3e1c7fSRyusuke Konishi 570f3e1c7fSRyusuke Konishi static int nilfs_warn_segment_error(int err) 580f3e1c7fSRyusuke Konishi { 590f3e1c7fSRyusuke Konishi switch (err) { 600f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_IO: 610f3e1c7fSRyusuke Konishi printk(KERN_WARNING 620f3e1c7fSRyusuke Konishi "NILFS warning: I/O error on loading last segment\n"); 630f3e1c7fSRyusuke Konishi return -EIO; 640f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_MAGIC: 650f3e1c7fSRyusuke Konishi printk(KERN_WARNING 660f3e1c7fSRyusuke Konishi "NILFS warning: Segment magic number invalid\n"); 670f3e1c7fSRyusuke Konishi break; 680f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_SEQ: 690f3e1c7fSRyusuke Konishi printk(KERN_WARNING 700f3e1c7fSRyusuke Konishi "NILFS warning: Sequence number mismatch\n"); 710f3e1c7fSRyusuke Konishi break; 720f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT: 730f3e1c7fSRyusuke Konishi printk(KERN_WARNING 740f3e1c7fSRyusuke Konishi "NILFS warning: Checksum error in super root\n"); 750f3e1c7fSRyusuke Konishi break; 760f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_CHECKSUM_FULL: 770f3e1c7fSRyusuke Konishi printk(KERN_WARNING 780f3e1c7fSRyusuke Konishi "NILFS warning: Checksum error in segment payload\n"); 790f3e1c7fSRyusuke Konishi break; 800f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_CONSISTENCY: 810f3e1c7fSRyusuke Konishi printk(KERN_WARNING 820f3e1c7fSRyusuke Konishi "NILFS warning: Inconsistent segment\n"); 830f3e1c7fSRyusuke Konishi break; 840f3e1c7fSRyusuke Konishi case NILFS_SEG_NO_SUPER_ROOT: 850f3e1c7fSRyusuke Konishi printk(KERN_WARNING 860f3e1c7fSRyusuke Konishi "NILFS warning: No super root in the last segment\n"); 870f3e1c7fSRyusuke Konishi break; 880f3e1c7fSRyusuke Konishi } 890f3e1c7fSRyusuke Konishi return -EINVAL; 900f3e1c7fSRyusuke Konishi } 910f3e1c7fSRyusuke Konishi 920f3e1c7fSRyusuke Konishi /** 938b94025cSRyusuke Konishi * nilfs_compute_checksum - compute checksum of blocks continuously 948b94025cSRyusuke Konishi * @nilfs: nilfs object 950f3e1c7fSRyusuke Konishi * @bhs: buffer head of start block 960f3e1c7fSRyusuke Konishi * @sum: place to store result 970f3e1c7fSRyusuke Konishi * @offset: offset bytes in the first block 980f3e1c7fSRyusuke Konishi * @check_bytes: number of bytes to be checked 990f3e1c7fSRyusuke Konishi * @start: DBN of start block 1000f3e1c7fSRyusuke Konishi * @nblock: number of blocks to be checked 1010f3e1c7fSRyusuke Konishi */ 1028b94025cSRyusuke Konishi static int nilfs_compute_checksum(struct the_nilfs *nilfs, 1038b94025cSRyusuke Konishi struct buffer_head *bhs, u32 *sum, 1048b94025cSRyusuke Konishi unsigned long offset, u64 check_bytes, 1050f3e1c7fSRyusuke Konishi sector_t start, unsigned long nblock) 1060f3e1c7fSRyusuke Konishi { 1078b94025cSRyusuke Konishi unsigned int blocksize = nilfs->ns_blocksize; 1080f3e1c7fSRyusuke Konishi unsigned long size; 1090f3e1c7fSRyusuke Konishi u32 crc; 1100f3e1c7fSRyusuke Konishi 1110f3e1c7fSRyusuke Konishi BUG_ON(offset >= blocksize); 1120f3e1c7fSRyusuke Konishi check_bytes -= offset; 1130f3e1c7fSRyusuke Konishi size = min_t(u64, check_bytes, blocksize - offset); 1148b94025cSRyusuke Konishi crc = crc32_le(nilfs->ns_crc_seed, 1150f3e1c7fSRyusuke Konishi (unsigned char *)bhs->b_data + offset, size); 1160f3e1c7fSRyusuke Konishi if (--nblock > 0) { 1170f3e1c7fSRyusuke Konishi do { 1188b94025cSRyusuke Konishi struct buffer_head *bh; 1198b94025cSRyusuke Konishi 1208b94025cSRyusuke Konishi bh = __bread(nilfs->ns_bdev, ++start, blocksize); 1210f3e1c7fSRyusuke Konishi if (!bh) 1220f3e1c7fSRyusuke Konishi return -EIO; 1230f3e1c7fSRyusuke Konishi check_bytes -= size; 1240f3e1c7fSRyusuke Konishi size = min_t(u64, check_bytes, blocksize); 1250f3e1c7fSRyusuke Konishi crc = crc32_le(crc, bh->b_data, size); 1260f3e1c7fSRyusuke Konishi brelse(bh); 1270f3e1c7fSRyusuke Konishi } while (--nblock > 0); 1280f3e1c7fSRyusuke Konishi } 1290f3e1c7fSRyusuke Konishi *sum = crc; 1300f3e1c7fSRyusuke Konishi return 0; 1310f3e1c7fSRyusuke Konishi } 1320f3e1c7fSRyusuke Konishi 1330f3e1c7fSRyusuke Konishi /** 1340f3e1c7fSRyusuke Konishi * nilfs_read_super_root_block - read super root block 1358b94025cSRyusuke Konishi * @nilfs: nilfs object 1360f3e1c7fSRyusuke Konishi * @sr_block: disk block number of the super root block 1370f3e1c7fSRyusuke Konishi * @pbh: address of a buffer_head pointer to return super root buffer 1380f3e1c7fSRyusuke Konishi * @check: CRC check flag 1390f3e1c7fSRyusuke Konishi */ 1408b94025cSRyusuke Konishi int nilfs_read_super_root_block(struct the_nilfs *nilfs, sector_t sr_block, 1410f3e1c7fSRyusuke Konishi struct buffer_head **pbh, int check) 1420f3e1c7fSRyusuke Konishi { 1430f3e1c7fSRyusuke Konishi struct buffer_head *bh_sr; 1440f3e1c7fSRyusuke Konishi struct nilfs_super_root *sr; 1450f3e1c7fSRyusuke Konishi u32 crc; 1460f3e1c7fSRyusuke Konishi int ret; 1470f3e1c7fSRyusuke Konishi 1480f3e1c7fSRyusuke Konishi *pbh = NULL; 1498b94025cSRyusuke Konishi bh_sr = __bread(nilfs->ns_bdev, sr_block, nilfs->ns_blocksize); 1500f3e1c7fSRyusuke Konishi if (unlikely(!bh_sr)) { 1510f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_IO; 1520f3e1c7fSRyusuke Konishi goto failed; 1530f3e1c7fSRyusuke Konishi } 1540f3e1c7fSRyusuke Konishi 1550f3e1c7fSRyusuke Konishi sr = (struct nilfs_super_root *)bh_sr->b_data; 1560f3e1c7fSRyusuke Konishi if (check) { 1570c6c44cbSRyusuke Konishi unsigned int bytes = le16_to_cpu(sr->sr_bytes); 1580f3e1c7fSRyusuke Konishi 1598b94025cSRyusuke Konishi if (bytes == 0 || bytes > nilfs->ns_blocksize) { 1600f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT; 1610f3e1c7fSRyusuke Konishi goto failed_bh; 1620f3e1c7fSRyusuke Konishi } 1638b94025cSRyusuke Konishi if (nilfs_compute_checksum( 1648b94025cSRyusuke Konishi nilfs, bh_sr, &crc, sizeof(sr->sr_sum), bytes, 1658b94025cSRyusuke Konishi sr_block, 1)) { 1660f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_IO; 1670f3e1c7fSRyusuke Konishi goto failed_bh; 1680f3e1c7fSRyusuke Konishi } 1690f3e1c7fSRyusuke Konishi if (crc != le32_to_cpu(sr->sr_sum)) { 1700f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT; 1710f3e1c7fSRyusuke Konishi goto failed_bh; 1720f3e1c7fSRyusuke Konishi } 1730f3e1c7fSRyusuke Konishi } 1740f3e1c7fSRyusuke Konishi *pbh = bh_sr; 1750f3e1c7fSRyusuke Konishi return 0; 1760f3e1c7fSRyusuke Konishi 1770f3e1c7fSRyusuke Konishi failed_bh: 1780f3e1c7fSRyusuke Konishi brelse(bh_sr); 1790f3e1c7fSRyusuke Konishi 1800f3e1c7fSRyusuke Konishi failed: 1810f3e1c7fSRyusuke Konishi return nilfs_warn_segment_error(ret); 1820f3e1c7fSRyusuke Konishi } 1830f3e1c7fSRyusuke Konishi 1840f3e1c7fSRyusuke Konishi /** 185354fa8beSRyusuke Konishi * nilfs_read_log_header - read summary header of the specified log 1868b94025cSRyusuke Konishi * @nilfs: nilfs object 187354fa8beSRyusuke Konishi * @start_blocknr: start block number of the log 188354fa8beSRyusuke Konishi * @sum: pointer to return segment summary structure 1890f3e1c7fSRyusuke Konishi */ 190354fa8beSRyusuke Konishi static struct buffer_head * 191354fa8beSRyusuke Konishi nilfs_read_log_header(struct the_nilfs *nilfs, sector_t start_blocknr, 192354fa8beSRyusuke Konishi struct nilfs_segment_summary **sum) 1930f3e1c7fSRyusuke Konishi { 1940f3e1c7fSRyusuke Konishi struct buffer_head *bh_sum; 195354fa8beSRyusuke Konishi 196354fa8beSRyusuke Konishi bh_sum = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize); 197354fa8beSRyusuke Konishi if (bh_sum) 198354fa8beSRyusuke Konishi *sum = (struct nilfs_segment_summary *)bh_sum->b_data; 199354fa8beSRyusuke Konishi return bh_sum; 200354fa8beSRyusuke Konishi } 201354fa8beSRyusuke Konishi 202354fa8beSRyusuke Konishi /** 203354fa8beSRyusuke Konishi * nilfs_validate_log - verify consistency of log 204354fa8beSRyusuke Konishi * @nilfs: nilfs object 205354fa8beSRyusuke Konishi * @seg_seq: sequence number of segment 206354fa8beSRyusuke Konishi * @bh_sum: buffer head of summary block 207354fa8beSRyusuke Konishi * @sum: segment summary struct 208354fa8beSRyusuke Konishi */ 209354fa8beSRyusuke Konishi static int nilfs_validate_log(struct the_nilfs *nilfs, u64 seg_seq, 210354fa8beSRyusuke Konishi struct buffer_head *bh_sum, 211354fa8beSRyusuke Konishi struct nilfs_segment_summary *sum) 212354fa8beSRyusuke Konishi { 21303f29365SJiro SEKIBA unsigned long nblock; 21403f29365SJiro SEKIBA u32 crc; 215354fa8beSRyusuke Konishi int ret; 2160f3e1c7fSRyusuke Konishi 217354fa8beSRyusuke Konishi ret = NILFS_SEG_FAIL_MAGIC; 218354fa8beSRyusuke Konishi if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC) 2190f3e1c7fSRyusuke Konishi goto out; 2200f3e1c7fSRyusuke Konishi 2210f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_SEQ; 222354fa8beSRyusuke Konishi if (le64_to_cpu(sum->ss_seq) != seg_seq) 223354fa8beSRyusuke Konishi goto out; 2240f3e1c7fSRyusuke Konishi 225354fa8beSRyusuke Konishi nblock = le32_to_cpu(sum->ss_nblocks); 2260f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CONSISTENCY; 227354fa8beSRyusuke Konishi if (unlikely(nblock == 0 || nblock > nilfs->ns_blocks_per_segment)) 228354fa8beSRyusuke Konishi /* This limits the number of blocks read in the CRC check */ 229354fa8beSRyusuke Konishi goto out; 230354fa8beSRyusuke Konishi 231354fa8beSRyusuke Konishi ret = NILFS_SEG_FAIL_IO; 2328b94025cSRyusuke Konishi if (nilfs_compute_checksum(nilfs, bh_sum, &crc, sizeof(sum->ss_datasum), 2338b94025cSRyusuke Konishi ((u64)nblock << nilfs->ns_blocksize_bits), 234354fa8beSRyusuke Konishi bh_sum->b_blocknr, nblock)) 235354fa8beSRyusuke Konishi goto out; 236354fa8beSRyusuke Konishi 23703f29365SJiro SEKIBA ret = NILFS_SEG_FAIL_CHECKSUM_FULL; 238354fa8beSRyusuke Konishi if (crc != le32_to_cpu(sum->ss_datasum)) 239354fa8beSRyusuke Konishi goto out; 240354fa8beSRyusuke Konishi ret = 0; 2410f3e1c7fSRyusuke Konishi out: 2420f3e1c7fSRyusuke Konishi return ret; 2430f3e1c7fSRyusuke Konishi } 2440f3e1c7fSRyusuke Konishi 2458b94025cSRyusuke Konishi /** 2468b94025cSRyusuke Konishi * nilfs_read_summary_info - read an item on summary blocks of a log 2478b94025cSRyusuke Konishi * @nilfs: nilfs object 2488b94025cSRyusuke Konishi * @pbh: the current buffer head on summary blocks [in, out] 2498b94025cSRyusuke Konishi * @offset: the current byte offset on summary blocks [in, out] 2508b94025cSRyusuke Konishi * @bytes: byte size of the item to be read 2518b94025cSRyusuke Konishi */ 2528b94025cSRyusuke Konishi static void *nilfs_read_summary_info(struct the_nilfs *nilfs, 2538b94025cSRyusuke Konishi struct buffer_head **pbh, 2540f3e1c7fSRyusuke Konishi unsigned int *offset, unsigned int bytes) 2550f3e1c7fSRyusuke Konishi { 2560f3e1c7fSRyusuke Konishi void *ptr; 2570f3e1c7fSRyusuke Konishi sector_t blocknr; 2580f3e1c7fSRyusuke Konishi 2590f3e1c7fSRyusuke Konishi BUG_ON((*pbh)->b_size < *offset); 2600f3e1c7fSRyusuke Konishi if (bytes > (*pbh)->b_size - *offset) { 2610f3e1c7fSRyusuke Konishi blocknr = (*pbh)->b_blocknr; 2620f3e1c7fSRyusuke Konishi brelse(*pbh); 2638b94025cSRyusuke Konishi *pbh = __bread(nilfs->ns_bdev, blocknr + 1, 2648b94025cSRyusuke Konishi nilfs->ns_blocksize); 2650f3e1c7fSRyusuke Konishi if (unlikely(!*pbh)) 2660f3e1c7fSRyusuke Konishi return NULL; 2670f3e1c7fSRyusuke Konishi *offset = 0; 2680f3e1c7fSRyusuke Konishi } 2690f3e1c7fSRyusuke Konishi ptr = (*pbh)->b_data + *offset; 2700f3e1c7fSRyusuke Konishi *offset += bytes; 2710f3e1c7fSRyusuke Konishi return ptr; 2720f3e1c7fSRyusuke Konishi } 2730f3e1c7fSRyusuke Konishi 2748b94025cSRyusuke Konishi /** 2758b94025cSRyusuke Konishi * nilfs_skip_summary_info - skip items on summary blocks of a log 2768b94025cSRyusuke Konishi * @nilfs: nilfs object 2778b94025cSRyusuke Konishi * @pbh: the current buffer head on summary blocks [in, out] 2788b94025cSRyusuke Konishi * @offset: the current byte offset on summary blocks [in, out] 2798b94025cSRyusuke Konishi * @bytes: byte size of the item to be skipped 2808b94025cSRyusuke Konishi * @count: number of items to be skipped 2818b94025cSRyusuke Konishi */ 2828b94025cSRyusuke Konishi static void nilfs_skip_summary_info(struct the_nilfs *nilfs, 2838b94025cSRyusuke Konishi struct buffer_head **pbh, 2840f3e1c7fSRyusuke Konishi unsigned int *offset, unsigned int bytes, 2850f3e1c7fSRyusuke Konishi unsigned long count) 2860f3e1c7fSRyusuke Konishi { 2870f3e1c7fSRyusuke Konishi unsigned int rest_item_in_current_block 2880f3e1c7fSRyusuke Konishi = ((*pbh)->b_size - *offset) / bytes; 2890f3e1c7fSRyusuke Konishi 2900f3e1c7fSRyusuke Konishi if (count <= rest_item_in_current_block) { 2910f3e1c7fSRyusuke Konishi *offset += bytes * count; 2920f3e1c7fSRyusuke Konishi } else { 2930f3e1c7fSRyusuke Konishi sector_t blocknr = (*pbh)->b_blocknr; 2940f3e1c7fSRyusuke Konishi unsigned int nitem_per_block = (*pbh)->b_size / bytes; 2950f3e1c7fSRyusuke Konishi unsigned int bcnt; 2960f3e1c7fSRyusuke Konishi 2970f3e1c7fSRyusuke Konishi count -= rest_item_in_current_block; 2980f3e1c7fSRyusuke Konishi bcnt = DIV_ROUND_UP(count, nitem_per_block); 2990f3e1c7fSRyusuke Konishi *offset = bytes * (count - (bcnt - 1) * nitem_per_block); 3000f3e1c7fSRyusuke Konishi 3010f3e1c7fSRyusuke Konishi brelse(*pbh); 3028b94025cSRyusuke Konishi *pbh = __bread(nilfs->ns_bdev, blocknr + bcnt, 3038b94025cSRyusuke Konishi nilfs->ns_blocksize); 3040f3e1c7fSRyusuke Konishi } 3050f3e1c7fSRyusuke Konishi } 3060f3e1c7fSRyusuke Konishi 3078b94025cSRyusuke Konishi /** 3088b94025cSRyusuke Konishi * nilfs_scan_dsync_log - get block information of a log written for data sync 3098b94025cSRyusuke Konishi * @nilfs: nilfs object 3108b94025cSRyusuke Konishi * @start_blocknr: start block number of the log 31185655484SRyusuke Konishi * @sum: log summary information 3128b94025cSRyusuke Konishi * @head: list head to add nilfs_recovery_block struct 3138b94025cSRyusuke Konishi */ 3148b94025cSRyusuke Konishi static int nilfs_scan_dsync_log(struct the_nilfs *nilfs, sector_t start_blocknr, 31585655484SRyusuke Konishi struct nilfs_segment_summary *sum, 3160f3e1c7fSRyusuke Konishi struct list_head *head) 3170f3e1c7fSRyusuke Konishi { 3180f3e1c7fSRyusuke Konishi struct buffer_head *bh; 3190f3e1c7fSRyusuke Konishi unsigned int offset; 32085655484SRyusuke Konishi u32 nfinfo, sumbytes; 32185655484SRyusuke Konishi sector_t blocknr; 3220f3e1c7fSRyusuke Konishi ino_t ino; 3230f3e1c7fSRyusuke Konishi int err = -EIO; 3240f3e1c7fSRyusuke Konishi 32585655484SRyusuke Konishi nfinfo = le32_to_cpu(sum->ss_nfinfo); 3260f3e1c7fSRyusuke Konishi if (!nfinfo) 3270f3e1c7fSRyusuke Konishi return 0; 3280f3e1c7fSRyusuke Konishi 32985655484SRyusuke Konishi sumbytes = le32_to_cpu(sum->ss_sumbytes); 33085655484SRyusuke Konishi blocknr = start_blocknr + DIV_ROUND_UP(sumbytes, nilfs->ns_blocksize); 3318b94025cSRyusuke Konishi bh = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize); 3320f3e1c7fSRyusuke Konishi if (unlikely(!bh)) 3330f3e1c7fSRyusuke Konishi goto out; 3340f3e1c7fSRyusuke Konishi 33585655484SRyusuke Konishi offset = le16_to_cpu(sum->ss_bytes); 3360f3e1c7fSRyusuke Konishi for (;;) { 3370f3e1c7fSRyusuke Konishi unsigned long nblocks, ndatablk, nnodeblk; 3380f3e1c7fSRyusuke Konishi struct nilfs_finfo *finfo; 3390f3e1c7fSRyusuke Konishi 3408b94025cSRyusuke Konishi finfo = nilfs_read_summary_info(nilfs, &bh, &offset, 3418b94025cSRyusuke Konishi sizeof(*finfo)); 3420f3e1c7fSRyusuke Konishi if (unlikely(!finfo)) 3430f3e1c7fSRyusuke Konishi goto out; 3440f3e1c7fSRyusuke Konishi 3450f3e1c7fSRyusuke Konishi ino = le64_to_cpu(finfo->fi_ino); 3460f3e1c7fSRyusuke Konishi nblocks = le32_to_cpu(finfo->fi_nblocks); 3470f3e1c7fSRyusuke Konishi ndatablk = le32_to_cpu(finfo->fi_ndatablk); 3480f3e1c7fSRyusuke Konishi nnodeblk = nblocks - ndatablk; 3490f3e1c7fSRyusuke Konishi 3500f3e1c7fSRyusuke Konishi while (ndatablk-- > 0) { 3510f3e1c7fSRyusuke Konishi struct nilfs_recovery_block *rb; 3520f3e1c7fSRyusuke Konishi struct nilfs_binfo_v *binfo; 3530f3e1c7fSRyusuke Konishi 3548b94025cSRyusuke Konishi binfo = nilfs_read_summary_info(nilfs, &bh, &offset, 3550f3e1c7fSRyusuke Konishi sizeof(*binfo)); 3560f3e1c7fSRyusuke Konishi if (unlikely(!binfo)) 3570f3e1c7fSRyusuke Konishi goto out; 3580f3e1c7fSRyusuke Konishi 3590f3e1c7fSRyusuke Konishi rb = kmalloc(sizeof(*rb), GFP_NOFS); 3600f3e1c7fSRyusuke Konishi if (unlikely(!rb)) { 3610f3e1c7fSRyusuke Konishi err = -ENOMEM; 3620f3e1c7fSRyusuke Konishi goto out; 3630f3e1c7fSRyusuke Konishi } 3640f3e1c7fSRyusuke Konishi rb->ino = ino; 3650f3e1c7fSRyusuke Konishi rb->blocknr = blocknr++; 3660f3e1c7fSRyusuke Konishi rb->vblocknr = le64_to_cpu(binfo->bi_vblocknr); 3670f3e1c7fSRyusuke Konishi rb->blkoff = le64_to_cpu(binfo->bi_blkoff); 3680f3e1c7fSRyusuke Konishi /* INIT_LIST_HEAD(&rb->list); */ 3690f3e1c7fSRyusuke Konishi list_add_tail(&rb->list, head); 3700f3e1c7fSRyusuke Konishi } 3710f3e1c7fSRyusuke Konishi if (--nfinfo == 0) 3720f3e1c7fSRyusuke Konishi break; 3738b94025cSRyusuke Konishi blocknr += nnodeblk; /* always 0 for data sync logs */ 3748b94025cSRyusuke Konishi nilfs_skip_summary_info(nilfs, &bh, &offset, sizeof(__le64), 3750f3e1c7fSRyusuke Konishi nnodeblk); 3760f3e1c7fSRyusuke Konishi if (unlikely(!bh)) 3770f3e1c7fSRyusuke Konishi goto out; 3780f3e1c7fSRyusuke Konishi } 3790f3e1c7fSRyusuke Konishi err = 0; 3800f3e1c7fSRyusuke Konishi out: 3810f3e1c7fSRyusuke Konishi brelse(bh); /* brelse(NULL) is just ignored */ 3820f3e1c7fSRyusuke Konishi return err; 3830f3e1c7fSRyusuke Konishi } 3840f3e1c7fSRyusuke Konishi 3850f3e1c7fSRyusuke Konishi static void dispose_recovery_list(struct list_head *head) 3860f3e1c7fSRyusuke Konishi { 3870f3e1c7fSRyusuke Konishi while (!list_empty(head)) { 3880cc12838SRyusuke Konishi struct nilfs_recovery_block *rb; 3890cc12838SRyusuke Konishi 3900cc12838SRyusuke Konishi rb = list_first_entry(head, struct nilfs_recovery_block, list); 3910f3e1c7fSRyusuke Konishi list_del(&rb->list); 3920f3e1c7fSRyusuke Konishi kfree(rb); 3930f3e1c7fSRyusuke Konishi } 3940f3e1c7fSRyusuke Konishi } 3950f3e1c7fSRyusuke Konishi 396654137ddSRyusuke Konishi struct nilfs_segment_entry { 397654137ddSRyusuke Konishi struct list_head list; 398654137ddSRyusuke Konishi __u64 segnum; 399654137ddSRyusuke Konishi }; 400654137ddSRyusuke Konishi 401654137ddSRyusuke Konishi static int nilfs_segment_list_add(struct list_head *head, __u64 segnum) 402654137ddSRyusuke Konishi { 403654137ddSRyusuke Konishi struct nilfs_segment_entry *ent = kmalloc(sizeof(*ent), GFP_NOFS); 404654137ddSRyusuke Konishi 405654137ddSRyusuke Konishi if (unlikely(!ent)) 406654137ddSRyusuke Konishi return -ENOMEM; 407654137ddSRyusuke Konishi 408654137ddSRyusuke Konishi ent->segnum = segnum; 409654137ddSRyusuke Konishi INIT_LIST_HEAD(&ent->list); 410654137ddSRyusuke Konishi list_add_tail(&ent->list, head); 411654137ddSRyusuke Konishi return 0; 412654137ddSRyusuke Konishi } 413654137ddSRyusuke Konishi 4140f3e1c7fSRyusuke Konishi void nilfs_dispose_segment_list(struct list_head *head) 4150f3e1c7fSRyusuke Konishi { 4160f3e1c7fSRyusuke Konishi while (!list_empty(head)) { 4170cc12838SRyusuke Konishi struct nilfs_segment_entry *ent; 4180cc12838SRyusuke Konishi 4190cc12838SRyusuke Konishi ent = list_first_entry(head, struct nilfs_segment_entry, list); 4200f3e1c7fSRyusuke Konishi list_del(&ent->list); 421654137ddSRyusuke Konishi kfree(ent); 4220f3e1c7fSRyusuke Konishi } 4230f3e1c7fSRyusuke Konishi } 4240f3e1c7fSRyusuke Konishi 4250f3e1c7fSRyusuke Konishi static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, 426f7545144SRyusuke Konishi struct super_block *sb, 4270f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 4280f3e1c7fSRyusuke Konishi { 4290f3e1c7fSRyusuke Konishi struct list_head *head = &ri->ri_used_segments; 4300f3e1c7fSRyusuke Konishi struct nilfs_segment_entry *ent, *n; 4310f3e1c7fSRyusuke Konishi struct inode *sufile = nilfs->ns_sufile; 4320f3e1c7fSRyusuke Konishi __u64 segnum[4]; 4330f3e1c7fSRyusuke Konishi int err; 4340f3e1c7fSRyusuke Konishi int i; 4350f3e1c7fSRyusuke Konishi 4360f3e1c7fSRyusuke Konishi segnum[0] = nilfs->ns_segnum; 4370f3e1c7fSRyusuke Konishi segnum[1] = nilfs->ns_nextnum; 4380f3e1c7fSRyusuke Konishi segnum[2] = ri->ri_segnum; 4390f3e1c7fSRyusuke Konishi segnum[3] = ri->ri_nextnum; 4400f3e1c7fSRyusuke Konishi 4410f3e1c7fSRyusuke Konishi /* 4420f3e1c7fSRyusuke Konishi * Releasing the next segment of the latest super root. 4430f3e1c7fSRyusuke Konishi * The next segment is invalidated by this recovery. 4440f3e1c7fSRyusuke Konishi */ 4450f3e1c7fSRyusuke Konishi err = nilfs_sufile_free(sufile, segnum[1]); 4460f3e1c7fSRyusuke Konishi if (unlikely(err)) 4470f3e1c7fSRyusuke Konishi goto failed; 4480f3e1c7fSRyusuke Konishi 4490f3e1c7fSRyusuke Konishi for (i = 1; i < 4; i++) { 450654137ddSRyusuke Konishi err = nilfs_segment_list_add(head, segnum[i]); 451654137ddSRyusuke Konishi if (unlikely(err)) 4520f3e1c7fSRyusuke Konishi goto failed; 4530f3e1c7fSRyusuke Konishi } 4540f3e1c7fSRyusuke Konishi 4550f3e1c7fSRyusuke Konishi /* 4560f3e1c7fSRyusuke Konishi * Collecting segments written after the latest super root. 4572c2e52fcSRyusuke Konishi * These are marked dirty to avoid being reallocated in the next write. 4580f3e1c7fSRyusuke Konishi */ 4590f3e1c7fSRyusuke Konishi list_for_each_entry_safe(ent, n, head, list) { 460c85399c2SRyusuke Konishi if (ent->segnum != segnum[0]) { 461c85399c2SRyusuke Konishi err = nilfs_sufile_scrap(sufile, ent->segnum); 4620f3e1c7fSRyusuke Konishi if (unlikely(err)) 4630f3e1c7fSRyusuke Konishi goto failed; 4642c2e52fcSRyusuke Konishi } 4650f3e1c7fSRyusuke Konishi list_del(&ent->list); 466654137ddSRyusuke Konishi kfree(ent); 4670f3e1c7fSRyusuke Konishi } 4680f3e1c7fSRyusuke Konishi 4690f3e1c7fSRyusuke Konishi /* Allocate new segments for recovery */ 4700f3e1c7fSRyusuke Konishi err = nilfs_sufile_alloc(sufile, &segnum[0]); 4710f3e1c7fSRyusuke Konishi if (unlikely(err)) 4720f3e1c7fSRyusuke Konishi goto failed; 4730f3e1c7fSRyusuke Konishi 4740f3e1c7fSRyusuke Konishi nilfs->ns_pseg_offset = 0; 4750f3e1c7fSRyusuke Konishi nilfs->ns_seg_seq = ri->ri_seq + 2; 4760f3e1c7fSRyusuke Konishi nilfs->ns_nextnum = nilfs->ns_segnum = segnum[0]; 4770f3e1c7fSRyusuke Konishi 4780f3e1c7fSRyusuke Konishi failed: 4790f3e1c7fSRyusuke Konishi /* No need to recover sufile because it will be destroyed on error */ 4800f3e1c7fSRyusuke Konishi return err; 4810f3e1c7fSRyusuke Konishi } 4820f3e1c7fSRyusuke Konishi 4838b94025cSRyusuke Konishi static int nilfs_recovery_copy_block(struct the_nilfs *nilfs, 4840f3e1c7fSRyusuke Konishi struct nilfs_recovery_block *rb, 4850f3e1c7fSRyusuke Konishi struct page *page) 4860f3e1c7fSRyusuke Konishi { 4870f3e1c7fSRyusuke Konishi struct buffer_head *bh_org; 4880f3e1c7fSRyusuke Konishi void *kaddr; 4890f3e1c7fSRyusuke Konishi 4908b94025cSRyusuke Konishi bh_org = __bread(nilfs->ns_bdev, rb->blocknr, nilfs->ns_blocksize); 4910f3e1c7fSRyusuke Konishi if (unlikely(!bh_org)) 4920f3e1c7fSRyusuke Konishi return -EIO; 4930f3e1c7fSRyusuke Konishi 4947b9c0976SCong Wang kaddr = kmap_atomic(page); 4950f3e1c7fSRyusuke Konishi memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size); 4967b9c0976SCong Wang kunmap_atomic(kaddr); 4970f3e1c7fSRyusuke Konishi brelse(bh_org); 4980f3e1c7fSRyusuke Konishi return 0; 4990f3e1c7fSRyusuke Konishi } 5000f3e1c7fSRyusuke Konishi 5018b94025cSRyusuke Konishi static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, 502f7545144SRyusuke Konishi struct super_block *sb, 5034d8d9293SRyusuke Konishi struct nilfs_root *root, 5040f3e1c7fSRyusuke Konishi struct list_head *head, 5050f3e1c7fSRyusuke Konishi unsigned long *nr_salvaged_blocks) 5060f3e1c7fSRyusuke Konishi { 5070f3e1c7fSRyusuke Konishi struct inode *inode; 5080f3e1c7fSRyusuke Konishi struct nilfs_recovery_block *rb, *n; 5090c6c44cbSRyusuke Konishi unsigned int blocksize = nilfs->ns_blocksize; 5100f3e1c7fSRyusuke Konishi struct page *page; 5110f3e1c7fSRyusuke Konishi loff_t pos; 5120f3e1c7fSRyusuke Konishi int err = 0, err2 = 0; 5130f3e1c7fSRyusuke Konishi 5140f3e1c7fSRyusuke Konishi list_for_each_entry_safe(rb, n, head, list) { 515f7545144SRyusuke Konishi inode = nilfs_iget(sb, root, rb->ino); 5160f3e1c7fSRyusuke Konishi if (IS_ERR(inode)) { 5170f3e1c7fSRyusuke Konishi err = PTR_ERR(inode); 5180f3e1c7fSRyusuke Konishi inode = NULL; 5190f3e1c7fSRyusuke Konishi goto failed_inode; 5200f3e1c7fSRyusuke Konishi } 5210f3e1c7fSRyusuke Konishi 5220f3e1c7fSRyusuke Konishi pos = rb->blkoff << inode->i_blkbits; 523155130a4SChristoph Hellwig err = block_write_begin(inode->i_mapping, pos, blocksize, 524155130a4SChristoph Hellwig 0, &page, nilfs_get_block); 525155130a4SChristoph Hellwig if (unlikely(err)) { 526155130a4SChristoph Hellwig loff_t isize = inode->i_size; 5274ad364caSRyusuke Konishi 528155130a4SChristoph Hellwig if (pos + blocksize > isize) 5292d1b399bSMarco Stornelli nilfs_write_failed(inode->i_mapping, 5302d1b399bSMarco Stornelli pos + blocksize); 5310f3e1c7fSRyusuke Konishi goto failed_inode; 532155130a4SChristoph Hellwig } 5330f3e1c7fSRyusuke Konishi 5348b94025cSRyusuke Konishi err = nilfs_recovery_copy_block(nilfs, rb, page); 5350f3e1c7fSRyusuke Konishi if (unlikely(err)) 5360f3e1c7fSRyusuke Konishi goto failed_page; 5370f3e1c7fSRyusuke Konishi 538bcbc8c64SRyusuke Konishi err = nilfs_set_file_dirty(inode, 1); 5390f3e1c7fSRyusuke Konishi if (unlikely(err)) 5400f3e1c7fSRyusuke Konishi goto failed_page; 5410f3e1c7fSRyusuke Konishi 5420f3e1c7fSRyusuke Konishi block_write_end(NULL, inode->i_mapping, pos, blocksize, 5430f3e1c7fSRyusuke Konishi blocksize, page, NULL); 5440f3e1c7fSRyusuke Konishi 5450f3e1c7fSRyusuke Konishi unlock_page(page); 54609cbfeafSKirill A. Shutemov put_page(page); 5470f3e1c7fSRyusuke Konishi 5480f3e1c7fSRyusuke Konishi (*nr_salvaged_blocks)++; 5490f3e1c7fSRyusuke Konishi goto next; 5500f3e1c7fSRyusuke Konishi 5510f3e1c7fSRyusuke Konishi failed_page: 5520f3e1c7fSRyusuke Konishi unlock_page(page); 55309cbfeafSKirill A. Shutemov put_page(page); 5540f3e1c7fSRyusuke Konishi 5550f3e1c7fSRyusuke Konishi failed_inode: 5560f3e1c7fSRyusuke Konishi printk(KERN_WARNING 5570f3e1c7fSRyusuke Konishi "NILFS warning: error recovering data block " 5580f3e1c7fSRyusuke Konishi "(err=%d, ino=%lu, block-offset=%llu)\n", 559b5696e5eSHeiko Carstens err, (unsigned long)rb->ino, 560b5696e5eSHeiko Carstens (unsigned long long)rb->blkoff); 5610f3e1c7fSRyusuke Konishi if (!err2) 5620f3e1c7fSRyusuke Konishi err2 = err; 5630f3e1c7fSRyusuke Konishi next: 5640f3e1c7fSRyusuke Konishi iput(inode); /* iput(NULL) is just ignored */ 5650f3e1c7fSRyusuke Konishi list_del_init(&rb->list); 5660f3e1c7fSRyusuke Konishi kfree(rb); 5670f3e1c7fSRyusuke Konishi } 5680f3e1c7fSRyusuke Konishi return err2; 5690f3e1c7fSRyusuke Konishi } 5700f3e1c7fSRyusuke Konishi 5710f3e1c7fSRyusuke Konishi /** 5720f3e1c7fSRyusuke Konishi * nilfs_do_roll_forward - salvage logical segments newer than the latest 5730f3e1c7fSRyusuke Konishi * checkpoint 5748b94025cSRyusuke Konishi * @nilfs: nilfs object 575f7545144SRyusuke Konishi * @sb: super block instance 5760f3e1c7fSRyusuke Konishi * @ri: pointer to a nilfs_recovery_info 5770f3e1c7fSRyusuke Konishi */ 5780f3e1c7fSRyusuke Konishi static int nilfs_do_roll_forward(struct the_nilfs *nilfs, 579f7545144SRyusuke Konishi struct super_block *sb, 5804d8d9293SRyusuke Konishi struct nilfs_root *root, 5810f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 5820f3e1c7fSRyusuke Konishi { 583354fa8beSRyusuke Konishi struct buffer_head *bh_sum = NULL; 5844f05028fSRyusuke Konishi struct nilfs_segment_summary *sum = NULL; 5850f3e1c7fSRyusuke Konishi sector_t pseg_start; 5860f3e1c7fSRyusuke Konishi sector_t seg_start, seg_end; /* Starting/ending DBN of full segment */ 5870f3e1c7fSRyusuke Konishi unsigned long nsalvaged_blocks = 0; 58885655484SRyusuke Konishi unsigned int flags; 5890f3e1c7fSRyusuke Konishi u64 seg_seq; 5900f3e1c7fSRyusuke Konishi __u64 segnum, nextnum = 0; 5910f3e1c7fSRyusuke Konishi int empty_seg = 0; 5920f3e1c7fSRyusuke Konishi int err = 0, ret; 5930f3e1c7fSRyusuke Konishi LIST_HEAD(dsync_blocks); /* list of data blocks to be recovered */ 5940f3e1c7fSRyusuke Konishi enum { 5950f3e1c7fSRyusuke Konishi RF_INIT_ST, 5960f3e1c7fSRyusuke Konishi RF_DSYNC_ST, /* scanning data-sync segments */ 5970f3e1c7fSRyusuke Konishi }; 5980f3e1c7fSRyusuke Konishi int state = RF_INIT_ST; 5990f3e1c7fSRyusuke Konishi 6000f3e1c7fSRyusuke Konishi pseg_start = ri->ri_lsegs_start; 6010f3e1c7fSRyusuke Konishi seg_seq = ri->ri_lsegs_start_seq; 6020f3e1c7fSRyusuke Konishi segnum = nilfs_get_segnum_of_block(nilfs, pseg_start); 6030f3e1c7fSRyusuke Konishi nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); 6040f3e1c7fSRyusuke Konishi 6050f3e1c7fSRyusuke Konishi while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) { 606354fa8beSRyusuke Konishi brelse(bh_sum); 607354fa8beSRyusuke Konishi bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum); 608354fa8beSRyusuke Konishi if (!bh_sum) { 609354fa8beSRyusuke Konishi err = -EIO; 610354fa8beSRyusuke Konishi goto failed; 611354fa8beSRyusuke Konishi } 6120f3e1c7fSRyusuke Konishi 613354fa8beSRyusuke Konishi ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum); 6140f3e1c7fSRyusuke Konishi if (ret) { 6150f3e1c7fSRyusuke Konishi if (ret == NILFS_SEG_FAIL_IO) { 6160f3e1c7fSRyusuke Konishi err = -EIO; 6170f3e1c7fSRyusuke Konishi goto failed; 6180f3e1c7fSRyusuke Konishi } 6190f3e1c7fSRyusuke Konishi goto strayed; 6200f3e1c7fSRyusuke Konishi } 621354fa8beSRyusuke Konishi 62285655484SRyusuke Konishi flags = le16_to_cpu(sum->ss_flags); 62385655484SRyusuke Konishi if (flags & NILFS_SS_SR) 6240f3e1c7fSRyusuke Konishi goto confused; 6250f3e1c7fSRyusuke Konishi 6260f3e1c7fSRyusuke Konishi /* Found a valid partial segment; do recovery actions */ 62785655484SRyusuke Konishi nextnum = nilfs_get_segnum_of_block(nilfs, 62885655484SRyusuke Konishi le64_to_cpu(sum->ss_next)); 6290f3e1c7fSRyusuke Konishi empty_seg = 0; 63085655484SRyusuke Konishi nilfs->ns_ctime = le64_to_cpu(sum->ss_create); 63185655484SRyusuke Konishi if (!(flags & NILFS_SS_GC)) 63285655484SRyusuke Konishi nilfs->ns_nongc_ctime = nilfs->ns_ctime; 6330f3e1c7fSRyusuke Konishi 6340f3e1c7fSRyusuke Konishi switch (state) { 6350f3e1c7fSRyusuke Konishi case RF_INIT_ST: 63685655484SRyusuke Konishi if (!(flags & NILFS_SS_LOGBGN) || 63785655484SRyusuke Konishi !(flags & NILFS_SS_SYNDT)) 6380f3e1c7fSRyusuke Konishi goto try_next_pseg; 6390f3e1c7fSRyusuke Konishi state = RF_DSYNC_ST; 6400f3e1c7fSRyusuke Konishi /* Fall through */ 6410f3e1c7fSRyusuke Konishi case RF_DSYNC_ST: 64285655484SRyusuke Konishi if (!(flags & NILFS_SS_SYNDT)) 6430f3e1c7fSRyusuke Konishi goto confused; 6440f3e1c7fSRyusuke Konishi 64585655484SRyusuke Konishi err = nilfs_scan_dsync_log(nilfs, pseg_start, sum, 6468b94025cSRyusuke Konishi &dsync_blocks); 6470f3e1c7fSRyusuke Konishi if (unlikely(err)) 6480f3e1c7fSRyusuke Konishi goto failed; 64985655484SRyusuke Konishi if (flags & NILFS_SS_LOGEND) { 6508b94025cSRyusuke Konishi err = nilfs_recover_dsync_blocks( 651f7545144SRyusuke Konishi nilfs, sb, root, &dsync_blocks, 6528b94025cSRyusuke Konishi &nsalvaged_blocks); 6530f3e1c7fSRyusuke Konishi if (unlikely(err)) 6540f3e1c7fSRyusuke Konishi goto failed; 6550f3e1c7fSRyusuke Konishi state = RF_INIT_ST; 6560f3e1c7fSRyusuke Konishi } 6570f3e1c7fSRyusuke Konishi break; /* Fall through to try_next_pseg */ 6580f3e1c7fSRyusuke Konishi } 6590f3e1c7fSRyusuke Konishi 6600f3e1c7fSRyusuke Konishi try_next_pseg: 6610f3e1c7fSRyusuke Konishi if (pseg_start == ri->ri_lsegs_end) 6620f3e1c7fSRyusuke Konishi break; 66385655484SRyusuke Konishi pseg_start += le32_to_cpu(sum->ss_nblocks); 6640f3e1c7fSRyusuke Konishi if (pseg_start < seg_end) 6650f3e1c7fSRyusuke Konishi continue; 6660f3e1c7fSRyusuke Konishi goto feed_segment; 6670f3e1c7fSRyusuke Konishi 6680f3e1c7fSRyusuke Konishi strayed: 6690f3e1c7fSRyusuke Konishi if (pseg_start == ri->ri_lsegs_end) 6700f3e1c7fSRyusuke Konishi break; 6710f3e1c7fSRyusuke Konishi 6720f3e1c7fSRyusuke Konishi feed_segment: 6730f3e1c7fSRyusuke Konishi /* Looking to the next full segment */ 6740f3e1c7fSRyusuke Konishi if (empty_seg++) 6750f3e1c7fSRyusuke Konishi break; 6760f3e1c7fSRyusuke Konishi seg_seq++; 6770f3e1c7fSRyusuke Konishi segnum = nextnum; 6780f3e1c7fSRyusuke Konishi nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); 6790f3e1c7fSRyusuke Konishi pseg_start = seg_start; 6800f3e1c7fSRyusuke Konishi } 6810f3e1c7fSRyusuke Konishi 6820f3e1c7fSRyusuke Konishi if (nsalvaged_blocks) { 6830f3e1c7fSRyusuke Konishi printk(KERN_INFO "NILFS (device %s): salvaged %lu blocks\n", 684f7545144SRyusuke Konishi sb->s_id, nsalvaged_blocks); 6850f3e1c7fSRyusuke Konishi ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; 6860f3e1c7fSRyusuke Konishi } 6870f3e1c7fSRyusuke Konishi out: 688354fa8beSRyusuke Konishi brelse(bh_sum); 6890f3e1c7fSRyusuke Konishi dispose_recovery_list(&dsync_blocks); 6900f3e1c7fSRyusuke Konishi return err; 6910f3e1c7fSRyusuke Konishi 6920f3e1c7fSRyusuke Konishi confused: 6930f3e1c7fSRyusuke Konishi err = -EINVAL; 6940f3e1c7fSRyusuke Konishi failed: 6950f3e1c7fSRyusuke Konishi printk(KERN_ERR 6960f3e1c7fSRyusuke Konishi "NILFS (device %s): Error roll-forwarding " 6970f3e1c7fSRyusuke Konishi "(err=%d, pseg block=%llu). ", 698f7545144SRyusuke Konishi sb->s_id, err, (unsigned long long)pseg_start); 6990f3e1c7fSRyusuke Konishi goto out; 7000f3e1c7fSRyusuke Konishi } 7010f3e1c7fSRyusuke Konishi 7020f3e1c7fSRyusuke Konishi static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, 7030f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 7040f3e1c7fSRyusuke Konishi { 7050f3e1c7fSRyusuke Konishi struct buffer_head *bh; 7060f3e1c7fSRyusuke Konishi int err; 7070f3e1c7fSRyusuke Konishi 7080f3e1c7fSRyusuke Konishi if (nilfs_get_segnum_of_block(nilfs, ri->ri_lsegs_start) != 7090f3e1c7fSRyusuke Konishi nilfs_get_segnum_of_block(nilfs, ri->ri_super_root)) 7100f3e1c7fSRyusuke Konishi return; 7110f3e1c7fSRyusuke Konishi 7128b94025cSRyusuke Konishi bh = __getblk(nilfs->ns_bdev, ri->ri_lsegs_start, nilfs->ns_blocksize); 7130f3e1c7fSRyusuke Konishi BUG_ON(!bh); 7140f3e1c7fSRyusuke Konishi memset(bh->b_data, 0, bh->b_size); 7150f3e1c7fSRyusuke Konishi set_buffer_dirty(bh); 7160f3e1c7fSRyusuke Konishi err = sync_dirty_buffer(bh); 7170f3e1c7fSRyusuke Konishi if (unlikely(err)) 7180f3e1c7fSRyusuke Konishi printk(KERN_WARNING 7190f3e1c7fSRyusuke Konishi "NILFS warning: buffer sync write failed during " 7200f3e1c7fSRyusuke Konishi "post-cleaning of recovery.\n"); 7210f3e1c7fSRyusuke Konishi brelse(bh); 7220f3e1c7fSRyusuke Konishi } 7230f3e1c7fSRyusuke Konishi 7240f3e1c7fSRyusuke Konishi /** 725aee5ce2fSRyusuke Konishi * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint 726aee5ce2fSRyusuke Konishi * @nilfs: nilfs object 727f7545144SRyusuke Konishi * @sb: super block instance 7280f3e1c7fSRyusuke Konishi * @ri: pointer to a nilfs_recovery_info struct to store search results. 7290f3e1c7fSRyusuke Konishi * 7300f3e1c7fSRyusuke Konishi * Return Value: On success, 0 is returned. On error, one of the following 7310f3e1c7fSRyusuke Konishi * negative error code is returned. 7320f3e1c7fSRyusuke Konishi * 7330f3e1c7fSRyusuke Konishi * %-EINVAL - Inconsistent filesystem state. 7340f3e1c7fSRyusuke Konishi * 7350f3e1c7fSRyusuke Konishi * %-EIO - I/O error 7360f3e1c7fSRyusuke Konishi * 7370f3e1c7fSRyusuke Konishi * %-ENOSPC - No space left on device (only in a panic state). 7380f3e1c7fSRyusuke Konishi * 7390f3e1c7fSRyusuke Konishi * %-ERESTARTSYS - Interrupted. 7400f3e1c7fSRyusuke Konishi * 7410f3e1c7fSRyusuke Konishi * %-ENOMEM - Insufficient memory available. 7420f3e1c7fSRyusuke Konishi */ 743aee5ce2fSRyusuke Konishi int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, 744f7545144SRyusuke Konishi struct super_block *sb, 7450f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 7460f3e1c7fSRyusuke Konishi { 7474d8d9293SRyusuke Konishi struct nilfs_root *root; 7480f3e1c7fSRyusuke Konishi int err; 7490f3e1c7fSRyusuke Konishi 7500f3e1c7fSRyusuke Konishi if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0) 7510f3e1c7fSRyusuke Konishi return 0; 7520f3e1c7fSRyusuke Konishi 753f7545144SRyusuke Konishi err = nilfs_attach_checkpoint(sb, ri->ri_cno, true, &root); 7540f3e1c7fSRyusuke Konishi if (unlikely(err)) { 7550f3e1c7fSRyusuke Konishi printk(KERN_ERR 7560f3e1c7fSRyusuke Konishi "NILFS: error loading the latest checkpoint.\n"); 7570f3e1c7fSRyusuke Konishi return err; 7580f3e1c7fSRyusuke Konishi } 7590f3e1c7fSRyusuke Konishi 760f7545144SRyusuke Konishi err = nilfs_do_roll_forward(nilfs, sb, root, ri); 7610f3e1c7fSRyusuke Konishi if (unlikely(err)) 7620f3e1c7fSRyusuke Konishi goto failed; 7630f3e1c7fSRyusuke Konishi 7640f3e1c7fSRyusuke Konishi if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) { 765f7545144SRyusuke Konishi err = nilfs_prepare_segment_for_recovery(nilfs, sb, ri); 7660f3e1c7fSRyusuke Konishi if (unlikely(err)) { 7670f3e1c7fSRyusuke Konishi printk(KERN_ERR "NILFS: Error preparing segments for " 7680f3e1c7fSRyusuke Konishi "recovery.\n"); 7690f3e1c7fSRyusuke Konishi goto failed; 7700f3e1c7fSRyusuke Konishi } 7710f3e1c7fSRyusuke Konishi 772f7545144SRyusuke Konishi err = nilfs_attach_log_writer(sb, root); 7730f3e1c7fSRyusuke Konishi if (unlikely(err)) 7740f3e1c7fSRyusuke Konishi goto failed; 7750f3e1c7fSRyusuke Konishi 7760f3e1c7fSRyusuke Konishi set_nilfs_discontinued(nilfs); 777f7545144SRyusuke Konishi err = nilfs_construct_segment(sb); 778f7545144SRyusuke Konishi nilfs_detach_log_writer(sb); 7790f3e1c7fSRyusuke Konishi 7800f3e1c7fSRyusuke Konishi if (unlikely(err)) { 7810f3e1c7fSRyusuke Konishi printk(KERN_ERR "NILFS: Oops! recovery failed. " 7820f3e1c7fSRyusuke Konishi "(err=%d)\n", err); 7830f3e1c7fSRyusuke Konishi goto failed; 7840f3e1c7fSRyusuke Konishi } 7850f3e1c7fSRyusuke Konishi 7868b94025cSRyusuke Konishi nilfs_finish_roll_forward(nilfs, ri); 7870f3e1c7fSRyusuke Konishi } 7880f3e1c7fSRyusuke Konishi 7890f3e1c7fSRyusuke Konishi failed: 7904d8d9293SRyusuke Konishi nilfs_put_root(root); 7910f3e1c7fSRyusuke Konishi return err; 7920f3e1c7fSRyusuke Konishi } 7930f3e1c7fSRyusuke Konishi 7940f3e1c7fSRyusuke Konishi /** 7950f3e1c7fSRyusuke Konishi * nilfs_search_super_root - search the latest valid super root 7960f3e1c7fSRyusuke Konishi * @nilfs: the_nilfs 7970f3e1c7fSRyusuke Konishi * @ri: pointer to a nilfs_recovery_info struct to store search results. 7980f3e1c7fSRyusuke Konishi * 7990f3e1c7fSRyusuke Konishi * nilfs_search_super_root() looks for the latest super-root from a partial 8000f3e1c7fSRyusuke Konishi * segment pointed by the superblock. It sets up struct the_nilfs through 8010f3e1c7fSRyusuke Konishi * this search. It fills nilfs_recovery_info (ri) required for recovery. 8020f3e1c7fSRyusuke Konishi * 8030f3e1c7fSRyusuke Konishi * Return Value: On success, 0 is returned. On error, one of the following 8040f3e1c7fSRyusuke Konishi * negative error code is returned. 8050f3e1c7fSRyusuke Konishi * 8060f3e1c7fSRyusuke Konishi * %-EINVAL - No valid segment found 8070f3e1c7fSRyusuke Konishi * 8080f3e1c7fSRyusuke Konishi * %-EIO - I/O error 8092d72b99eSRyusuke Konishi * 8102d72b99eSRyusuke Konishi * %-ENOMEM - Insufficient memory available. 8110f3e1c7fSRyusuke Konishi */ 8128b94025cSRyusuke Konishi int nilfs_search_super_root(struct the_nilfs *nilfs, 8130f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 8140f3e1c7fSRyusuke Konishi { 815354fa8beSRyusuke Konishi struct buffer_head *bh_sum = NULL; 8164f05028fSRyusuke Konishi struct nilfs_segment_summary *sum = NULL; 8170f3e1c7fSRyusuke Konishi sector_t pseg_start, pseg_end, sr_pseg_start = 0; 8180f3e1c7fSRyusuke Konishi sector_t seg_start, seg_end; /* range of full segment (block number) */ 819050b4142SRyusuke Konishi sector_t b, end; 82085655484SRyusuke Konishi unsigned long nblocks; 82185655484SRyusuke Konishi unsigned int flags; 8220f3e1c7fSRyusuke Konishi u64 seg_seq; 8230f3e1c7fSRyusuke Konishi __u64 segnum, nextnum = 0; 8240f3e1c7fSRyusuke Konishi __u64 cno; 8250f3e1c7fSRyusuke Konishi LIST_HEAD(segments); 8260f3e1c7fSRyusuke Konishi int empty_seg = 0, scan_newer = 0; 8270f3e1c7fSRyusuke Konishi int ret; 8280f3e1c7fSRyusuke Konishi 8290f3e1c7fSRyusuke Konishi pseg_start = nilfs->ns_last_pseg; 8300f3e1c7fSRyusuke Konishi seg_seq = nilfs->ns_last_seq; 8310f3e1c7fSRyusuke Konishi cno = nilfs->ns_last_cno; 8320f3e1c7fSRyusuke Konishi segnum = nilfs_get_segnum_of_block(nilfs, pseg_start); 8330f3e1c7fSRyusuke Konishi 8340f3e1c7fSRyusuke Konishi /* Calculate range of segment */ 8350f3e1c7fSRyusuke Konishi nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); 8360f3e1c7fSRyusuke Konishi 837050b4142SRyusuke Konishi /* Read ahead segment */ 838050b4142SRyusuke Konishi b = seg_start; 839050b4142SRyusuke Konishi while (b <= seg_end) 8408b94025cSRyusuke Konishi __breadahead(nilfs->ns_bdev, b++, nilfs->ns_blocksize); 841050b4142SRyusuke Konishi 8420f3e1c7fSRyusuke Konishi for (;;) { 843354fa8beSRyusuke Konishi brelse(bh_sum); 844354fa8beSRyusuke Konishi ret = NILFS_SEG_FAIL_IO; 845354fa8beSRyusuke Konishi bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum); 846354fa8beSRyusuke Konishi if (!bh_sum) 847354fa8beSRyusuke Konishi goto failed; 848354fa8beSRyusuke Konishi 849354fa8beSRyusuke Konishi ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum); 8500f3e1c7fSRyusuke Konishi if (ret) { 8510f3e1c7fSRyusuke Konishi if (ret == NILFS_SEG_FAIL_IO) 8520f3e1c7fSRyusuke Konishi goto failed; 8530f3e1c7fSRyusuke Konishi goto strayed; 8540f3e1c7fSRyusuke Konishi } 855354fa8beSRyusuke Konishi 85685655484SRyusuke Konishi nblocks = le32_to_cpu(sum->ss_nblocks); 85785655484SRyusuke Konishi pseg_end = pseg_start + nblocks - 1; 8580f3e1c7fSRyusuke Konishi if (unlikely(pseg_end > seg_end)) { 8590f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CONSISTENCY; 8600f3e1c7fSRyusuke Konishi goto strayed; 8610f3e1c7fSRyusuke Konishi } 8620f3e1c7fSRyusuke Konishi 8630f3e1c7fSRyusuke Konishi /* A valid partial segment */ 8640f3e1c7fSRyusuke Konishi ri->ri_pseg_start = pseg_start; 8650f3e1c7fSRyusuke Konishi ri->ri_seq = seg_seq; 8660f3e1c7fSRyusuke Konishi ri->ri_segnum = segnum; 86785655484SRyusuke Konishi nextnum = nilfs_get_segnum_of_block(nilfs, 86885655484SRyusuke Konishi le64_to_cpu(sum->ss_next)); 8690f3e1c7fSRyusuke Konishi ri->ri_nextnum = nextnum; 8700f3e1c7fSRyusuke Konishi empty_seg = 0; 8710f3e1c7fSRyusuke Konishi 87285655484SRyusuke Konishi flags = le16_to_cpu(sum->ss_flags); 87385655484SRyusuke Konishi if (!(flags & NILFS_SS_SR) && !scan_newer) { 874076a378bSRyusuke Konishi /* 875076a378bSRyusuke Konishi * This will never happen because a superblock 876076a378bSRyusuke Konishi * (last_segment) always points to a pseg with 877076a378bSRyusuke Konishi * a super root. 878076a378bSRyusuke Konishi */ 8790f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CONSISTENCY; 8800f3e1c7fSRyusuke Konishi goto failed; 8810f3e1c7fSRyusuke Konishi } 882050b4142SRyusuke Konishi 883050b4142SRyusuke Konishi if (pseg_start == seg_start) { 884050b4142SRyusuke Konishi nilfs_get_segment_range(nilfs, nextnum, &b, &end); 885050b4142SRyusuke Konishi while (b <= end) 8868b94025cSRyusuke Konishi __breadahead(nilfs->ns_bdev, b++, 8878b94025cSRyusuke Konishi nilfs->ns_blocksize); 888050b4142SRyusuke Konishi } 88985655484SRyusuke Konishi if (!(flags & NILFS_SS_SR)) { 89085655484SRyusuke Konishi if (!ri->ri_lsegs_start && (flags & NILFS_SS_LOGBGN)) { 8910f3e1c7fSRyusuke Konishi ri->ri_lsegs_start = pseg_start; 8920f3e1c7fSRyusuke Konishi ri->ri_lsegs_start_seq = seg_seq; 8930f3e1c7fSRyusuke Konishi } 89485655484SRyusuke Konishi if (flags & NILFS_SS_LOGEND) 8950f3e1c7fSRyusuke Konishi ri->ri_lsegs_end = pseg_start; 8960f3e1c7fSRyusuke Konishi goto try_next_pseg; 8970f3e1c7fSRyusuke Konishi } 8980f3e1c7fSRyusuke Konishi 8990f3e1c7fSRyusuke Konishi /* A valid super root was found. */ 9000f3e1c7fSRyusuke Konishi ri->ri_cno = cno++; 9010f3e1c7fSRyusuke Konishi ri->ri_super_root = pseg_end; 9020f3e1c7fSRyusuke Konishi ri->ri_lsegs_start = ri->ri_lsegs_end = 0; 9030f3e1c7fSRyusuke Konishi 9040f3e1c7fSRyusuke Konishi nilfs_dispose_segment_list(&segments); 90585655484SRyusuke Konishi sr_pseg_start = pseg_start; 90685655484SRyusuke Konishi nilfs->ns_pseg_offset = pseg_start + nblocks - seg_start; 9070f3e1c7fSRyusuke Konishi nilfs->ns_seg_seq = seg_seq; 9080f3e1c7fSRyusuke Konishi nilfs->ns_segnum = segnum; 9090f3e1c7fSRyusuke Konishi nilfs->ns_cno = cno; /* nilfs->ns_cno = ri->ri_cno + 1 */ 91085655484SRyusuke Konishi nilfs->ns_ctime = le64_to_cpu(sum->ss_create); 9110f3e1c7fSRyusuke Konishi nilfs->ns_nextnum = nextnum; 9120f3e1c7fSRyusuke Konishi 9130f3e1c7fSRyusuke Konishi if (scan_newer) 9140f3e1c7fSRyusuke Konishi ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED; 9152c2e52fcSRyusuke Konishi else { 9162c2e52fcSRyusuke Konishi if (nilfs->ns_mount_state & NILFS_VALID_FS) 9170f3e1c7fSRyusuke Konishi goto super_root_found; 9180f3e1c7fSRyusuke Konishi scan_newer = 1; 9192c2e52fcSRyusuke Konishi } 9200f3e1c7fSRyusuke Konishi 9210f3e1c7fSRyusuke Konishi try_next_pseg: 9220f3e1c7fSRyusuke Konishi /* Standing on a course, or met an inconsistent state */ 92385655484SRyusuke Konishi pseg_start += nblocks; 9240f3e1c7fSRyusuke Konishi if (pseg_start < seg_end) 9250f3e1c7fSRyusuke Konishi continue; 9260f3e1c7fSRyusuke Konishi goto feed_segment; 9270f3e1c7fSRyusuke Konishi 9280f3e1c7fSRyusuke Konishi strayed: 9290f3e1c7fSRyusuke Konishi /* Off the trail */ 9300f3e1c7fSRyusuke Konishi if (!scan_newer) 9310f3e1c7fSRyusuke Konishi /* 9320f3e1c7fSRyusuke Konishi * This can happen if a checkpoint was written without 9330f3e1c7fSRyusuke Konishi * barriers, or as a result of an I/O failure. 9340f3e1c7fSRyusuke Konishi */ 9350f3e1c7fSRyusuke Konishi goto failed; 9360f3e1c7fSRyusuke Konishi 9370f3e1c7fSRyusuke Konishi feed_segment: 9380f3e1c7fSRyusuke Konishi /* Looking to the next full segment */ 9390f3e1c7fSRyusuke Konishi if (empty_seg++) 9400f3e1c7fSRyusuke Konishi goto super_root_found; /* found a valid super root */ 9410f3e1c7fSRyusuke Konishi 942654137ddSRyusuke Konishi ret = nilfs_segment_list_add(&segments, segnum); 943654137ddSRyusuke Konishi if (unlikely(ret)) 9440f3e1c7fSRyusuke Konishi goto failed; 9450f3e1c7fSRyusuke Konishi 9460f3e1c7fSRyusuke Konishi seg_seq++; 9470f3e1c7fSRyusuke Konishi segnum = nextnum; 9480f3e1c7fSRyusuke Konishi nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); 9490f3e1c7fSRyusuke Konishi pseg_start = seg_start; 9500f3e1c7fSRyusuke Konishi } 9510f3e1c7fSRyusuke Konishi 9520f3e1c7fSRyusuke Konishi super_root_found: 9530f3e1c7fSRyusuke Konishi /* Updating pointers relating to the latest checkpoint */ 954354fa8beSRyusuke Konishi brelse(bh_sum); 9550935db74SRyusuke Konishi list_splice_tail(&segments, &ri->ri_used_segments); 9560f3e1c7fSRyusuke Konishi nilfs->ns_last_pseg = sr_pseg_start; 9570f3e1c7fSRyusuke Konishi nilfs->ns_last_seq = nilfs->ns_seg_seq; 9580f3e1c7fSRyusuke Konishi nilfs->ns_last_cno = ri->ri_cno; 9590f3e1c7fSRyusuke Konishi return 0; 9600f3e1c7fSRyusuke Konishi 9610f3e1c7fSRyusuke Konishi failed: 962354fa8beSRyusuke Konishi brelse(bh_sum); 9630f3e1c7fSRyusuke Konishi nilfs_dispose_segment_list(&segments); 9640f3e1c7fSRyusuke Konishi return (ret < 0) ? ret : nilfs_warn_segment_error(ret); 9650f3e1c7fSRyusuke Konishi } 966