From c6341130fc6bf9861c0fc3aeba6a08140868e38f Mon Sep 17 00:00:00 2001 From: Krzysztof Mazur Date: Thu, 19 May 2011 20:38:44 +0200 Subject: [PATCH 36/84] lsbd: check ptab checksums --- drivers/block/lsbd.c | 49 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/drivers/block/lsbd.c b/drivers/block/lsbd.c index fb34cb2..7b4ab40 100644 --- a/drivers/block/lsbd.c +++ b/drivers/block/lsbd.c @@ -662,6 +662,7 @@ int lsbd_read_lcache(struct lsbd *p) unsigned int lcache_chunk; unsigned int lcache_base; lsbd_lcache_t *cache; + u32 ptab_checksum; int first = 1; /* to protect against OOM allocate at most 64 MB of lcache */ @@ -701,18 +702,29 @@ int lsbd_read_lcache(struct lsbd *p) if (sectors > sectors_max) sectors = sectors_max; - for (i = 0; i < sectors; i++) { - sector_id = be32_to_cpu(sects[i].id); + ptab_checksum = lsbd_checksum(bh->b_data + + be32_to_cpu(b->ptab_offset), + (p->sectors_per_block - 1) + * sizeof(struct lsbd_sect)); - if (sector_id >= p->lsectors) - continue; + if (be32_to_cpu(b->ptab_checksum) == ptab_checksum) { + for (i = 0; i < sectors; i++) { + sector_id = be32_to_cpu(sects[i].id); - if (p->lcache[sector_id] == LSBD_SECT_INVALID) { - p->lcache[sector_id] = block - * p->sectors_per_block + i + 1; - BUG_ON(p->lcache[sector_id] >= p->psectors); - readed++; + if (sector_id >= p->lsectors) + continue; + + if (p->lcache[sector_id] == LSBD_SECT_INVALID) { + p->lcache[sector_id] = block + * p->sectors_per_block + i + 1; + BUG_ON(p->lcache[sector_id] + >= p->psectors); + readed++; + } } + } else { + lsbd_info(p, "block %d: ptab checksum error\n", + block); } /* @@ -1550,6 +1562,7 @@ void lsbd_clean_block(struct lsbd *p) unsigned long sectors_max; unsigned long i; unsigned int ptab_offset; + u32 ptab_checksum; int mirrored = 0; block++; @@ -1588,6 +1601,23 @@ void lsbd_clean_block(struct lsbd *p) lsbd_debug(p, "ptab_offset %d\n", ptab_offset); lsbd_debug(p, "cleaning block %ld: %ld sectors\n", block, sectors); + ptab_checksum = lsbd_checksum(bh->b_data + + be32_to_cpu(b->ptab_offset), + (p->sectors_per_block - 1) + * sizeof(struct lsbd_sect)); + + /* + * if ptab checksum is invalid we try to retry with another copy + * - we don't want to skip next block. + */ + if (be32_to_cpu(b->ptab_checksum) != ptab_checksum) { + lsbd_info(p, "clean: block %ld: ptab checksum error\n", block); + brelse(bh); + lsbd_put_buffer(p, bh); + p->clean_block = block; + return; + } + for (i = 0; i < sectors; i++) { unsigned int sector_id = be32_to_cpu(sects[i].id); unsigned int s = block * p->sectors_per_block + i + 1; @@ -1616,6 +1646,7 @@ void lsbd_clean_block(struct lsbd *p) } } } + brelse(bh); lsbd_put_buffer(p, bh); -- 1.8.4.652.g0d6e0ce