Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 206331
b: refs/heads/master
c: 354fa8b
h: refs/heads/master
i:
  206329: f7124ab
  206327: d86a1fb
v: v3
  • Loading branch information
Ryusuke Konishi committed Jul 23, 2010
1 parent 8e04673 commit 34ae2cb
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 42 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: aee5ce2f578b98eba16e59cb84d39a95682a836b
refs/heads/master: 354fa8be280ce81c88b6b236d62d23ebcade2d3f
110 changes: 69 additions & 41 deletions trunk/fs/nilfs2/recovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,58 +202,63 @@ int nilfs_read_super_root_block(struct the_nilfs *nilfs, sector_t sr_block,
}

/**
* load_segment_summary - read segment summary of the specified partial segment
* nilfs_read_log_header - read summary header of the specified log
* @nilfs: nilfs object
* @pseg_start: start disk block number of partial segment
* @seg_seq: sequence number requested
* @ssi: pointer to nilfs_segsum_info struct to store information
* @start_blocknr: start block number of the log
* @sum: pointer to return segment summary structure
*/
static int
load_segment_summary(struct the_nilfs *nilfs, sector_t pseg_start,
u64 seg_seq, struct nilfs_segsum_info *ssi)
static struct buffer_head *
nilfs_read_log_header(struct the_nilfs *nilfs, sector_t start_blocknr,
struct nilfs_segment_summary **sum)
{
struct buffer_head *bh_sum;
struct nilfs_segment_summary *sum;

bh_sum = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize);
if (bh_sum)
*sum = (struct nilfs_segment_summary *)bh_sum->b_data;
return bh_sum;
}

/**
* nilfs_validate_log - verify consistency of log
* @nilfs: nilfs object
* @seg_seq: sequence number of segment
* @bh_sum: buffer head of summary block
* @sum: segment summary struct
*/
static int nilfs_validate_log(struct the_nilfs *nilfs, u64 seg_seq,
struct buffer_head *bh_sum,
struct nilfs_segment_summary *sum)
{
unsigned long nblock;
u32 crc;
int ret = NILFS_SEG_FAIL_IO;
int ret;

bh_sum = __bread(nilfs->ns_bdev, pseg_start, nilfs->ns_blocksize);
if (!bh_sum)
ret = NILFS_SEG_FAIL_MAGIC;
if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC)
goto out;

sum = (struct nilfs_segment_summary *)bh_sum->b_data;

/* Check consistency of segment summary */
if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC) {
ret = NILFS_SEG_FAIL_MAGIC;
goto failed;
}
store_segsum_info(ssi, sum, nilfs->ns_blocksize);
if (seg_seq != ssi->seg_seq) {
ret = NILFS_SEG_FAIL_SEQ;
goto failed;
}
ret = NILFS_SEG_FAIL_SEQ;
if (le64_to_cpu(sum->ss_seq) != seg_seq)
goto out;

nblock = ssi->nblocks;
if (unlikely(nblock == 0 || nblock > nilfs->ns_blocks_per_segment)) {
nblock = le32_to_cpu(sum->ss_nblocks);
ret = NILFS_SEG_FAIL_CONSISTENCY;
if (unlikely(nblock == 0 || nblock > nilfs->ns_blocks_per_segment))
/* This limits the number of blocks read in the CRC check */
ret = NILFS_SEG_FAIL_CONSISTENCY;
goto failed;
}
goto out;

ret = NILFS_SEG_FAIL_IO;
if (nilfs_compute_checksum(nilfs, bh_sum, &crc, sizeof(sum->ss_datasum),
((u64)nblock << nilfs->ns_blocksize_bits),
pseg_start, nblock)) {
ret = NILFS_SEG_FAIL_IO;
goto failed;
}
if (crc == le32_to_cpu(sum->ss_datasum))
ret = 0;
else
ret = NILFS_SEG_FAIL_CHECKSUM_FULL;
failed:
brelse(bh_sum);
out:
bh_sum->b_blocknr, nblock))
goto out;

ret = NILFS_SEG_FAIL_CHECKSUM_FULL;
if (crc != le32_to_cpu(sum->ss_datasum))
goto out;
ret = 0;
out:
return ret;
}

Expand Down Expand Up @@ -589,6 +594,8 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
struct nilfs_recovery_info *ri)
{
struct nilfs_segsum_info ssi;
struct buffer_head *bh_sum = NULL;
struct nilfs_segment_summary *sum;
sector_t pseg_start;
sector_t seg_start, seg_end; /* Starting/ending DBN of full segment */
unsigned long nsalvaged_blocks = 0;
Expand All @@ -610,15 +617,23 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end);

while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) {
brelse(bh_sum);
bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum);
if (!bh_sum) {
err = -EIO;
goto failed;
}

ret = load_segment_summary(nilfs, pseg_start, seg_seq, &ssi);
ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum);
if (ret) {
if (ret == NILFS_SEG_FAIL_IO) {
err = -EIO;
goto failed;
}
goto strayed;
}

store_segsum_info(&ssi, sum, nilfs->ns_blocksize);
if (unlikely(NILFS_SEG_HAS_SR(&ssi)))
goto confused;

Expand Down Expand Up @@ -682,6 +697,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE;
}
out:
brelse(bh_sum);
dispose_recovery_list(&dsync_blocks);
nilfs_detach_writer(nilfs, sbi);
return err;
Expand Down Expand Up @@ -807,6 +823,8 @@ int nilfs_search_super_root(struct the_nilfs *nilfs,
struct nilfs_recovery_info *ri)
{
struct nilfs_segsum_info ssi;
struct buffer_head *bh_sum = NULL;
struct nilfs_segment_summary *sum;
sector_t pseg_start, pseg_end, sr_pseg_start = 0;
sector_t seg_start, seg_end; /* range of full segment (block number) */
sector_t b, end;
Expand All @@ -831,12 +849,20 @@ int nilfs_search_super_root(struct the_nilfs *nilfs,
__breadahead(nilfs->ns_bdev, b++, nilfs->ns_blocksize);

for (;;) {
ret = load_segment_summary(nilfs, pseg_start, seg_seq, &ssi);
brelse(bh_sum);
ret = NILFS_SEG_FAIL_IO;
bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum);
if (!bh_sum)
goto failed;

ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum);
if (ret) {
if (ret == NILFS_SEG_FAIL_IO)
goto failed;
goto strayed;
}

store_segsum_info(&ssi, sum, nilfs->ns_blocksize);
pseg_end = pseg_start + ssi.nblocks - 1;
if (unlikely(pseg_end > seg_end)) {
ret = NILFS_SEG_FAIL_CONSISTENCY;
Expand Down Expand Up @@ -936,13 +962,15 @@ int nilfs_search_super_root(struct the_nilfs *nilfs,

super_root_found:
/* Updating pointers relating to the latest checkpoint */
brelse(bh_sum);
list_splice_tail(&segments, &ri->ri_used_segments);
nilfs->ns_last_pseg = sr_pseg_start;
nilfs->ns_last_seq = nilfs->ns_seg_seq;
nilfs->ns_last_cno = ri->ri_cno;
return 0;

failed:
brelse(bh_sum);
nilfs_dispose_segment_list(&segments);
return (ret < 0) ? ret : nilfs_warn_segment_error(ret);
}

0 comments on commit 34ae2cb

Please sign in to comment.