From a8e84d6ff0491588c0e2263889f4ae38392a71c8 Mon Sep 17 00:00:00 2001 From: Krzysztof Mazur Date: Sat, 4 Feb 2012 18:25:19 +0100 Subject: [PATCH 65/84] lsbd: move sector check for separate function This patch moves block and sector checksum checking to separate functions. Signed-off-by: Krzysztof Mazur --- drivers/block/lsbd.c | 133 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 83 insertions(+), 50 deletions(-) diff --git a/drivers/block/lsbd.c b/drivers/block/lsbd.c index 1b9a0f5..84a5bfc 100644 --- a/drivers/block/lsbd.c +++ b/drivers/block/lsbd.c @@ -707,72 +707,105 @@ out: return ret; } -/** - * lsbd_check_sectors - check recently written sectors - * @p: LSBD device +/* + * lsbd_check_data_sectors - check data sectors of selected block + * + * This function checks checksums of data sectors of selected block. + * This function returns zero when all sectors have proper checksums; + * non-zero error code otherwise. */ -static int lsbd_check_sectors(struct lsbd *p) +static int lsbd_check_data_sectors(struct lsbd *p, struct buffer_head *bh, + struct lsbd_block *b, unsigned int block) { - struct buffer_head *bh; - struct lsbd_block *b; - unsigned int block; - unsigned int i = 0; struct lsbd_sect *sects; unsigned int sectors; unsigned int sectors_max; - unsigned int readed_blocks = 0; + unsigned int i = 0; u32 ptab_checksum; + int ret = 0; + sectors_max = (p->sector_size - sizeof(*b)) / sizeof(sects[0]); - block = p->cur_block; - do { - readed_blocks++; - bh = lsbd_sread(p, block, 0); - if (bh == NULL) - continue; - b = (void *) bh->b_data; + /* + * Process sector -> logical sector mapping firts because + * they are never than lcache. + */ + sects = (void *) (bh->b_data + be32_to_cpu(b->ptab_offset)); + sectors = be32_to_cpu(b->sectors_per_block) - 1; + if (sectors > sectors_max) + sectors = sectors_max; - if (!lsbd_block_verify_ok(p, b)) { - brelse(bh); - lsbd_put_buffer(p, bh); - continue; + ptab_checksum = lsbd_checksum(bh->b_data + + be32_to_cpu(b->ptab_offset), + (p->sectors_per_block - 1) + * sizeof(struct lsbd_sect)); + + if (be32_to_cpu(b->ptab_checksum) == ptab_checksum) { + for (i = 0; i < sectors; i++) { + u32 cksum; + unsigned int sector_id; + + sector_id = be32_to_cpu(sects[i].id); + if (sector_id == LSBD_SECT_INVALID) + continue; + + cksum = be32_to_cpu(sects[i].data_checksum); + if (lsbd_check_sector(p, block, i, cksum)) + ret = -EIO; } + } else { + ret = -EIO; + lsbd_info(p, "block %d: ptab checksum error\n", block); + } + return ret; +} - /* - * Process sector -> logical sector mapping firts because - * they are never than lcache. - */ - sects = (void *) (bh->b_data + be32_to_cpu(b->ptab_offset)); - sectors = be32_to_cpu(b->sectors_per_block) - 1; - if (sectors > sectors_max) - sectors = sectors_max; +/* + * lsbd_check_block - check specified block + * + * This function check checks data checksums of specified block. + * + * Currently lcache checksum is not checked. + */ +static int lsbd_check_block(struct lsbd *p, unsigned int block) +{ + struct buffer_head *bh; + struct lsbd_block *b; + int ret = -EIO; - ptab_checksum = lsbd_checksum(bh->b_data - + be32_to_cpu(b->ptab_offset), - (p->sectors_per_block - 1) - * sizeof(struct lsbd_sect)); + bh = lsbd_sread(p, block, 0); + if (bh == NULL) + goto out; - if (be32_to_cpu(b->ptab_checksum) == ptab_checksum) { - for (i = 0; i < sectors; i++) { - u32 cksum; - unsigned int sector_id; + b = (void *) bh->b_data; + if (!lsbd_block_verify_ok(p, b)) + goto out_relse; - sector_id = be32_to_cpu(sects[i].id); - if (sector_id == LSBD_SECT_INVALID) - continue; + ret = lsbd_check_data_sectors(p, bh, b, block); - cksum = be32_to_cpu(sects[i].data_checksum); - lsbd_check_sector(p, block, i, cksum); - } - } else { - lsbd_info(p, "block %d: ptab checksum error\n", - block); - } +out_relse: + brelse(bh); + lsbd_put_buffer(p, bh); +out: + return ret; +} - brelse(bh); - lsbd_put_buffer(p, bh); - } while ((readed_blocks < 4) - && ((block = block_prev(p, block)) != p->cur_block)); +/** + * lsbd_check_sectors - check recently written sectors + * @p: LSBD device + */ +static int lsbd_check_sectors(struct lsbd *p) +{ + unsigned int block; + unsigned int readed_blocks = 0; + + block = p->cur_block; + do { + readed_blocks++; + + lsbd_check_block(p, block); + block = block_prev(p, block); + } while ((readed_blocks < 4) && (block != p->cur_block)); lsbd_info(p, "sector checking finished\n"); return 0; -- 1.8.4.652.g0d6e0ce