NeilBrown: restripe: add support for new layouts including DDF

Martin F. Krafft madduck at alioth.debian.org
Wed Jan 27 02:02:54 UTC 2010


Module: mdadm
Branch: upstream
Commit: e0d95aac9626badd1b849ce4f99f9c406d55beae
URL:    http://git.debian.org/?p=pkg-mdadm/mdadm.git;a=commit;h=e0d95aac9626badd1b849ce4f99f9c406d55beae

Author: NeilBrown <neilb at suse.de>
Date:   Mon May 25 10:52:31 2009 +1000

restripe: add support for new layouts including DDF

md supports new raid6 layouts to support conversion to and from
raid5 and well as DDF.  Make sure restripe handles those, including
getting the order right for Q-syndrome calculation.

Signed-off-by: NeilBrown <neilb at suse.de>

---

 restripe.c |  130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 125 insertions(+), 5 deletions(-)

diff --git a/restripe.c b/restripe.c
index 509b450..416d023 100644
--- a/restripe.c
+++ b/restripe.c
@@ -30,7 +30,8 @@
  *
  */
 
-static int geo_map(int block, unsigned long long stripe, int raid_disks, int level, int layout)
+static int geo_map(int block, unsigned long long stripe, int raid_disks,
+		   int level, int layout)
 {
 	/* On the given stripe, find which disk in the array will have
 	 * block numbered 'block'.
@@ -42,6 +43,7 @@ static int geo_map(int block, unsigned long long stripe, int raid_disks, int lev
 	switch(level*100 + layout) {
 	case 000:
 	case 400:
+	case 500 + ALGORITHM_PARITY_N:
 		/* raid 4 isn't messed around by parity blocks */
 		if (block == -1)
 			return raid_disks-1; /* parity block */
@@ -70,6 +72,65 @@ static int geo_map(int block, unsigned long long stripe, int raid_disks, int lev
 		if (block == -1) return pd;
 		return (pd + 1 + block) % raid_disks;
 
+	case 500 + ALGORITHM_PARITY_0:
+		return block + 1;
+
+
+	case 600 + ALGORITHM_PARITY_N_6:
+		if (block == -2)
+			return raid_disks - 1;
+		if (block == -1)
+			return raid_disks - 2; /* parity block */
+		return block;
+	case 600 + ALGORITHM_LEFT_ASYMMETRIC_6:
+		if (block == -2)
+			return raid_disks - 1;
+		raid_disks--;
+		pd = (raid_disks-1) - stripe % raid_disks;
+		if (block == -1) return pd;
+		if (block >= pd)
+			block++;
+		return block;
+
+	case 600 + ALGORITHM_RIGHT_ASYMMETRIC_6:
+		if (block == -2)
+			return raid_disks - 1;
+		raid_disks--;
+		pd = stripe % raid_disks;
+		if (block == -1) return pd;
+		if (block >= pd)
+			block++;
+		return block;
+
+	case 600 + ALGORITHM_LEFT_SYMMETRIC_6:
+		if (block == -2)
+			return raid_disks - 1;
+		raid_disks--;
+		pd = (raid_disks - 1) - stripe % raid_disks;
+		if (block == -1) return pd;
+		return (pd + 1 + block) % raid_disks;
+
+	case 600 + ALGORITHM_RIGHT_SYMMETRIC_6:
+		if (block == -2)
+			return raid_disks - 1;
+		raid_disks--;
+		pd = stripe % raid_disks;
+		if (block == -1) return pd;
+		return (pd + 1 + block) % raid_disks;
+
+	case 600 + ALGORITHM_PARITY_0_6:
+		if (block == -2)
+			return raid_disks - 1;
+		return block + 1;
+
+
+	case 600 + ALGORITHM_PARITY_0:
+		if (block == -1)
+			return 0;
+		if (block == -2)
+			return 1;
+		return block + 2;
+
 	case 600 + ALGORITHM_LEFT_ASYMMETRIC:
 		pd = raid_disks - 1 - (stripe % raid_disks);
 		if (block == -1) return pd;
@@ -80,6 +141,8 @@ static int geo_map(int block, unsigned long long stripe, int raid_disks, int lev
 			return block+2;
 		return block;
 
+	case 600 + ALGORITHM_ROTATING_ZERO_RESTART:
+		/* Different order for calculating Q, otherwize same as ... */
 	case 600 + ALGORITHM_RIGHT_ASYMMETRIC:
 		pd = stripe % raid_disks;
 		if (block == -1) return pd;
@@ -101,9 +164,43 @@ static int geo_map(int block, unsigned long long stripe, int raid_disks, int lev
 		if (block == -1) return pd;
 		if (block == -2) return (pd+1) % raid_disks;
 		return (pd + 2 + block) % raid_disks;
+
+
+	case 600 + ALGORITHM_ROTATING_N_RESTART:
+		/* Same a left_asymmetric, by first stripe is
+		 * D D D P Q  rather than
+		 * Q D D D P
+		 */
+		pd = raid_disks - 1 - ((stripe + 1) % raid_disks);
+		if (block == -1) return pd;
+		if (block == -2) return (pd+1) % raid_disks;
+		if (pd == raid_disks - 1)
+			return block+1;
+		if (block >= pd)
+			return block+2;
+		return block;
+
+	case 600 + ALGORITHM_ROTATING_N_CONTINUE:
+		/* Same as left_symmetric but Q is before P */
+		pd = raid_disks - 1 - (stripe % raid_disks);
+		if (block == -1) return pd;
+		if (block == -2) return (pd+raid_disks-1) % raid_disks;
+		return (pd + 1 + block) % raid_disks;
 	}
 	return -1;
 }
+static int is_ddf(int layout)
+{
+	switch (layout)
+	{
+	default:
+		return 0;
+	case ALGORITHM_ROTATING_N_CONTINUE:
+	case ALGORITHM_ROTATING_N_RESTART:
+	case ALGORITHM_ROTATING_ZERO_RESTART:
+		return 1;
+	}
+}
 
 
 static void xor_blocks(char *target, char **sources, int disks, int size)
@@ -205,16 +302,20 @@ int restore_stripes(int *dest, unsigned long long *offsets,
 	char *stripe_buf = malloc(raid_disks * chunk_size);
 	char **stripes = malloc(raid_disks * sizeof(char*));
 	char **blocks = malloc(raid_disks * sizeof(char*));
+	char *zero = malloc(chunk_size);
 	int i;
 
 	int data_disks = raid_disks - (level == 0 ? 0 : level <=5 ? 1 : 2);
 
-	if (stripe_buf == NULL || stripes == NULL || blocks == NULL) {
+	if (stripe_buf == NULL || stripes == NULL || blocks == NULL
+	    || zero == NULL) {
 		free(stripe_buf);
 		free(stripes);
 		free(blocks);
+		free(zero);
 		return -2;
 	}
+	memset(zero, 0, chunk_size);
 	for (i=0; i<raid_disks; i++)
 		stripes[i] = stripe_buf + i * chunk_size;
 	while (length > 0) {
@@ -226,7 +327,6 @@ int restore_stripes(int *dest, unsigned long long *offsets,
 		for (i=0; i < data_disks; i++) {
 			int disk = geo_map(i, start/chunk_size/data_disks,
 					   raid_disks, level, layout);
-			blocks[i] = stripes[disk];
 			if (lseek64(source, read_offset, 0) != read_offset)
 				return -1;
 			if (read(source, stripes[disk], chunk_size) != chunk_size)
@@ -240,6 +340,8 @@ int restore_stripes(int *dest, unsigned long long *offsets,
 		case 5:
 			disk = geo_map(-1, start/chunk_size/data_disks,
 					   raid_disks, level, layout);
+			for (i = 0; i < data_disks; i++)
+				blocks[i] = stripes[(disk+1+i) % raid_disks];
 			xor_blocks(stripes[disk], blocks, data_disks, chunk_size);
 			break;
 		case 6:
@@ -247,9 +349,27 @@ int restore_stripes(int *dest, unsigned long long *offsets,
 				       raid_disks, level, layout);
 			qdisk = geo_map(-2, start/chunk_size/data_disks,
 				       raid_disks, level, layout);
-
-			qsyndrome(stripes[disk], stripes[qdisk], blocks,
-				  data_disks, chunk_size);
+			if (is_ddf(layout)) {
+				/* q over 'raid_disks' blocks, in device order.
+				 * 'p' and 'q' get to be all zero
+				 */
+				for (i = 0; i < raid_disks; i++)
+					if (i == disk || i == qdisk)
+						blocks[i] = zero;
+					else
+						blocks[i] = stripes[i];
+				qsyndrome(stripes[disk], stripes[qdisk],
+					  blocks, raid_disks, chunk_size);
+			} else {
+				/* for md' q is over 'data_disks' blocks,
+				 * starting immediately after 'q'
+				 */
+				for (i = 0; i < data_disks; i++)
+					blocks[i] = stripes[(qdisk+1+i) % raid_disks];
+
+				qsyndrome(stripes[disk], stripes[qdisk], blocks,
+					  data_disks, chunk_size);
+			}
 			break;
 		}
 		for (i=0; i < raid_disks ; i++)




More information about the pkg-mdadm-commits mailing list