From a8e84d6ff0491588c0e2263889f4ae38392a71c8 Mon Sep 17 00:00:00 2001
From: Krzysztof Mazur <krzysiek@podlesie.net>
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 <krzysiek@podlesie.net>
---
 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

