From ad1a3c2f082d90ff050fd089496732f1371900ab Mon Sep 17 00:00:00 2001
From: NeilBrown <neilb@suse.de>
Date: Thu, 16 Jul 2015 11:55:27 +1000
Subject: [PATCH 134/359] raid6check
References: bsc#1081910

fix checking of DDF layouts.

Stuff probably still broken.

Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Coly Li <colyli@suse.de>

---
 raid6check.c | 53 ++++++++++++++++++++++++++++++++++-------------------
 restripe.c   |  5 +++--
 2 files changed, 37 insertions(+), 21 deletions(-)

diff --git a/raid6check.c b/raid6check.c
index a78ac5c..6909b50 100644
--- a/raid6check.c
+++ b/raid6check.c
@@ -40,6 +40,7 @@ enum repair {
 
 int geo_map(int block, unsigned long long stripe, int raid_disks,
 	    int level, int layout);
+int is_ddf(int layout);
 void qsyndrome(uint8_t *p, uint8_t *q, uint8_t **sources, int disks, int size);
 void make_tables(void);
 void ensure_zero_has_size(int chunk_size);
@@ -327,19 +328,21 @@ int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets,
 		  enum repair repair, int failed_disk1, int failed_disk2)
 {
 	/* read the data and p and q blocks, and check we got them right */
+	int data_disks = raid_disks - 2;
+	int syndrome_disks = data_disks + is_ddf(layout) * 2;
 	char *stripe_buf = xmalloc(raid_disks * chunk_size);
 	char **stripes = xmalloc(raid_disks * sizeof(char*));
-	char **blocks = xmalloc(raid_disks * sizeof(char*));
+	char **blocks = xmalloc((syndrome_disks + 2) * sizeof(char*));
 	char **blocks_page = xmalloc(raid_disks * sizeof(char*));
-	int *block_index_for_slot = xmalloc(raid_disks * sizeof(int));
+	int *block_index_for_slot = xmalloc((syndrome_disks+2) * sizeof(int));
 	uint8_t *p = xmalloc(chunk_size);
 	uint8_t *q = xmalloc(chunk_size);
+	char *zero = xmalloc(chunk_size);
 	int *results = xmalloc(chunk_size * sizeof(int));
 	sighandler_t *sig = xmalloc(3 * sizeof(sighandler_t));
 
 	int i, j;
 	int diskP, diskQ, diskD;
-	int data_disks = raid_disks - 2;
 	int err = 0;
 
 	extern int tables_ready;
@@ -347,6 +350,7 @@ int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets,
 	if (!tables_ready)
 		make_tables();
 
+	memset(zero, 0, chunk_size);
 	for ( i = 0 ; i < raid_disks ; i++)
 		stripes[i] = stripe_buf + i * chunk_size;
 
@@ -379,25 +383,36 @@ int check_stripes(struct mdinfo *info, int *source, unsigned long long *offsets,
 
 		diskP = geo_map(-1, start, raid_disks, level, layout);
 		diskQ = geo_map(-2, start, raid_disks, level, layout);
-		/* The syndrome-order if disks starts immediately after 'Q',
-		 * but skips P */
-		diskD = diskQ;
-		for (i = 0 ; i < data_disks ; i++) {
-			diskD = diskD + 1;
-			if (diskD > raid_disks)
-				diskD = 0;
-			if (diskD == diskP)
-				diskD += 1;
-			if (diskD > raid_disks)
-				diskD = 0;
-			blocks[i] = stripes[diskD];
-			block_index_for_slot[diskD] = i;
+		if (!is_ddf(layout)) {
+			/* The syndrome-order of disks starts immediately after 'Q',
+			 * but skips P */
+			diskD = diskQ;
+			for (i = 0 ; i < data_disks ; i++) {
+				diskD = diskD + 1;
+				if (diskD >= raid_disks)
+					diskD = 0;
+				if (diskD == diskP)
+					diskD += 1;
+				if (diskD >= raid_disks)
+					diskD = 0;
+				blocks[i] = stripes[diskD];
+				block_index_for_slot[diskD] = i;
+			}
+		} else {
+			/* The syndrome-order exactly follows raid-disk
+			 * numbers, with ZERO in place of P and Q
+			 */
+			for (i = 0 ; i < raid_disks; i++)
+				if (i == diskP || i == diskQ)
+					blocks[i] = zero;
+				else
+					blocks[i] = stripes[i];
 		}
 
-		qsyndrome(p, q, (uint8_t**)blocks, data_disks, chunk_size);
-		blocks[data_disks] = stripes[diskP];
+		qsyndrome(p, q, (uint8_t**)blocks, syndrome_disks, chunk_size);
+		blocks[syndrome_disks] = stripes[diskP];
 		block_index_for_slot[diskP] = data_disks;
-		blocks[data_disks+1] = stripes[diskQ];
+		blocks[syndrome_disks+1] = stripes[diskQ];
 		block_index_for_slot[diskQ] = data_disks+1;
 
 		raid6_collect(chunk_size, p, q, stripes[diskP], stripes[diskQ], results);
diff --git a/restripe.c b/restripe.c
index 30849b7..40d6061 100644
--- a/restripe.c
+++ b/restripe.c
@@ -194,7 +194,8 @@ int geo_map(int block, unsigned long long stripe, int raid_disks,
 	}
 	return -1;
 }
-static int is_ddf(int layout)
+
+int is_ddf(int layout)
 {
 	switch (layout)
 	{
@@ -883,7 +884,7 @@ unsigned long long getnum(char *str, char **err)
 }
 
 char const Name[] = "test_restripe";
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
 {
 	/* save/restore file raid_disks chunk_size level layout start length devices...
 	 */
-- 
2.16.1

