diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-05-23 06:21:49 -0400 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2010-07-22 21:02:09 -0400 |
commit | 354fa8be280ce81c88b6b236d62d23ebcade2d3f (patch) | |
tree | 68577608794a15910b72d7644339edc1f39eddbe /fs/nilfs2 | |
parent | aee5ce2f578b98eba16e59cb84d39a95682a836b (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')
-rw-r--r-- | fs/nilfs2/recovery.c | 110 |
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 | */ |
211 | static int | 210 | static struct buffer_head * |
212 | load_segment_summary(struct the_nilfs *nilfs, sector_t pseg_start, | 211 | nilfs_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 | */ | ||
229 | static 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; | 261 | out: |
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 | } |