From 118b38c7ad5eda9cb132799c41ad6cbec2e89c9c Mon Sep 17 00:00:00 2001 From: Krzysztof Mazur Date: Wed, 27 Jul 2011 21:09:50 +0200 Subject: [PATCH 54/84] lsbd: improve/fix mirrored clean error handling This patch improves error handling during block cleaning on mirrored devices. Now in case of block checksum error copy is readed. Now retries are processed immediately - this avoids problems with rewritting first copy and using it in case of secondary copy read failure. This patch also fixes memory leaks in case of block checksum failure or invalid ptab_offset. --- drivers/block/lsbd.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/block/lsbd.c b/drivers/block/lsbd.c index 39ee11b..2a8249a 100644 --- a/drivers/block/lsbd.c +++ b/drivers/block/lsbd.c @@ -1698,8 +1698,9 @@ void lsbd_clean_block(struct lsbd *p) unsigned long i; unsigned int ptab_offset; u32 ptab_checksum; - int mirrored = 0; + int mirrored; +retry: block++; if (block >= p->blocks) block = 0; @@ -1708,6 +1709,7 @@ void lsbd_clean_block(struct lsbd *p) * in case of error on even block in mirrored devices we just * skip such block and the next block will be properly cleared */ + mirrored = 0; if (!(block & 1) && p->mirrored) { BUG_ON(block + 1 >= p->blocks); mirrored = 1; @@ -1720,13 +1722,18 @@ void lsbd_clean_block(struct lsbd *p) ret = lsbd_block_verify_ok(p, b); if (!ret) { + lsbd_info(p, "clean: block %ld: block checksum error\n", block); brelse(bh); + lsbd_put_buffer(p, bh); + if (mirrored) + goto retry; goto out; } ptab_offset = be32_to_cpu(b->ptab_offset); if (ptab_offset >= p->sector_size) { brelse(bh); + lsbd_put_buffer(p, bh); goto out; } sectors_max = (p->sector_size - ptab_offset) / sizeof(sects[0]); @@ -1752,8 +1759,9 @@ void lsbd_clean_block(struct lsbd *p) lsbd_info(p, "clean: block %ld: ptab checksum error\n", block); brelse(bh); lsbd_put_buffer(p, bh); - p->clean_block = block; - return; + if (mirrored) + goto retry; + goto out; } for (i = 0; i < sectors; i++) { -- 1.8.4.652.g0d6e0ce