1ae98043fSRyusuke Konishi // SPDX-License-Identifier: GPL-2.0+ 20f3e1c7fSRyusuke Konishi /* 30f3e1c7fSRyusuke Konishi * recovery.c - NILFS recovery logic 40f3e1c7fSRyusuke Konishi * 50f3e1c7fSRyusuke Konishi * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation. 60f3e1c7fSRyusuke Konishi * 74b420ab4SRyusuke Konishi * Written by Ryusuke Konishi. 80f3e1c7fSRyusuke Konishi */ 90f3e1c7fSRyusuke Konishi 100f3e1c7fSRyusuke Konishi #include <linux/buffer_head.h> 110f3e1c7fSRyusuke Konishi #include <linux/blkdev.h> 120f3e1c7fSRyusuke Konishi #include <linux/swap.h> 135a0e3ad6STejun Heo #include <linux/slab.h> 140f3e1c7fSRyusuke Konishi #include <linux/crc32.h> 150f3e1c7fSRyusuke Konishi #include "nilfs.h" 160f3e1c7fSRyusuke Konishi #include "segment.h" 170f3e1c7fSRyusuke Konishi #include "sufile.h" 180f3e1c7fSRyusuke Konishi #include "page.h" 190f3e1c7fSRyusuke Konishi #include "segbuf.h" 200f3e1c7fSRyusuke Konishi 210f3e1c7fSRyusuke Konishi /* 220f3e1c7fSRyusuke Konishi * Segment check result 230f3e1c7fSRyusuke Konishi */ 240f3e1c7fSRyusuke Konishi enum { 250f3e1c7fSRyusuke Konishi NILFS_SEG_VALID, 260f3e1c7fSRyusuke Konishi NILFS_SEG_NO_SUPER_ROOT, 270f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_IO, 280f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_MAGIC, 290f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_SEQ, 300f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT, 310f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_CHECKSUM_FULL, 320f3e1c7fSRyusuke Konishi NILFS_SEG_FAIL_CONSISTENCY, 330f3e1c7fSRyusuke Konishi }; 340f3e1c7fSRyusuke Konishi 350f3e1c7fSRyusuke Konishi /* work structure for recovery */ 360f3e1c7fSRyusuke Konishi struct nilfs_recovery_block { 37076a378bSRyusuke Konishi ino_t ino; /* 38076a378bSRyusuke Konishi * Inode number of the file that this block 39076a378bSRyusuke Konishi * belongs to 40076a378bSRyusuke Konishi */ 410f3e1c7fSRyusuke Konishi sector_t blocknr; /* block number */ 420f3e1c7fSRyusuke Konishi __u64 vblocknr; /* virtual block number */ 430f3e1c7fSRyusuke Konishi unsigned long blkoff; /* File offset of the data block (per block) */ 440f3e1c7fSRyusuke Konishi struct list_head list; 450f3e1c7fSRyusuke Konishi }; 460f3e1c7fSRyusuke Konishi 470f3e1c7fSRyusuke Konishi 48feee880fSRyusuke Konishi static int nilfs_warn_segment_error(struct super_block *sb, int err) 490f3e1c7fSRyusuke Konishi { 50feee880fSRyusuke Konishi const char *msg = NULL; 51feee880fSRyusuke Konishi 520f3e1c7fSRyusuke Konishi switch (err) { 530f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_IO: 54a1d0747aSJoe Perches nilfs_err(sb, "I/O error reading segment"); 550f3e1c7fSRyusuke Konishi return -EIO; 560f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_MAGIC: 57feee880fSRyusuke Konishi msg = "Magic number mismatch"; 580f3e1c7fSRyusuke Konishi break; 590f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_SEQ: 60feee880fSRyusuke Konishi msg = "Sequence number mismatch"; 610f3e1c7fSRyusuke Konishi break; 620f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT: 63feee880fSRyusuke Konishi msg = "Checksum error in super root"; 640f3e1c7fSRyusuke Konishi break; 650f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_CHECKSUM_FULL: 66feee880fSRyusuke Konishi msg = "Checksum error in segment payload"; 670f3e1c7fSRyusuke Konishi break; 680f3e1c7fSRyusuke Konishi case NILFS_SEG_FAIL_CONSISTENCY: 69feee880fSRyusuke Konishi msg = "Inconsistency found"; 700f3e1c7fSRyusuke Konishi break; 710f3e1c7fSRyusuke Konishi case NILFS_SEG_NO_SUPER_ROOT: 72feee880fSRyusuke Konishi msg = "No super root in the last segment"; 730f3e1c7fSRyusuke Konishi break; 74feee880fSRyusuke Konishi default: 75a1d0747aSJoe Perches nilfs_err(sb, "unrecognized segment error %d", err); 76feee880fSRyusuke Konishi return -EINVAL; 770f3e1c7fSRyusuke Konishi } 78a1d0747aSJoe Perches nilfs_warn(sb, "invalid segment: %s", msg); 790f3e1c7fSRyusuke Konishi return -EINVAL; 800f3e1c7fSRyusuke Konishi } 810f3e1c7fSRyusuke Konishi 820f3e1c7fSRyusuke Konishi /** 838b94025cSRyusuke Konishi * nilfs_compute_checksum - compute checksum of blocks continuously 848b94025cSRyusuke Konishi * @nilfs: nilfs object 850f3e1c7fSRyusuke Konishi * @bhs: buffer head of start block 860f3e1c7fSRyusuke Konishi * @sum: place to store result 870f3e1c7fSRyusuke Konishi * @offset: offset bytes in the first block 880f3e1c7fSRyusuke Konishi * @check_bytes: number of bytes to be checked 890f3e1c7fSRyusuke Konishi * @start: DBN of start block 900f3e1c7fSRyusuke Konishi * @nblock: number of blocks to be checked 910f3e1c7fSRyusuke Konishi */ 928b94025cSRyusuke Konishi static int nilfs_compute_checksum(struct the_nilfs *nilfs, 938b94025cSRyusuke Konishi struct buffer_head *bhs, u32 *sum, 948b94025cSRyusuke Konishi unsigned long offset, u64 check_bytes, 950f3e1c7fSRyusuke Konishi sector_t start, unsigned long nblock) 960f3e1c7fSRyusuke Konishi { 978b94025cSRyusuke Konishi unsigned int blocksize = nilfs->ns_blocksize; 980f3e1c7fSRyusuke Konishi unsigned long size; 990f3e1c7fSRyusuke Konishi u32 crc; 1000f3e1c7fSRyusuke Konishi 1010f3e1c7fSRyusuke Konishi BUG_ON(offset >= blocksize); 1020f3e1c7fSRyusuke Konishi check_bytes -= offset; 1030f3e1c7fSRyusuke Konishi size = min_t(u64, check_bytes, blocksize - offset); 1048b94025cSRyusuke Konishi crc = crc32_le(nilfs->ns_crc_seed, 1050f3e1c7fSRyusuke Konishi (unsigned char *)bhs->b_data + offset, size); 1060f3e1c7fSRyusuke Konishi if (--nblock > 0) { 1070f3e1c7fSRyusuke Konishi do { 1088b94025cSRyusuke Konishi struct buffer_head *bh; 1098b94025cSRyusuke Konishi 1108b94025cSRyusuke Konishi bh = __bread(nilfs->ns_bdev, ++start, blocksize); 1110f3e1c7fSRyusuke Konishi if (!bh) 1120f3e1c7fSRyusuke Konishi return -EIO; 1130f3e1c7fSRyusuke Konishi check_bytes -= size; 1140f3e1c7fSRyusuke Konishi size = min_t(u64, check_bytes, blocksize); 1150f3e1c7fSRyusuke Konishi crc = crc32_le(crc, bh->b_data, size); 1160f3e1c7fSRyusuke Konishi brelse(bh); 1170f3e1c7fSRyusuke Konishi } while (--nblock > 0); 1180f3e1c7fSRyusuke Konishi } 1190f3e1c7fSRyusuke Konishi *sum = crc; 1200f3e1c7fSRyusuke Konishi return 0; 1210f3e1c7fSRyusuke Konishi } 1220f3e1c7fSRyusuke Konishi 1230f3e1c7fSRyusuke Konishi /** 1240f3e1c7fSRyusuke Konishi * nilfs_read_super_root_block - read super root block 1258b94025cSRyusuke Konishi * @nilfs: nilfs object 1260f3e1c7fSRyusuke Konishi * @sr_block: disk block number of the super root block 1270f3e1c7fSRyusuke Konishi * @pbh: address of a buffer_head pointer to return super root buffer 1280f3e1c7fSRyusuke Konishi * @check: CRC check flag 1290f3e1c7fSRyusuke Konishi */ 1308b94025cSRyusuke Konishi int nilfs_read_super_root_block(struct the_nilfs *nilfs, sector_t sr_block, 1310f3e1c7fSRyusuke Konishi struct buffer_head **pbh, int check) 1320f3e1c7fSRyusuke Konishi { 1330f3e1c7fSRyusuke Konishi struct buffer_head *bh_sr; 1340f3e1c7fSRyusuke Konishi struct nilfs_super_root *sr; 1350f3e1c7fSRyusuke Konishi u32 crc; 1360f3e1c7fSRyusuke Konishi int ret; 1370f3e1c7fSRyusuke Konishi 1380f3e1c7fSRyusuke Konishi *pbh = NULL; 1398b94025cSRyusuke Konishi bh_sr = __bread(nilfs->ns_bdev, sr_block, nilfs->ns_blocksize); 1400f3e1c7fSRyusuke Konishi if (unlikely(!bh_sr)) { 1410f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_IO; 1420f3e1c7fSRyusuke Konishi goto failed; 1430f3e1c7fSRyusuke Konishi } 1440f3e1c7fSRyusuke Konishi 1450f3e1c7fSRyusuke Konishi sr = (struct nilfs_super_root *)bh_sr->b_data; 1460f3e1c7fSRyusuke Konishi if (check) { 1470c6c44cbSRyusuke Konishi unsigned int bytes = le16_to_cpu(sr->sr_bytes); 1480f3e1c7fSRyusuke Konishi 1498b94025cSRyusuke Konishi if (bytes == 0 || bytes > nilfs->ns_blocksize) { 1500f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT; 1510f3e1c7fSRyusuke Konishi goto failed_bh; 1520f3e1c7fSRyusuke Konishi } 1538b94025cSRyusuke Konishi if (nilfs_compute_checksum( 1548b94025cSRyusuke Konishi nilfs, bh_sr, &crc, sizeof(sr->sr_sum), bytes, 1558b94025cSRyusuke Konishi sr_block, 1)) { 1560f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_IO; 1570f3e1c7fSRyusuke Konishi goto failed_bh; 1580f3e1c7fSRyusuke Konishi } 1590f3e1c7fSRyusuke Konishi if (crc != le32_to_cpu(sr->sr_sum)) { 1600f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT; 1610f3e1c7fSRyusuke Konishi goto failed_bh; 1620f3e1c7fSRyusuke Konishi } 1630f3e1c7fSRyusuke Konishi } 1640f3e1c7fSRyusuke Konishi *pbh = bh_sr; 1650f3e1c7fSRyusuke Konishi return 0; 1660f3e1c7fSRyusuke Konishi 1670f3e1c7fSRyusuke Konishi failed_bh: 1680f3e1c7fSRyusuke Konishi brelse(bh_sr); 1690f3e1c7fSRyusuke Konishi 1700f3e1c7fSRyusuke Konishi failed: 171feee880fSRyusuke Konishi return nilfs_warn_segment_error(nilfs->ns_sb, ret); 1720f3e1c7fSRyusuke Konishi } 1730f3e1c7fSRyusuke Konishi 1740f3e1c7fSRyusuke Konishi /** 175354fa8beSRyusuke Konishi * nilfs_read_log_header - read summary header of the specified log 1768b94025cSRyusuke Konishi * @nilfs: nilfs object 177354fa8beSRyusuke Konishi * @start_blocknr: start block number of the log 178354fa8beSRyusuke Konishi * @sum: pointer to return segment summary structure 1790f3e1c7fSRyusuke Konishi */ 180354fa8beSRyusuke Konishi static struct buffer_head * 181354fa8beSRyusuke Konishi nilfs_read_log_header(struct the_nilfs *nilfs, sector_t start_blocknr, 182354fa8beSRyusuke Konishi struct nilfs_segment_summary **sum) 1830f3e1c7fSRyusuke Konishi { 1840f3e1c7fSRyusuke Konishi struct buffer_head *bh_sum; 185354fa8beSRyusuke Konishi 186354fa8beSRyusuke Konishi bh_sum = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize); 187354fa8beSRyusuke Konishi if (bh_sum) 188354fa8beSRyusuke Konishi *sum = (struct nilfs_segment_summary *)bh_sum->b_data; 189354fa8beSRyusuke Konishi return bh_sum; 190354fa8beSRyusuke Konishi } 191354fa8beSRyusuke Konishi 192354fa8beSRyusuke Konishi /** 193354fa8beSRyusuke Konishi * nilfs_validate_log - verify consistency of log 194354fa8beSRyusuke Konishi * @nilfs: nilfs object 195354fa8beSRyusuke Konishi * @seg_seq: sequence number of segment 196354fa8beSRyusuke Konishi * @bh_sum: buffer head of summary block 197354fa8beSRyusuke Konishi * @sum: segment summary struct 198354fa8beSRyusuke Konishi */ 199354fa8beSRyusuke Konishi static int nilfs_validate_log(struct the_nilfs *nilfs, u64 seg_seq, 200354fa8beSRyusuke Konishi struct buffer_head *bh_sum, 201354fa8beSRyusuke Konishi struct nilfs_segment_summary *sum) 202354fa8beSRyusuke Konishi { 20303f29365SJiro SEKIBA unsigned long nblock; 20403f29365SJiro SEKIBA u32 crc; 205354fa8beSRyusuke Konishi int ret; 2060f3e1c7fSRyusuke Konishi 207354fa8beSRyusuke Konishi ret = NILFS_SEG_FAIL_MAGIC; 208354fa8beSRyusuke Konishi if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC) 2090f3e1c7fSRyusuke Konishi goto out; 2100f3e1c7fSRyusuke Konishi 2110f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_SEQ; 212354fa8beSRyusuke Konishi if (le64_to_cpu(sum->ss_seq) != seg_seq) 213354fa8beSRyusuke Konishi goto out; 2140f3e1c7fSRyusuke Konishi 215354fa8beSRyusuke Konishi nblock = le32_to_cpu(sum->ss_nblocks); 2160f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CONSISTENCY; 217354fa8beSRyusuke Konishi if (unlikely(nblock == 0 || nblock > nilfs->ns_blocks_per_segment)) 218354fa8beSRyusuke Konishi /* This limits the number of blocks read in the CRC check */ 219354fa8beSRyusuke Konishi goto out; 220354fa8beSRyusuke Konishi 221354fa8beSRyusuke Konishi ret = NILFS_SEG_FAIL_IO; 2228b94025cSRyusuke Konishi if (nilfs_compute_checksum(nilfs, bh_sum, &crc, sizeof(sum->ss_datasum), 2238b94025cSRyusuke Konishi ((u64)nblock << nilfs->ns_blocksize_bits), 224354fa8beSRyusuke Konishi bh_sum->b_blocknr, nblock)) 225354fa8beSRyusuke Konishi goto out; 226354fa8beSRyusuke Konishi 22703f29365SJiro SEKIBA ret = NILFS_SEG_FAIL_CHECKSUM_FULL; 228354fa8beSRyusuke Konishi if (crc != le32_to_cpu(sum->ss_datasum)) 229354fa8beSRyusuke Konishi goto out; 230354fa8beSRyusuke Konishi ret = 0; 2310f3e1c7fSRyusuke Konishi out: 2320f3e1c7fSRyusuke Konishi return ret; 2330f3e1c7fSRyusuke Konishi } 2340f3e1c7fSRyusuke Konishi 2358b94025cSRyusuke Konishi /** 2368b94025cSRyusuke Konishi * nilfs_read_summary_info - read an item on summary blocks of a log 2378b94025cSRyusuke Konishi * @nilfs: nilfs object 2388b94025cSRyusuke Konishi * @pbh: the current buffer head on summary blocks [in, out] 2398b94025cSRyusuke Konishi * @offset: the current byte offset on summary blocks [in, out] 2408b94025cSRyusuke Konishi * @bytes: byte size of the item to be read 2418b94025cSRyusuke Konishi */ 2428b94025cSRyusuke Konishi static void *nilfs_read_summary_info(struct the_nilfs *nilfs, 2438b94025cSRyusuke Konishi struct buffer_head **pbh, 2440f3e1c7fSRyusuke Konishi unsigned int *offset, unsigned int bytes) 2450f3e1c7fSRyusuke Konishi { 2460f3e1c7fSRyusuke Konishi void *ptr; 2470f3e1c7fSRyusuke Konishi sector_t blocknr; 2480f3e1c7fSRyusuke Konishi 2490f3e1c7fSRyusuke Konishi BUG_ON((*pbh)->b_size < *offset); 2500f3e1c7fSRyusuke Konishi if (bytes > (*pbh)->b_size - *offset) { 2510f3e1c7fSRyusuke Konishi blocknr = (*pbh)->b_blocknr; 2520f3e1c7fSRyusuke Konishi brelse(*pbh); 2538b94025cSRyusuke Konishi *pbh = __bread(nilfs->ns_bdev, blocknr + 1, 2548b94025cSRyusuke Konishi nilfs->ns_blocksize); 2550f3e1c7fSRyusuke Konishi if (unlikely(!*pbh)) 2560f3e1c7fSRyusuke Konishi return NULL; 2570f3e1c7fSRyusuke Konishi *offset = 0; 2580f3e1c7fSRyusuke Konishi } 2590f3e1c7fSRyusuke Konishi ptr = (*pbh)->b_data + *offset; 2600f3e1c7fSRyusuke Konishi *offset += bytes; 2610f3e1c7fSRyusuke Konishi return ptr; 2620f3e1c7fSRyusuke Konishi } 2630f3e1c7fSRyusuke Konishi 2648b94025cSRyusuke Konishi /** 2658b94025cSRyusuke Konishi * nilfs_skip_summary_info - skip items on summary blocks of a log 2668b94025cSRyusuke Konishi * @nilfs: nilfs object 2678b94025cSRyusuke Konishi * @pbh: the current buffer head on summary blocks [in, out] 2688b94025cSRyusuke Konishi * @offset: the current byte offset on summary blocks [in, out] 2698b94025cSRyusuke Konishi * @bytes: byte size of the item to be skipped 2708b94025cSRyusuke Konishi * @count: number of items to be skipped 2718b94025cSRyusuke Konishi */ 2728b94025cSRyusuke Konishi static void nilfs_skip_summary_info(struct the_nilfs *nilfs, 2738b94025cSRyusuke Konishi struct buffer_head **pbh, 2740f3e1c7fSRyusuke Konishi unsigned int *offset, unsigned int bytes, 2750f3e1c7fSRyusuke Konishi unsigned long count) 2760f3e1c7fSRyusuke Konishi { 2770f3e1c7fSRyusuke Konishi unsigned int rest_item_in_current_block 2780f3e1c7fSRyusuke Konishi = ((*pbh)->b_size - *offset) / bytes; 2790f3e1c7fSRyusuke Konishi 2800f3e1c7fSRyusuke Konishi if (count <= rest_item_in_current_block) { 2810f3e1c7fSRyusuke Konishi *offset += bytes * count; 2820f3e1c7fSRyusuke Konishi } else { 2830f3e1c7fSRyusuke Konishi sector_t blocknr = (*pbh)->b_blocknr; 2840f3e1c7fSRyusuke Konishi unsigned int nitem_per_block = (*pbh)->b_size / bytes; 2850f3e1c7fSRyusuke Konishi unsigned int bcnt; 2860f3e1c7fSRyusuke Konishi 2870f3e1c7fSRyusuke Konishi count -= rest_item_in_current_block; 2880f3e1c7fSRyusuke Konishi bcnt = DIV_ROUND_UP(count, nitem_per_block); 2890f3e1c7fSRyusuke Konishi *offset = bytes * (count - (bcnt - 1) * nitem_per_block); 2900f3e1c7fSRyusuke Konishi 2910f3e1c7fSRyusuke Konishi brelse(*pbh); 2928b94025cSRyusuke Konishi *pbh = __bread(nilfs->ns_bdev, blocknr + bcnt, 2938b94025cSRyusuke Konishi nilfs->ns_blocksize); 2940f3e1c7fSRyusuke Konishi } 2950f3e1c7fSRyusuke Konishi } 2960f3e1c7fSRyusuke Konishi 2978b94025cSRyusuke Konishi /** 2988b94025cSRyusuke Konishi * nilfs_scan_dsync_log - get block information of a log written for data sync 2998b94025cSRyusuke Konishi * @nilfs: nilfs object 3008b94025cSRyusuke Konishi * @start_blocknr: start block number of the log 30185655484SRyusuke Konishi * @sum: log summary information 3028b94025cSRyusuke Konishi * @head: list head to add nilfs_recovery_block struct 3038b94025cSRyusuke Konishi */ 3048b94025cSRyusuke Konishi static int nilfs_scan_dsync_log(struct the_nilfs *nilfs, sector_t start_blocknr, 30585655484SRyusuke Konishi struct nilfs_segment_summary *sum, 3060f3e1c7fSRyusuke Konishi struct list_head *head) 3070f3e1c7fSRyusuke Konishi { 3080f3e1c7fSRyusuke Konishi struct buffer_head *bh; 3090f3e1c7fSRyusuke Konishi unsigned int offset; 31085655484SRyusuke Konishi u32 nfinfo, sumbytes; 31185655484SRyusuke Konishi sector_t blocknr; 3120f3e1c7fSRyusuke Konishi ino_t ino; 3130f3e1c7fSRyusuke Konishi int err = -EIO; 3140f3e1c7fSRyusuke Konishi 31585655484SRyusuke Konishi nfinfo = le32_to_cpu(sum->ss_nfinfo); 3160f3e1c7fSRyusuke Konishi if (!nfinfo) 3170f3e1c7fSRyusuke Konishi return 0; 3180f3e1c7fSRyusuke Konishi 31985655484SRyusuke Konishi sumbytes = le32_to_cpu(sum->ss_sumbytes); 32085655484SRyusuke Konishi blocknr = start_blocknr + DIV_ROUND_UP(sumbytes, nilfs->ns_blocksize); 3218b94025cSRyusuke Konishi bh = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize); 3220f3e1c7fSRyusuke Konishi if (unlikely(!bh)) 3230f3e1c7fSRyusuke Konishi goto out; 3240f3e1c7fSRyusuke Konishi 32585655484SRyusuke Konishi offset = le16_to_cpu(sum->ss_bytes); 3260f3e1c7fSRyusuke Konishi for (;;) { 3270f3e1c7fSRyusuke Konishi unsigned long nblocks, ndatablk, nnodeblk; 3280f3e1c7fSRyusuke Konishi struct nilfs_finfo *finfo; 3290f3e1c7fSRyusuke Konishi 3308b94025cSRyusuke Konishi finfo = nilfs_read_summary_info(nilfs, &bh, &offset, 3318b94025cSRyusuke Konishi sizeof(*finfo)); 3320f3e1c7fSRyusuke Konishi if (unlikely(!finfo)) 3330f3e1c7fSRyusuke Konishi goto out; 3340f3e1c7fSRyusuke Konishi 3350f3e1c7fSRyusuke Konishi ino = le64_to_cpu(finfo->fi_ino); 3360f3e1c7fSRyusuke Konishi nblocks = le32_to_cpu(finfo->fi_nblocks); 3370f3e1c7fSRyusuke Konishi ndatablk = le32_to_cpu(finfo->fi_ndatablk); 3380f3e1c7fSRyusuke Konishi nnodeblk = nblocks - ndatablk; 3390f3e1c7fSRyusuke Konishi 3400f3e1c7fSRyusuke Konishi while (ndatablk-- > 0) { 3410f3e1c7fSRyusuke Konishi struct nilfs_recovery_block *rb; 3420f3e1c7fSRyusuke Konishi struct nilfs_binfo_v *binfo; 3430f3e1c7fSRyusuke Konishi 3448b94025cSRyusuke Konishi binfo = nilfs_read_summary_info(nilfs, &bh, &offset, 3450f3e1c7fSRyusuke Konishi sizeof(*binfo)); 3460f3e1c7fSRyusuke Konishi if (unlikely(!binfo)) 3470f3e1c7fSRyusuke Konishi goto out; 3480f3e1c7fSRyusuke Konishi 3490f3e1c7fSRyusuke Konishi rb = kmalloc(sizeof(*rb), GFP_NOFS); 3500f3e1c7fSRyusuke Konishi if (unlikely(!rb)) { 3510f3e1c7fSRyusuke Konishi err = -ENOMEM; 3520f3e1c7fSRyusuke Konishi goto out; 3530f3e1c7fSRyusuke Konishi } 3540f3e1c7fSRyusuke Konishi rb->ino = ino; 3550f3e1c7fSRyusuke Konishi rb->blocknr = blocknr++; 3560f3e1c7fSRyusuke Konishi rb->vblocknr = le64_to_cpu(binfo->bi_vblocknr); 3570f3e1c7fSRyusuke Konishi rb->blkoff = le64_to_cpu(binfo->bi_blkoff); 3580f3e1c7fSRyusuke Konishi /* INIT_LIST_HEAD(&rb->list); */ 3590f3e1c7fSRyusuke Konishi list_add_tail(&rb->list, head); 3600f3e1c7fSRyusuke Konishi } 3610f3e1c7fSRyusuke Konishi if (--nfinfo == 0) 3620f3e1c7fSRyusuke Konishi break; 3638b94025cSRyusuke Konishi blocknr += nnodeblk; /* always 0 for data sync logs */ 3648b94025cSRyusuke Konishi nilfs_skip_summary_info(nilfs, &bh, &offset, sizeof(__le64), 3650f3e1c7fSRyusuke Konishi nnodeblk); 3660f3e1c7fSRyusuke Konishi if (unlikely(!bh)) 3670f3e1c7fSRyusuke Konishi goto out; 3680f3e1c7fSRyusuke Konishi } 3690f3e1c7fSRyusuke Konishi err = 0; 3700f3e1c7fSRyusuke Konishi out: 3710f3e1c7fSRyusuke Konishi brelse(bh); /* brelse(NULL) is just ignored */ 3720f3e1c7fSRyusuke Konishi return err; 3730f3e1c7fSRyusuke Konishi } 3740f3e1c7fSRyusuke Konishi 3750f3e1c7fSRyusuke Konishi static void dispose_recovery_list(struct list_head *head) 3760f3e1c7fSRyusuke Konishi { 3770f3e1c7fSRyusuke Konishi while (!list_empty(head)) { 3780cc12838SRyusuke Konishi struct nilfs_recovery_block *rb; 3790cc12838SRyusuke Konishi 3800cc12838SRyusuke Konishi rb = list_first_entry(head, struct nilfs_recovery_block, list); 3810f3e1c7fSRyusuke Konishi list_del(&rb->list); 3820f3e1c7fSRyusuke Konishi kfree(rb); 3830f3e1c7fSRyusuke Konishi } 3840f3e1c7fSRyusuke Konishi } 3850f3e1c7fSRyusuke Konishi 386654137ddSRyusuke Konishi struct nilfs_segment_entry { 387654137ddSRyusuke Konishi struct list_head list; 388654137ddSRyusuke Konishi __u64 segnum; 389654137ddSRyusuke Konishi }; 390654137ddSRyusuke Konishi 391654137ddSRyusuke Konishi static int nilfs_segment_list_add(struct list_head *head, __u64 segnum) 392654137ddSRyusuke Konishi { 393654137ddSRyusuke Konishi struct nilfs_segment_entry *ent = kmalloc(sizeof(*ent), GFP_NOFS); 394654137ddSRyusuke Konishi 395654137ddSRyusuke Konishi if (unlikely(!ent)) 396654137ddSRyusuke Konishi return -ENOMEM; 397654137ddSRyusuke Konishi 398654137ddSRyusuke Konishi ent->segnum = segnum; 399654137ddSRyusuke Konishi INIT_LIST_HEAD(&ent->list); 400654137ddSRyusuke Konishi list_add_tail(&ent->list, head); 401654137ddSRyusuke Konishi return 0; 402654137ddSRyusuke Konishi } 403654137ddSRyusuke Konishi 4040f3e1c7fSRyusuke Konishi void nilfs_dispose_segment_list(struct list_head *head) 4050f3e1c7fSRyusuke Konishi { 4060f3e1c7fSRyusuke Konishi while (!list_empty(head)) { 4070cc12838SRyusuke Konishi struct nilfs_segment_entry *ent; 4080cc12838SRyusuke Konishi 4090cc12838SRyusuke Konishi ent = list_first_entry(head, struct nilfs_segment_entry, list); 4100f3e1c7fSRyusuke Konishi list_del(&ent->list); 411654137ddSRyusuke Konishi kfree(ent); 4120f3e1c7fSRyusuke Konishi } 4130f3e1c7fSRyusuke Konishi } 4140f3e1c7fSRyusuke Konishi 4150f3e1c7fSRyusuke Konishi static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, 416f7545144SRyusuke Konishi struct super_block *sb, 4170f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 4180f3e1c7fSRyusuke Konishi { 4190f3e1c7fSRyusuke Konishi struct list_head *head = &ri->ri_used_segments; 4200f3e1c7fSRyusuke Konishi struct nilfs_segment_entry *ent, *n; 4210f3e1c7fSRyusuke Konishi struct inode *sufile = nilfs->ns_sufile; 4220f3e1c7fSRyusuke Konishi __u64 segnum[4]; 4230f3e1c7fSRyusuke Konishi int err; 4240f3e1c7fSRyusuke Konishi int i; 4250f3e1c7fSRyusuke Konishi 4260f3e1c7fSRyusuke Konishi segnum[0] = nilfs->ns_segnum; 4270f3e1c7fSRyusuke Konishi segnum[1] = nilfs->ns_nextnum; 4280f3e1c7fSRyusuke Konishi segnum[2] = ri->ri_segnum; 4290f3e1c7fSRyusuke Konishi segnum[3] = ri->ri_nextnum; 4300f3e1c7fSRyusuke Konishi 4310f3e1c7fSRyusuke Konishi /* 4320f3e1c7fSRyusuke Konishi * Releasing the next segment of the latest super root. 4330f3e1c7fSRyusuke Konishi * The next segment is invalidated by this recovery. 4340f3e1c7fSRyusuke Konishi */ 4350f3e1c7fSRyusuke Konishi err = nilfs_sufile_free(sufile, segnum[1]); 4360f3e1c7fSRyusuke Konishi if (unlikely(err)) 4370f3e1c7fSRyusuke Konishi goto failed; 4380f3e1c7fSRyusuke Konishi 4390f3e1c7fSRyusuke Konishi for (i = 1; i < 4; i++) { 440654137ddSRyusuke Konishi err = nilfs_segment_list_add(head, segnum[i]); 441654137ddSRyusuke Konishi if (unlikely(err)) 4420f3e1c7fSRyusuke Konishi goto failed; 4430f3e1c7fSRyusuke Konishi } 4440f3e1c7fSRyusuke Konishi 4450f3e1c7fSRyusuke Konishi /* 4460f3e1c7fSRyusuke Konishi * Collecting segments written after the latest super root. 4472c2e52fcSRyusuke Konishi * These are marked dirty to avoid being reallocated in the next write. 4480f3e1c7fSRyusuke Konishi */ 4490f3e1c7fSRyusuke Konishi list_for_each_entry_safe(ent, n, head, list) { 450c85399c2SRyusuke Konishi if (ent->segnum != segnum[0]) { 451c85399c2SRyusuke Konishi err = nilfs_sufile_scrap(sufile, ent->segnum); 4520f3e1c7fSRyusuke Konishi if (unlikely(err)) 4530f3e1c7fSRyusuke Konishi goto failed; 4542c2e52fcSRyusuke Konishi } 4550f3e1c7fSRyusuke Konishi list_del(&ent->list); 456654137ddSRyusuke Konishi kfree(ent); 4570f3e1c7fSRyusuke Konishi } 4580f3e1c7fSRyusuke Konishi 4590f3e1c7fSRyusuke Konishi /* Allocate new segments for recovery */ 4600f3e1c7fSRyusuke Konishi err = nilfs_sufile_alloc(sufile, &segnum[0]); 4610f3e1c7fSRyusuke Konishi if (unlikely(err)) 4620f3e1c7fSRyusuke Konishi goto failed; 4630f3e1c7fSRyusuke Konishi 4640f3e1c7fSRyusuke Konishi nilfs->ns_pseg_offset = 0; 4650f3e1c7fSRyusuke Konishi nilfs->ns_seg_seq = ri->ri_seq + 2; 4660f3e1c7fSRyusuke Konishi nilfs->ns_nextnum = nilfs->ns_segnum = segnum[0]; 4670f3e1c7fSRyusuke Konishi 4680f3e1c7fSRyusuke Konishi failed: 4690f3e1c7fSRyusuke Konishi /* No need to recover sufile because it will be destroyed on error */ 4700f3e1c7fSRyusuke Konishi return err; 4710f3e1c7fSRyusuke Konishi } 4720f3e1c7fSRyusuke Konishi 4738b94025cSRyusuke Konishi static int nilfs_recovery_copy_block(struct the_nilfs *nilfs, 4740f3e1c7fSRyusuke Konishi struct nilfs_recovery_block *rb, 4750f3e1c7fSRyusuke Konishi struct page *page) 4760f3e1c7fSRyusuke Konishi { 4770f3e1c7fSRyusuke Konishi struct buffer_head *bh_org; 4780f3e1c7fSRyusuke Konishi void *kaddr; 4790f3e1c7fSRyusuke Konishi 4808b94025cSRyusuke Konishi bh_org = __bread(nilfs->ns_bdev, rb->blocknr, nilfs->ns_blocksize); 4810f3e1c7fSRyusuke Konishi if (unlikely(!bh_org)) 4820f3e1c7fSRyusuke Konishi return -EIO; 4830f3e1c7fSRyusuke Konishi 4847b9c0976SCong Wang kaddr = kmap_atomic(page); 4850f3e1c7fSRyusuke Konishi memcpy(kaddr + bh_offset(bh_org), bh_org->b_data, bh_org->b_size); 4867b9c0976SCong Wang kunmap_atomic(kaddr); 4870f3e1c7fSRyusuke Konishi brelse(bh_org); 4880f3e1c7fSRyusuke Konishi return 0; 4890f3e1c7fSRyusuke Konishi } 4900f3e1c7fSRyusuke Konishi 4918b94025cSRyusuke Konishi static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, 492f7545144SRyusuke Konishi struct super_block *sb, 4934d8d9293SRyusuke Konishi struct nilfs_root *root, 4940f3e1c7fSRyusuke Konishi struct list_head *head, 4950f3e1c7fSRyusuke Konishi unsigned long *nr_salvaged_blocks) 4960f3e1c7fSRyusuke Konishi { 4970f3e1c7fSRyusuke Konishi struct inode *inode; 4980f3e1c7fSRyusuke Konishi struct nilfs_recovery_block *rb, *n; 4990c6c44cbSRyusuke Konishi unsigned int blocksize = nilfs->ns_blocksize; 5000f3e1c7fSRyusuke Konishi struct page *page; 5010f3e1c7fSRyusuke Konishi loff_t pos; 5020f3e1c7fSRyusuke Konishi int err = 0, err2 = 0; 5030f3e1c7fSRyusuke Konishi 5040f3e1c7fSRyusuke Konishi list_for_each_entry_safe(rb, n, head, list) { 505f7545144SRyusuke Konishi inode = nilfs_iget(sb, root, rb->ino); 5060f3e1c7fSRyusuke Konishi if (IS_ERR(inode)) { 5070f3e1c7fSRyusuke Konishi err = PTR_ERR(inode); 5080f3e1c7fSRyusuke Konishi inode = NULL; 5090f3e1c7fSRyusuke Konishi goto failed_inode; 5100f3e1c7fSRyusuke Konishi } 5110f3e1c7fSRyusuke Konishi 5120f3e1c7fSRyusuke Konishi pos = rb->blkoff << inode->i_blkbits; 513155130a4SChristoph Hellwig err = block_write_begin(inode->i_mapping, pos, blocksize, 514155130a4SChristoph Hellwig 0, &page, nilfs_get_block); 515155130a4SChristoph Hellwig if (unlikely(err)) { 516155130a4SChristoph Hellwig loff_t isize = inode->i_size; 5174ad364caSRyusuke Konishi 518155130a4SChristoph Hellwig if (pos + blocksize > isize) 5192d1b399bSMarco Stornelli nilfs_write_failed(inode->i_mapping, 5202d1b399bSMarco Stornelli pos + blocksize); 5210f3e1c7fSRyusuke Konishi goto failed_inode; 522155130a4SChristoph Hellwig } 5230f3e1c7fSRyusuke Konishi 5248b94025cSRyusuke Konishi err = nilfs_recovery_copy_block(nilfs, rb, page); 5250f3e1c7fSRyusuke Konishi if (unlikely(err)) 5260f3e1c7fSRyusuke Konishi goto failed_page; 5270f3e1c7fSRyusuke Konishi 528bcbc8c64SRyusuke Konishi err = nilfs_set_file_dirty(inode, 1); 5290f3e1c7fSRyusuke Konishi if (unlikely(err)) 5300f3e1c7fSRyusuke Konishi goto failed_page; 5310f3e1c7fSRyusuke Konishi 5320f3e1c7fSRyusuke Konishi block_write_end(NULL, inode->i_mapping, pos, blocksize, 5330f3e1c7fSRyusuke Konishi blocksize, page, NULL); 5340f3e1c7fSRyusuke Konishi 5350f3e1c7fSRyusuke Konishi unlock_page(page); 53609cbfeafSKirill A. Shutemov put_page(page); 5370f3e1c7fSRyusuke Konishi 5380f3e1c7fSRyusuke Konishi (*nr_salvaged_blocks)++; 5390f3e1c7fSRyusuke Konishi goto next; 5400f3e1c7fSRyusuke Konishi 5410f3e1c7fSRyusuke Konishi failed_page: 5420f3e1c7fSRyusuke Konishi unlock_page(page); 54309cbfeafSKirill A. Shutemov put_page(page); 5440f3e1c7fSRyusuke Konishi 5450f3e1c7fSRyusuke Konishi failed_inode: 546a1d0747aSJoe Perches nilfs_warn(sb, 547feee880fSRyusuke Konishi "error %d recovering data block (ino=%lu, block-offset=%llu)", 548b5696e5eSHeiko Carstens err, (unsigned long)rb->ino, 549b5696e5eSHeiko Carstens (unsigned long long)rb->blkoff); 5500f3e1c7fSRyusuke Konishi if (!err2) 5510f3e1c7fSRyusuke Konishi err2 = err; 5520f3e1c7fSRyusuke Konishi next: 5530f3e1c7fSRyusuke Konishi iput(inode); /* iput(NULL) is just ignored */ 5540f3e1c7fSRyusuke Konishi list_del_init(&rb->list); 5550f3e1c7fSRyusuke Konishi kfree(rb); 5560f3e1c7fSRyusuke Konishi } 5570f3e1c7fSRyusuke Konishi return err2; 5580f3e1c7fSRyusuke Konishi } 5590f3e1c7fSRyusuke Konishi 5600f3e1c7fSRyusuke Konishi /** 5610f3e1c7fSRyusuke Konishi * nilfs_do_roll_forward - salvage logical segments newer than the latest 5620f3e1c7fSRyusuke Konishi * checkpoint 5638b94025cSRyusuke Konishi * @nilfs: nilfs object 564f7545144SRyusuke Konishi * @sb: super block instance 5650f3e1c7fSRyusuke Konishi * @ri: pointer to a nilfs_recovery_info 5660f3e1c7fSRyusuke Konishi */ 5670f3e1c7fSRyusuke Konishi static int nilfs_do_roll_forward(struct the_nilfs *nilfs, 568f7545144SRyusuke Konishi struct super_block *sb, 5694d8d9293SRyusuke Konishi struct nilfs_root *root, 5700f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 5710f3e1c7fSRyusuke Konishi { 572354fa8beSRyusuke Konishi struct buffer_head *bh_sum = NULL; 5734f05028fSRyusuke Konishi struct nilfs_segment_summary *sum = NULL; 5740f3e1c7fSRyusuke Konishi sector_t pseg_start; 5750f3e1c7fSRyusuke Konishi sector_t seg_start, seg_end; /* Starting/ending DBN of full segment */ 5760f3e1c7fSRyusuke Konishi unsigned long nsalvaged_blocks = 0; 57785655484SRyusuke Konishi unsigned int flags; 5780f3e1c7fSRyusuke Konishi u64 seg_seq; 5790f3e1c7fSRyusuke Konishi __u64 segnum, nextnum = 0; 5800f3e1c7fSRyusuke Konishi int empty_seg = 0; 5810f3e1c7fSRyusuke Konishi int err = 0, ret; 5820f3e1c7fSRyusuke Konishi LIST_HEAD(dsync_blocks); /* list of data blocks to be recovered */ 5830f3e1c7fSRyusuke Konishi enum { 5840f3e1c7fSRyusuke Konishi RF_INIT_ST, 5850f3e1c7fSRyusuke Konishi RF_DSYNC_ST, /* scanning data-sync segments */ 5860f3e1c7fSRyusuke Konishi }; 5870f3e1c7fSRyusuke Konishi int state = RF_INIT_ST; 5880f3e1c7fSRyusuke Konishi 5890f3e1c7fSRyusuke Konishi pseg_start = ri->ri_lsegs_start; 5900f3e1c7fSRyusuke Konishi seg_seq = ri->ri_lsegs_start_seq; 5910f3e1c7fSRyusuke Konishi segnum = nilfs_get_segnum_of_block(nilfs, pseg_start); 5920f3e1c7fSRyusuke Konishi nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); 5930f3e1c7fSRyusuke Konishi 5940f3e1c7fSRyusuke Konishi while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) { 595354fa8beSRyusuke Konishi brelse(bh_sum); 596354fa8beSRyusuke Konishi bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum); 597354fa8beSRyusuke Konishi if (!bh_sum) { 598354fa8beSRyusuke Konishi err = -EIO; 599354fa8beSRyusuke Konishi goto failed; 600354fa8beSRyusuke Konishi } 6010f3e1c7fSRyusuke Konishi 602354fa8beSRyusuke Konishi ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum); 6030f3e1c7fSRyusuke Konishi if (ret) { 6040f3e1c7fSRyusuke Konishi if (ret == NILFS_SEG_FAIL_IO) { 6050f3e1c7fSRyusuke Konishi err = -EIO; 6060f3e1c7fSRyusuke Konishi goto failed; 6070f3e1c7fSRyusuke Konishi } 6080f3e1c7fSRyusuke Konishi goto strayed; 6090f3e1c7fSRyusuke Konishi } 610354fa8beSRyusuke Konishi 61185655484SRyusuke Konishi flags = le16_to_cpu(sum->ss_flags); 61285655484SRyusuke Konishi if (flags & NILFS_SS_SR) 6130f3e1c7fSRyusuke Konishi goto confused; 6140f3e1c7fSRyusuke Konishi 6150f3e1c7fSRyusuke Konishi /* Found a valid partial segment; do recovery actions */ 61685655484SRyusuke Konishi nextnum = nilfs_get_segnum_of_block(nilfs, 61785655484SRyusuke Konishi le64_to_cpu(sum->ss_next)); 6180f3e1c7fSRyusuke Konishi empty_seg = 0; 61985655484SRyusuke Konishi nilfs->ns_ctime = le64_to_cpu(sum->ss_create); 62085655484SRyusuke Konishi if (!(flags & NILFS_SS_GC)) 62185655484SRyusuke Konishi nilfs->ns_nongc_ctime = nilfs->ns_ctime; 6220f3e1c7fSRyusuke Konishi 6230f3e1c7fSRyusuke Konishi switch (state) { 6240f3e1c7fSRyusuke Konishi case RF_INIT_ST: 62585655484SRyusuke Konishi if (!(flags & NILFS_SS_LOGBGN) || 62685655484SRyusuke Konishi !(flags & NILFS_SS_SYNDT)) 6270f3e1c7fSRyusuke Konishi goto try_next_pseg; 6280f3e1c7fSRyusuke Konishi state = RF_DSYNC_ST; 6290f3e1c7fSRyusuke Konishi /* Fall through */ 6300f3e1c7fSRyusuke Konishi case RF_DSYNC_ST: 63185655484SRyusuke Konishi if (!(flags & NILFS_SS_SYNDT)) 6320f3e1c7fSRyusuke Konishi goto confused; 6330f3e1c7fSRyusuke Konishi 63485655484SRyusuke Konishi err = nilfs_scan_dsync_log(nilfs, pseg_start, sum, 6358b94025cSRyusuke Konishi &dsync_blocks); 6360f3e1c7fSRyusuke Konishi if (unlikely(err)) 6370f3e1c7fSRyusuke Konishi goto failed; 63885655484SRyusuke Konishi if (flags & NILFS_SS_LOGEND) { 6398b94025cSRyusuke Konishi err = nilfs_recover_dsync_blocks( 640f7545144SRyusuke Konishi nilfs, sb, root, &dsync_blocks, 6418b94025cSRyusuke Konishi &nsalvaged_blocks); 6420f3e1c7fSRyusuke Konishi if (unlikely(err)) 6430f3e1c7fSRyusuke Konishi goto failed; 6440f3e1c7fSRyusuke Konishi state = RF_INIT_ST; 6450f3e1c7fSRyusuke Konishi } 6460f3e1c7fSRyusuke Konishi break; /* Fall through to try_next_pseg */ 6470f3e1c7fSRyusuke Konishi } 6480f3e1c7fSRyusuke Konishi 6490f3e1c7fSRyusuke Konishi try_next_pseg: 6500f3e1c7fSRyusuke Konishi if (pseg_start == ri->ri_lsegs_end) 6510f3e1c7fSRyusuke Konishi break; 65285655484SRyusuke Konishi pseg_start += le32_to_cpu(sum->ss_nblocks); 6530f3e1c7fSRyusuke Konishi if (pseg_start < seg_end) 6540f3e1c7fSRyusuke Konishi continue; 6550f3e1c7fSRyusuke Konishi goto feed_segment; 6560f3e1c7fSRyusuke Konishi 6570f3e1c7fSRyusuke Konishi strayed: 6580f3e1c7fSRyusuke Konishi if (pseg_start == ri->ri_lsegs_end) 6590f3e1c7fSRyusuke Konishi break; 6600f3e1c7fSRyusuke Konishi 6610f3e1c7fSRyusuke Konishi feed_segment: 6620f3e1c7fSRyusuke Konishi /* Looking to the next full segment */ 6630f3e1c7fSRyusuke Konishi if (empty_seg++) 6640f3e1c7fSRyusuke Konishi break; 6650f3e1c7fSRyusuke Konishi seg_seq++; 6660f3e1c7fSRyusuke Konishi segnum = nextnum; 6670f3e1c7fSRyusuke Konishi nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); 6680f3e1c7fSRyusuke Konishi pseg_start = seg_start; 6690f3e1c7fSRyusuke Konishi } 6700f3e1c7fSRyusuke Konishi 6710f3e1c7fSRyusuke Konishi if (nsalvaged_blocks) { 672a1d0747aSJoe Perches nilfs_info(sb, "salvaged %lu blocks", nsalvaged_blocks); 6730f3e1c7fSRyusuke Konishi ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; 6740f3e1c7fSRyusuke Konishi } 6750f3e1c7fSRyusuke Konishi out: 676354fa8beSRyusuke Konishi brelse(bh_sum); 6770f3e1c7fSRyusuke Konishi dispose_recovery_list(&dsync_blocks); 6780f3e1c7fSRyusuke Konishi return err; 6790f3e1c7fSRyusuke Konishi 6800f3e1c7fSRyusuke Konishi confused: 6810f3e1c7fSRyusuke Konishi err = -EINVAL; 6820f3e1c7fSRyusuke Konishi failed: 683a1d0747aSJoe Perches nilfs_err(sb, 684feee880fSRyusuke Konishi "error %d roll-forwarding partial segment at blocknr = %llu", 685feee880fSRyusuke Konishi err, (unsigned long long)pseg_start); 6860f3e1c7fSRyusuke Konishi goto out; 6870f3e1c7fSRyusuke Konishi } 6880f3e1c7fSRyusuke Konishi 6890f3e1c7fSRyusuke Konishi static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, 6900f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 6910f3e1c7fSRyusuke Konishi { 6920f3e1c7fSRyusuke Konishi struct buffer_head *bh; 6930f3e1c7fSRyusuke Konishi int err; 6940f3e1c7fSRyusuke Konishi 6950f3e1c7fSRyusuke Konishi if (nilfs_get_segnum_of_block(nilfs, ri->ri_lsegs_start) != 6960f3e1c7fSRyusuke Konishi nilfs_get_segnum_of_block(nilfs, ri->ri_super_root)) 6970f3e1c7fSRyusuke Konishi return; 6980f3e1c7fSRyusuke Konishi 6998b94025cSRyusuke Konishi bh = __getblk(nilfs->ns_bdev, ri->ri_lsegs_start, nilfs->ns_blocksize); 7000f3e1c7fSRyusuke Konishi BUG_ON(!bh); 7010f3e1c7fSRyusuke Konishi memset(bh->b_data, 0, bh->b_size); 7020f3e1c7fSRyusuke Konishi set_buffer_dirty(bh); 7030f3e1c7fSRyusuke Konishi err = sync_dirty_buffer(bh); 7040f3e1c7fSRyusuke Konishi if (unlikely(err)) 705a1d0747aSJoe Perches nilfs_warn(nilfs->ns_sb, 706feee880fSRyusuke Konishi "buffer sync write failed during post-cleaning of recovery."); 7070f3e1c7fSRyusuke Konishi brelse(bh); 7080f3e1c7fSRyusuke Konishi } 7090f3e1c7fSRyusuke Konishi 7100f3e1c7fSRyusuke Konishi /** 711aee5ce2fSRyusuke Konishi * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint 712aee5ce2fSRyusuke Konishi * @nilfs: nilfs object 713f7545144SRyusuke Konishi * @sb: super block instance 7140f3e1c7fSRyusuke Konishi * @ri: pointer to a nilfs_recovery_info struct to store search results. 7150f3e1c7fSRyusuke Konishi * 7160f3e1c7fSRyusuke Konishi * Return Value: On success, 0 is returned. On error, one of the following 7170f3e1c7fSRyusuke Konishi * negative error code is returned. 7180f3e1c7fSRyusuke Konishi * 7190f3e1c7fSRyusuke Konishi * %-EINVAL - Inconsistent filesystem state. 7200f3e1c7fSRyusuke Konishi * 7210f3e1c7fSRyusuke Konishi * %-EIO - I/O error 7220f3e1c7fSRyusuke Konishi * 7230f3e1c7fSRyusuke Konishi * %-ENOSPC - No space left on device (only in a panic state). 7240f3e1c7fSRyusuke Konishi * 7250f3e1c7fSRyusuke Konishi * %-ERESTARTSYS - Interrupted. 7260f3e1c7fSRyusuke Konishi * 7270f3e1c7fSRyusuke Konishi * %-ENOMEM - Insufficient memory available. 7280f3e1c7fSRyusuke Konishi */ 729aee5ce2fSRyusuke Konishi int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, 730f7545144SRyusuke Konishi struct super_block *sb, 7310f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 7320f3e1c7fSRyusuke Konishi { 7334d8d9293SRyusuke Konishi struct nilfs_root *root; 7340f3e1c7fSRyusuke Konishi int err; 7350f3e1c7fSRyusuke Konishi 7360f3e1c7fSRyusuke Konishi if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0) 7370f3e1c7fSRyusuke Konishi return 0; 7380f3e1c7fSRyusuke Konishi 739f7545144SRyusuke Konishi err = nilfs_attach_checkpoint(sb, ri->ri_cno, true, &root); 7400f3e1c7fSRyusuke Konishi if (unlikely(err)) { 741a1d0747aSJoe Perches nilfs_err(sb, "error %d loading the latest checkpoint", err); 7420f3e1c7fSRyusuke Konishi return err; 7430f3e1c7fSRyusuke Konishi } 7440f3e1c7fSRyusuke Konishi 745f7545144SRyusuke Konishi err = nilfs_do_roll_forward(nilfs, sb, root, ri); 7460f3e1c7fSRyusuke Konishi if (unlikely(err)) 7470f3e1c7fSRyusuke Konishi goto failed; 7480f3e1c7fSRyusuke Konishi 7490f3e1c7fSRyusuke Konishi if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) { 750f7545144SRyusuke Konishi err = nilfs_prepare_segment_for_recovery(nilfs, sb, ri); 7510f3e1c7fSRyusuke Konishi if (unlikely(err)) { 752a1d0747aSJoe Perches nilfs_err(sb, "error %d preparing segment for recovery", 753feee880fSRyusuke Konishi err); 7540f3e1c7fSRyusuke Konishi goto failed; 7550f3e1c7fSRyusuke Konishi } 7560f3e1c7fSRyusuke Konishi 757f7545144SRyusuke Konishi err = nilfs_attach_log_writer(sb, root); 7580f3e1c7fSRyusuke Konishi if (unlikely(err)) 7590f3e1c7fSRyusuke Konishi goto failed; 7600f3e1c7fSRyusuke Konishi 7610f3e1c7fSRyusuke Konishi set_nilfs_discontinued(nilfs); 762f7545144SRyusuke Konishi err = nilfs_construct_segment(sb); 763f7545144SRyusuke Konishi nilfs_detach_log_writer(sb); 7640f3e1c7fSRyusuke Konishi 7650f3e1c7fSRyusuke Konishi if (unlikely(err)) { 766a1d0747aSJoe Perches nilfs_err(sb, "error %d writing segment for recovery", 767feee880fSRyusuke Konishi err); 7680f3e1c7fSRyusuke Konishi goto failed; 7690f3e1c7fSRyusuke Konishi } 7700f3e1c7fSRyusuke Konishi 7718b94025cSRyusuke Konishi nilfs_finish_roll_forward(nilfs, ri); 7720f3e1c7fSRyusuke Konishi } 7730f3e1c7fSRyusuke Konishi 7740f3e1c7fSRyusuke Konishi failed: 7754d8d9293SRyusuke Konishi nilfs_put_root(root); 7760f3e1c7fSRyusuke Konishi return err; 7770f3e1c7fSRyusuke Konishi } 7780f3e1c7fSRyusuke Konishi 7790f3e1c7fSRyusuke Konishi /** 7800f3e1c7fSRyusuke Konishi * nilfs_search_super_root - search the latest valid super root 7810f3e1c7fSRyusuke Konishi * @nilfs: the_nilfs 7820f3e1c7fSRyusuke Konishi * @ri: pointer to a nilfs_recovery_info struct to store search results. 7830f3e1c7fSRyusuke Konishi * 7840f3e1c7fSRyusuke Konishi * nilfs_search_super_root() looks for the latest super-root from a partial 7850f3e1c7fSRyusuke Konishi * segment pointed by the superblock. It sets up struct the_nilfs through 7860f3e1c7fSRyusuke Konishi * this search. It fills nilfs_recovery_info (ri) required for recovery. 7870f3e1c7fSRyusuke Konishi * 7880f3e1c7fSRyusuke Konishi * Return Value: On success, 0 is returned. On error, one of the following 7890f3e1c7fSRyusuke Konishi * negative error code is returned. 7900f3e1c7fSRyusuke Konishi * 7910f3e1c7fSRyusuke Konishi * %-EINVAL - No valid segment found 7920f3e1c7fSRyusuke Konishi * 7930f3e1c7fSRyusuke Konishi * %-EIO - I/O error 7942d72b99eSRyusuke Konishi * 7952d72b99eSRyusuke Konishi * %-ENOMEM - Insufficient memory available. 7960f3e1c7fSRyusuke Konishi */ 7978b94025cSRyusuke Konishi int nilfs_search_super_root(struct the_nilfs *nilfs, 7980f3e1c7fSRyusuke Konishi struct nilfs_recovery_info *ri) 7990f3e1c7fSRyusuke Konishi { 800354fa8beSRyusuke Konishi struct buffer_head *bh_sum = NULL; 8014f05028fSRyusuke Konishi struct nilfs_segment_summary *sum = NULL; 8020f3e1c7fSRyusuke Konishi sector_t pseg_start, pseg_end, sr_pseg_start = 0; 8030f3e1c7fSRyusuke Konishi sector_t seg_start, seg_end; /* range of full segment (block number) */ 804050b4142SRyusuke Konishi sector_t b, end; 80585655484SRyusuke Konishi unsigned long nblocks; 80685655484SRyusuke Konishi unsigned int flags; 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 822050b4142SRyusuke Konishi /* Read ahead segment */ 823050b4142SRyusuke Konishi b = seg_start; 824050b4142SRyusuke Konishi while (b <= seg_end) 8258b94025cSRyusuke Konishi __breadahead(nilfs->ns_bdev, b++, nilfs->ns_blocksize); 826050b4142SRyusuke Konishi 8270f3e1c7fSRyusuke Konishi for (;;) { 828354fa8beSRyusuke Konishi brelse(bh_sum); 829354fa8beSRyusuke Konishi ret = NILFS_SEG_FAIL_IO; 830354fa8beSRyusuke Konishi bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum); 831354fa8beSRyusuke Konishi if (!bh_sum) 832354fa8beSRyusuke Konishi goto failed; 833354fa8beSRyusuke Konishi 834354fa8beSRyusuke Konishi ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum); 8350f3e1c7fSRyusuke Konishi if (ret) { 8360f3e1c7fSRyusuke Konishi if (ret == NILFS_SEG_FAIL_IO) 8370f3e1c7fSRyusuke Konishi goto failed; 8380f3e1c7fSRyusuke Konishi goto strayed; 8390f3e1c7fSRyusuke Konishi } 840354fa8beSRyusuke Konishi 84185655484SRyusuke Konishi nblocks = le32_to_cpu(sum->ss_nblocks); 84285655484SRyusuke Konishi pseg_end = pseg_start + nblocks - 1; 8430f3e1c7fSRyusuke Konishi if (unlikely(pseg_end > seg_end)) { 8440f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CONSISTENCY; 8450f3e1c7fSRyusuke Konishi goto strayed; 8460f3e1c7fSRyusuke Konishi } 8470f3e1c7fSRyusuke Konishi 8480f3e1c7fSRyusuke Konishi /* A valid partial segment */ 8490f3e1c7fSRyusuke Konishi ri->ri_pseg_start = pseg_start; 8500f3e1c7fSRyusuke Konishi ri->ri_seq = seg_seq; 8510f3e1c7fSRyusuke Konishi ri->ri_segnum = segnum; 85285655484SRyusuke Konishi nextnum = nilfs_get_segnum_of_block(nilfs, 85385655484SRyusuke Konishi le64_to_cpu(sum->ss_next)); 8540f3e1c7fSRyusuke Konishi ri->ri_nextnum = nextnum; 8550f3e1c7fSRyusuke Konishi empty_seg = 0; 8560f3e1c7fSRyusuke Konishi 85785655484SRyusuke Konishi flags = le16_to_cpu(sum->ss_flags); 85885655484SRyusuke Konishi if (!(flags & NILFS_SS_SR) && !scan_newer) { 859076a378bSRyusuke Konishi /* 860076a378bSRyusuke Konishi * This will never happen because a superblock 861076a378bSRyusuke Konishi * (last_segment) always points to a pseg with 862076a378bSRyusuke Konishi * a super root. 863076a378bSRyusuke Konishi */ 8640f3e1c7fSRyusuke Konishi ret = NILFS_SEG_FAIL_CONSISTENCY; 8650f3e1c7fSRyusuke Konishi goto failed; 8660f3e1c7fSRyusuke Konishi } 867050b4142SRyusuke Konishi 868050b4142SRyusuke Konishi if (pseg_start == seg_start) { 869050b4142SRyusuke Konishi nilfs_get_segment_range(nilfs, nextnum, &b, &end); 870050b4142SRyusuke Konishi while (b <= end) 8718b94025cSRyusuke Konishi __breadahead(nilfs->ns_bdev, b++, 8728b94025cSRyusuke Konishi nilfs->ns_blocksize); 873050b4142SRyusuke Konishi } 87485655484SRyusuke Konishi if (!(flags & NILFS_SS_SR)) { 87585655484SRyusuke Konishi if (!ri->ri_lsegs_start && (flags & NILFS_SS_LOGBGN)) { 8760f3e1c7fSRyusuke Konishi ri->ri_lsegs_start = pseg_start; 8770f3e1c7fSRyusuke Konishi ri->ri_lsegs_start_seq = seg_seq; 8780f3e1c7fSRyusuke Konishi } 87985655484SRyusuke Konishi if (flags & NILFS_SS_LOGEND) 8800f3e1c7fSRyusuke Konishi ri->ri_lsegs_end = pseg_start; 8810f3e1c7fSRyusuke Konishi goto try_next_pseg; 8820f3e1c7fSRyusuke Konishi } 8830f3e1c7fSRyusuke Konishi 8840f3e1c7fSRyusuke Konishi /* A valid super root was found. */ 8850f3e1c7fSRyusuke Konishi ri->ri_cno = cno++; 8860f3e1c7fSRyusuke Konishi ri->ri_super_root = pseg_end; 8870f3e1c7fSRyusuke Konishi ri->ri_lsegs_start = ri->ri_lsegs_end = 0; 8880f3e1c7fSRyusuke Konishi 8890f3e1c7fSRyusuke Konishi nilfs_dispose_segment_list(&segments); 89085655484SRyusuke Konishi sr_pseg_start = pseg_start; 89185655484SRyusuke Konishi nilfs->ns_pseg_offset = pseg_start + nblocks - seg_start; 8920f3e1c7fSRyusuke Konishi nilfs->ns_seg_seq = seg_seq; 8930f3e1c7fSRyusuke Konishi nilfs->ns_segnum = segnum; 8940f3e1c7fSRyusuke Konishi nilfs->ns_cno = cno; /* nilfs->ns_cno = ri->ri_cno + 1 */ 89585655484SRyusuke Konishi nilfs->ns_ctime = le64_to_cpu(sum->ss_create); 8960f3e1c7fSRyusuke Konishi nilfs->ns_nextnum = nextnum; 8970f3e1c7fSRyusuke Konishi 8980f3e1c7fSRyusuke Konishi if (scan_newer) 8990f3e1c7fSRyusuke Konishi ri->ri_need_recovery = NILFS_RECOVERY_SR_UPDATED; 9002c2e52fcSRyusuke Konishi else { 9012c2e52fcSRyusuke Konishi if (nilfs->ns_mount_state & NILFS_VALID_FS) 9020f3e1c7fSRyusuke Konishi goto super_root_found; 9030f3e1c7fSRyusuke Konishi scan_newer = 1; 9042c2e52fcSRyusuke Konishi } 9050f3e1c7fSRyusuke Konishi 9060f3e1c7fSRyusuke Konishi try_next_pseg: 9070f3e1c7fSRyusuke Konishi /* Standing on a course, or met an inconsistent state */ 90885655484SRyusuke Konishi pseg_start += nblocks; 9090f3e1c7fSRyusuke Konishi if (pseg_start < seg_end) 9100f3e1c7fSRyusuke Konishi continue; 9110f3e1c7fSRyusuke Konishi goto feed_segment; 9120f3e1c7fSRyusuke Konishi 9130f3e1c7fSRyusuke Konishi strayed: 9140f3e1c7fSRyusuke Konishi /* Off the trail */ 9150f3e1c7fSRyusuke Konishi if (!scan_newer) 9160f3e1c7fSRyusuke Konishi /* 9170f3e1c7fSRyusuke Konishi * This can happen if a checkpoint was written without 9180f3e1c7fSRyusuke Konishi * barriers, or as a result of an I/O failure. 9190f3e1c7fSRyusuke Konishi */ 9200f3e1c7fSRyusuke Konishi goto failed; 9210f3e1c7fSRyusuke Konishi 9220f3e1c7fSRyusuke Konishi feed_segment: 9230f3e1c7fSRyusuke Konishi /* Looking to the next full segment */ 9240f3e1c7fSRyusuke Konishi if (empty_seg++) 9250f3e1c7fSRyusuke Konishi goto super_root_found; /* found a valid super root */ 9260f3e1c7fSRyusuke Konishi 927654137ddSRyusuke Konishi ret = nilfs_segment_list_add(&segments, segnum); 928654137ddSRyusuke Konishi if (unlikely(ret)) 9290f3e1c7fSRyusuke Konishi goto failed; 9300f3e1c7fSRyusuke Konishi 9310f3e1c7fSRyusuke Konishi seg_seq++; 9320f3e1c7fSRyusuke Konishi segnum = nextnum; 9330f3e1c7fSRyusuke Konishi nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); 9340f3e1c7fSRyusuke Konishi pseg_start = seg_start; 9350f3e1c7fSRyusuke Konishi } 9360f3e1c7fSRyusuke Konishi 9370f3e1c7fSRyusuke Konishi super_root_found: 9380f3e1c7fSRyusuke Konishi /* Updating pointers relating to the latest checkpoint */ 939354fa8beSRyusuke Konishi brelse(bh_sum); 9400935db74SRyusuke Konishi list_splice_tail(&segments, &ri->ri_used_segments); 9410f3e1c7fSRyusuke Konishi nilfs->ns_last_pseg = sr_pseg_start; 9420f3e1c7fSRyusuke Konishi nilfs->ns_last_seq = nilfs->ns_seg_seq; 9430f3e1c7fSRyusuke Konishi nilfs->ns_last_cno = ri->ri_cno; 9440f3e1c7fSRyusuke Konishi return 0; 9450f3e1c7fSRyusuke Konishi 9460f3e1c7fSRyusuke Konishi failed: 947354fa8beSRyusuke Konishi brelse(bh_sum); 9480f3e1c7fSRyusuke Konishi nilfs_dispose_segment_list(&segments); 949feee880fSRyusuke Konishi return ret < 0 ? ret : nilfs_warn_segment_error(nilfs->ns_sb, ret); 9500f3e1c7fSRyusuke Konishi } 951