aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/recovery.c
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2010-05-23 06:21:49 -0400
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2010-07-22 21:02:09 -0400
commit354fa8be280ce81c88b6b236d62d23ebcade2d3f (patch)
tree68577608794a15910b72d7644339edc1f39eddbe /fs/nilfs2/recovery.c
parentaee5ce2f578b98eba16e59cb84d39a95682a836b (diff)
nilfs2: divide load_segment_summary function
load_segment_summary function has two distinct roles: getting summary header of a log, and verifying consistencies of the log. This divide it into two corresponding functions, nilfs_read_log_header and nilfs_validate_log to clarify the meaning. Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Diffstat (limited to 'fs/nilfs2/recovery.c')
-rw-r--r--fs/nilfs2/recovery.c110
1 files changed, 69 insertions, 41 deletions
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index fd7fb4149aa7..35506b1704d1 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -202,58 +202,63 @@ int nilfs_read_super_root_block(struct the_nilfs *nilfs, sector_t sr_block,
202} 202}
203 203
204/** 204/**
205 * load_segment_summary - read segment summary of the specified partial segment 205 * nilfs_read_log_header - read summary header of the specified log
206 * @nilfs: nilfs object 206 * @nilfs: nilfs object
207 * @pseg_start: start disk block number of partial segment 207 * @start_blocknr: start block number of the log
208 * @seg_seq: sequence number requested 208 * @sum: pointer to return segment summary structure
209 * @ssi: pointer to nilfs_segsum_info struct to store information
210 */ 209 */
211static int 210static struct buffer_head *
212load_segment_summary(struct the_nilfs *nilfs, sector_t pseg_start, 211nilfs_read_log_header(struct the_nilfs *nilfs, sector_t start_blocknr,
213 u64 seg_seq, struct nilfs_segsum_info *ssi) 212 struct nilfs_segment_summary **sum)
214{ 213{
215 struct buffer_head *bh_sum; 214 struct buffer_head *bh_sum;
216 struct nilfs_segment_summary *sum; 215
216 bh_sum = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize);
217 if (bh_sum)
218 *sum = (struct nilfs_segment_summary *)bh_sum->b_data;
219 return bh_sum;
220}
221
222/**
223 * nilfs_validate_log - verify consistency of log
224 * @nilfs: nilfs object
225 * @seg_seq: sequence number of segment
226 * @bh_sum: buffer head of summary block
227 * @sum: segment summary struct
228 */
229static int nilfs_validate_log(struct the_nilfs *nilfs, u64 seg_seq,
230 struct buffer_head *bh_sum,
231 struct nilfs_segment_summary *sum)
232{
217 unsigned long nblock; 233 unsigned long nblock;
218 u32 crc; 234 u32 crc;
219 int ret = NILFS_SEG_FAIL_IO; 235 int ret;
220 236
221 bh_sum = __bread(nilfs->ns_bdev, pseg_start, nilfs->ns_blocksize); 237 ret = NILFS_SEG_FAIL_MAGIC;
222 if (!bh_sum) 238 if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC)
223 goto out; 239 goto out;
224 240
225 sum = (struct nilfs_segment_summary *)bh_sum->b_data; 241 ret = NILFS_SEG_FAIL_SEQ;
226 242 if (le64_to_cpu(sum->ss_seq) != seg_seq)
227 /* Check consistency of segment summary */ 243 goto out;
228 if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC) {
229 ret = NILFS_SEG_FAIL_MAGIC;
230 goto failed;
231 }
232 store_segsum_info(ssi, sum, nilfs->ns_blocksize);
233 if (seg_seq != ssi->seg_seq) {
234 ret = NILFS_SEG_FAIL_SEQ;
235 goto failed;
236 }
237 244
238 nblock = ssi->nblocks; 245 nblock = le32_to_cpu(sum->ss_nblocks);
239 if (unlikely(nblock == 0 || nblock > nilfs->ns_blocks_per_segment)) { 246 ret = NILFS_SEG_FAIL_CONSISTENCY;
247 if (unlikely(nblock == 0 || nblock > nilfs->ns_blocks_per_segment))
240 /* This limits the number of blocks read in the CRC check */ 248 /* This limits the number of blocks read in the CRC check */
241 ret = NILFS_SEG_FAIL_CONSISTENCY; 249 goto out;
242 goto failed; 250
243 } 251 ret = NILFS_SEG_FAIL_IO;
244 if (nilfs_compute_checksum(nilfs, bh_sum, &crc, sizeof(sum->ss_datasum), 252 if (nilfs_compute_checksum(nilfs, bh_sum, &crc, sizeof(sum->ss_datasum),
245 ((u64)nblock << nilfs->ns_blocksize_bits), 253 ((u64)nblock << nilfs->ns_blocksize_bits),
246 pseg_start, nblock)) { 254 bh_sum->b_blocknr, nblock))
247 ret = NILFS_SEG_FAIL_IO; 255 goto out;
248 goto failed; 256
249 } 257 ret = NILFS_SEG_FAIL_CHECKSUM_FULL;
250 if (crc == le32_to_cpu(sum->ss_datasum)) 258 if (crc != le32_to_cpu(sum->ss_datasum))
251 ret = 0; 259 goto out;
252 else 260 ret = 0;
253 ret = NILFS_SEG_FAIL_CHECKSUM_FULL; 261out:
254 failed:
255 brelse(bh_sum);
256 out:
257 return ret; 262 return ret;
258} 263}
259 264
@@ -589,6 +594,8 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
589 struct nilfs_recovery_info *ri) 594 struct nilfs_recovery_info *ri)
590{ 595{
591 struct nilfs_segsum_info ssi; 596 struct nilfs_segsum_info ssi;
597 struct buffer_head *bh_sum = NULL;
598 struct nilfs_segment_summary *sum;
592 sector_t pseg_start; 599 sector_t pseg_start;
593 sector_t seg_start, seg_end; /* Starting/ending DBN of full segment */ 600 sector_t seg_start, seg_end; /* Starting/ending DBN of full segment */
594 unsigned long nsalvaged_blocks = 0; 601 unsigned long nsalvaged_blocks = 0;
@@ -610,8 +617,14 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
610 nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); 617 nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);
611 618
612 while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) { 619 while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) {
620 brelse(bh_sum);
621 bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum);
622 if (!bh_sum) {
623 err = -EIO;
624 goto failed;
625 }
613 626
614 ret = load_segment_summary(nilfs, pseg_start, seg_seq, &ssi); 627 ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum);
615 if (ret) { 628 if (ret) {
616 if (ret == NILFS_SEG_FAIL_IO) { 629 if (ret == NILFS_SEG_FAIL_IO) {
617 err = -EIO; 630 err = -EIO;
@@ -619,6 +632,8 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
619 } 632 }
620 goto strayed; 633 goto strayed;
621 } 634 }
635
636 store_segsum_info(&ssi, sum, nilfs->ns_blocksize);
622 if (unlikely(NILFS_SEG_HAS_SR(&ssi))) 637 if (unlikely(NILFS_SEG_HAS_SR(&ssi)))
623 goto confused; 638 goto confused;
624 639
@@ -682,6 +697,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
682 ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; 697 ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE;
683 } 698 }
684 out: 699 out:
700 brelse(bh_sum);
685 dispose_recovery_list(&dsync_blocks); 701 dispose_recovery_list(&dsync_blocks);
686 nilfs_detach_writer(nilfs, sbi); 702 nilfs_detach_writer(nilfs, sbi);
687 return err; 703 return err;
@@ -807,6 +823,8 @@ int nilfs_search_super_root(struct the_nilfs *nilfs,
807 struct nilfs_recovery_info *ri) 823 struct nilfs_recovery_info *ri)
808{ 824{
809 struct nilfs_segsum_info ssi; 825 struct nilfs_segsum_info ssi;
826 struct buffer_head *bh_sum = NULL;
827 struct nilfs_segment_summary *sum;
810 sector_t pseg_start, pseg_end, sr_pseg_start = 0; 828 sector_t pseg_start, pseg_end, sr_pseg_start = 0;
811 sector_t seg_start, seg_end; /* range of full segment (block number) */ 829 sector_t seg_start, seg_end; /* range of full segment (block number) */
812 sector_t b, end; 830 sector_t b, end;
@@ -831,12 +849,20 @@ int nilfs_search_super_root(struct the_nilfs *nilfs,
831 __breadahead(nilfs->ns_bdev, b++, nilfs->ns_blocksize); 849 __breadahead(nilfs->ns_bdev, b++, nilfs->ns_blocksize);
832 850
833 for (;;) { 851 for (;;) {
834 ret = load_segment_summary(nilfs, pseg_start, seg_seq, &ssi); 852 brelse(bh_sum);
853 ret = NILFS_SEG_FAIL_IO;
854 bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum);
855 if (!bh_sum)
856 goto failed;
857
858 ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum);
835 if (ret) { 859 if (ret) {
836 if (ret == NILFS_SEG_FAIL_IO) 860 if (ret == NILFS_SEG_FAIL_IO)
837 goto failed; 861 goto failed;
838 goto strayed; 862 goto strayed;
839 } 863 }
864
865 store_segsum_info(&ssi, sum, nilfs->ns_blocksize);
840 pseg_end = pseg_start + ssi.nblocks - 1; 866 pseg_end = pseg_start + ssi.nblocks - 1;
841 if (unlikely(pseg_end > seg_end)) { 867 if (unlikely(pseg_end > seg_end)) {
842 ret = NILFS_SEG_FAIL_CONSISTENCY; 868 ret = NILFS_SEG_FAIL_CONSISTENCY;
@@ -936,6 +962,7 @@ int nilfs_search_super_root(struct the_nilfs *nilfs,
936 962
937 super_root_found: 963 super_root_found:
938 /* Updating pointers relating to the latest checkpoint */ 964 /* Updating pointers relating to the latest checkpoint */
965 brelse(bh_sum);
939 list_splice_tail(&segments, &ri->ri_used_segments); 966 list_splice_tail(&segments, &ri->ri_used_segments);
940 nilfs->ns_last_pseg = sr_pseg_start; 967 nilfs->ns_last_pseg = sr_pseg_start;
941 nilfs->ns_last_seq = nilfs->ns_seg_seq; 968 nilfs->ns_last_seq = nilfs->ns_seg_seq;
@@ -943,6 +970,7 @@ int nilfs_search_super_root(struct the_nilfs *nilfs,
943 return 0; 970 return 0;
944 971
945 failed: 972 failed:
973 brelse(bh_sum);
946 nilfs_dispose_segment_list(&segments); 974 nilfs_dispose_segment_list(&segments);
947 return (ret < 0) ? ret : nilfs_warn_segment_error(ret); 975 return (ret < 0) ? ret : nilfs_warn_segment_error(ret);
948} 976}