From a6c4f96094fbaee957444e141d67e12873c41d05 Mon Sep 17 00:00:00 2001 From: Krzysztof Mazur Date: Sat, 4 Feb 2012 19:44:14 +0100 Subject: [PATCH 66/84] lsbd: skip last block if it is corrupted This patch add skipping if last block if it is corrupted. This adds protection against data corruption caused by partial block write. Signed-off-by: Krzysztof Mazur --- drivers/block/lsbd.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/block/lsbd.c b/drivers/block/lsbd.c index 84a5bfc..45240e0 100644 --- a/drivers/block/lsbd.c +++ b/drivers/block/lsbd.c @@ -1040,15 +1040,16 @@ static int lsbd_load_params(struct lsbd *p) unsigned int block = 0; unsigned int i; unsigned int blocks; + unsigned int blocks_to_check; unsigned int sector_size; unsigned int sectors_per_block; block = p->cur_block; - i = p->blocks; - if (i > 100) - i = 100; + blocks_to_check = p->blocks; + if (blocks_to_check > 100) + blocks_to_check = 100; - for (; i > 0; i--, block = block_prev(p, block)) { + for (i = 0; i < blocks_to_check; i++, block = block_prev(p, block)) { lsbd_debug(p, "params: block %d\n", block); bh = lsbd_sread(p, block, 0); if (bh == NULL) @@ -1108,6 +1109,23 @@ static int lsbd_load_params(struct lsbd *p) return -EINVAL; } + /* + * The last block can be possibly corrupted by power + * failure. We detect this by checking checksums. + * If the block is corrupted we just skip it. We can + * do it safely because we keep larger than 1 block + * minimal rewrite distance, so the device state + * without last sector is always consistent. + */ + if ((i == 0) && lsbd_check_data_sectors(p, bh, b, block)) { + p->cur_block = block_prev(p, block); + p->clean_block = p->cur_block; + brelse(bh); + lsbd_put_buffer(p, bh); + lsbd_info(p, "corrupted block %d, skipping\n", block); + continue; + } + lsbd_info(p, "logical size %d KiB, physical %d KiB%s\n", p->lsectors * (p->sector_size >> 10), p->blocks * p->sectors_per_block -- 1.8.4.652.g0d6e0ce