Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 6 May 2012 11:32:37 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r235076 - in head: sbin/geom/class/raid sys/geom/raid
Message-ID:  <201205061132.q46BWbVq012106@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Sun May  6 11:32:36 2012
New Revision: 235076
URL: http://svn.freebsd.org/changeset/base/235076

Log:
  Add support for RAID5R. Slightly improve support for RAIDMDF.

Modified:
  head/sbin/geom/class/raid/graid.8
  head/sys/geom/raid/g_raid.c
  head/sys/geom/raid/g_raid.h
  head/sys/geom/raid/md_ddf.c
  head/sys/geom/raid/tr_raid5.c

Modified: head/sbin/geom/class/raid/graid.8
==============================================================================
--- head/sbin/geom/class/raid/graid.8	Sun May  6 11:02:53 2012	(r235075)
+++ head/sbin/geom/class/raid/graid.8	Sun May  6 11:32:36 2012	(r235076)
@@ -215,7 +215,7 @@ volumes per array, partitions per disk, 
 The following configurations are supported: RAID0 (2+ disks), RAID1 (2+ disks),
 RAID1E (3+ disks), RAID3 (3+ disks), RAID4 (3+ disks), RAID5 (3+ disks),
 RAID5E (4+ disks), RAID5EE (4+ disks), RAID5R (3+ disks), RAID6 (4+ disks),
-RAIDMDF (5+ disks), RAID10 (4+ disks), SINGLE (1 disk), CONCAT (2+ disks).
+RAIDMDF (4+ disks), RAID10 (4+ disks), SINGLE (1 disk), CONCAT (2+ disks).
 .Pp
 Format supports two options "BE" and "LE", that mean big-endian byte order
 defined by specification (default) and little-endian used by some Adaptec
@@ -264,8 +264,8 @@ to be used.
 Full support for the following RAID levels is currently implemented:
 RAID0, RAID1, RAID1E, RAID10, SINGLE, CONCAT.
 The following RAID levels supported as read-only for volumes in optimal
-state (without using redundancy): RAID4, RAID5, RAID5E, RAID5EE, RAID6,
-RAIDMDF.
+state (without using redundancy): RAID4, RAID5, RAID5E, RAID5EE, RAID5R,
+RAID6, RAIDMDF.
 .Sh RAID LEVEL MIGRATION
 The GEOM RAID class has no support for RAID level migration, allowed by some
 metadata formats.

Modified: head/sys/geom/raid/g_raid.c
==============================================================================
--- head/sys/geom/raid/g_raid.c	Sun May  6 11:02:53 2012	(r235075)
+++ head/sys/geom/raid/g_raid.c	Sun May  6 11:32:36 2012	(r235076)
@@ -1856,6 +1856,7 @@ g_raid_create_volume(struct g_raid_softc
 	vol->v_state = G_RAID_VOLUME_S_STARTING;
 	vol->v_raid_level = G_RAID_VOLUME_RL_UNKNOWN;
 	vol->v_raid_level_qualifier = G_RAID_VOLUME_RLQ_UNKNOWN;
+	vol->v_rotate_parity = 1;
 	bioq_init(&vol->v_inflight);
 	bioq_init(&vol->v_locked);
 	LIST_INIT(&vol->v_locks);

Modified: head/sys/geom/raid/g_raid.h
==============================================================================
--- head/sys/geom/raid/g_raid.h	Sun May  6 11:02:53 2012	(r235075)
+++ head/sys/geom/raid/g_raid.h	Sun May  6 11:32:36 2012	(r235076)
@@ -278,7 +278,13 @@ struct g_raid_volume {
 	u_int			 v_raid_level;	/* Array RAID level. */
 	u_int			 v_raid_level_qualifier; /* RAID level det. */
 	u_int			 v_disks_count;	/* Number of disks in array. */
+	u_int			 v_mdf_pdisks;	/* Number of parity disks
+						   in RAIDMDF array. */
+	uint16_t		 v_mdf_polynomial; /* Polynomial for RAIDMDF. */
+	uint8_t			 v_mdf_method;	/* Generation method for RAIDMDF. */
 	u_int			 v_strip_size;	/* Array strip size. */
+	u_int			 v_rotate_parity; /* Rotate RAID5R parity
+						   after numer of stripes. */
 	u_int			 v_sectorsize;	/* Volume sector size. */
 	off_t			 v_mediasize;	/* Volume media size.  */
 	struct bio_queue_head	 v_inflight;	/* In-flight write requests. */

Modified: head/sys/geom/raid/md_ddf.c
==============================================================================
--- head/sys/geom/raid/md_ddf.c	Sun May  6 11:02:53 2012	(r235075)
+++ head/sys/geom/raid/md_ddf.c	Sun May  6 11:32:36 2012	(r235076)
@@ -1517,7 +1517,7 @@ g_raid_md_ddf_supported(int level, int q
 		    qual != G_RAID_VOLUME_RLQ_RMDFLA &&
 		    qual != G_RAID_VOLUME_RLQ_RMDFLS)
 			return (0);
-		if (disks < 5)
+		if (disks < 4)
 			return (0);
 		break;
 	case G_RAID_VOLUME_RL_RAID1E:
@@ -1850,6 +1850,13 @@ g_raid_md_ddf_start(struct g_raid_volume
 	vol->v_strip_size = vol->v_sectorsize << GET8(vmeta, vdc->Stripe_Size);
 	vol->v_disks_count = GET16(vmeta, vdc->Primary_Element_Count) *
 	    GET8(vmeta, vdc->Secondary_Element_Count);
+	vol->v_mdf_pdisks = GET8(vmeta, vdc->MDF_Parity_Disks);
+	vol->v_mdf_polynomial = GET16(vmeta, vdc->MDF_Parity_Generator_Polynomial);
+	vol->v_mdf_method = GET8(vmeta, vdc->MDF_Constant_Generation_Method);
+	if (GET8(vmeta, vdc->Rotate_Parity_count) > 31)
+		vol->v_rotate_parity = 1;
+	else
+		vol->v_rotate_parity = 1 << GET8(vmeta, vdc->Rotate_Parity_count);
 	vol->v_mediasize = GET64(vmeta, vdc->VD_Size) * vol->v_sectorsize;
 	for (i = 0, j = 0, bvd = 0; i < vol->v_disks_count; i++, j++) {
 		if (j == GET16(vmeta, vdc->Primary_Element_Count)) {
@@ -2430,16 +2437,24 @@ g_raid_md_ctl_ddf(struct g_raid_md_objec
 			vol->v_mediasize = size;
 		else if (level == G_RAID_VOLUME_RL_RAID3 ||
 		    level == G_RAID_VOLUME_RL_RAID4 ||
-		    level == G_RAID_VOLUME_RL_RAID5 ||
-		    level == G_RAID_VOLUME_RL_RAID5R)
+		    level == G_RAID_VOLUME_RL_RAID5)
 			vol->v_mediasize = size * (numdisks - 1);
-		else if (level == G_RAID_VOLUME_RL_RAID6 ||
+		else if (level == G_RAID_VOLUME_RL_RAID5R) {
+			vol->v_mediasize = size * (numdisks - 1);
+			vol->v_rotate_parity = 1024;
+		} else if (level == G_RAID_VOLUME_RL_RAID6 ||
 		    level == G_RAID_VOLUME_RL_RAID5E ||
 		    level == G_RAID_VOLUME_RL_RAID5EE)
 			vol->v_mediasize = size * (numdisks - 2);
-		else if (level == G_RAID_VOLUME_RL_RAIDMDF)
-			vol->v_mediasize = size * (numdisks - 3);
-		else { /* RAID1E */
+		else if (level == G_RAID_VOLUME_RL_RAIDMDF) {
+			if (numdisks < 5)
+				vol->v_mdf_pdisks = 2;
+			else
+				vol->v_mdf_pdisks = 3;
+			vol->v_mdf_polynomial = 0x11d;
+			vol->v_mdf_method = 0x00;
+			vol->v_mediasize = size * (numdisks - vol->v_mdf_pdisks);
+		} else { /* RAID1E */
 			vol->v_mediasize = ((size * numdisks) / strip / 2) *
 			    strip;
 		}
@@ -2761,6 +2776,13 @@ g_raid_md_write_ddf(struct g_raid_md_obj
 		SET64(vmeta, vdc->Block_Count, 0);
 		SET64(vmeta, vdc->VD_Size, vol->v_mediasize / vol->v_sectorsize);
 		SET16(vmeta, vdc->Block_Size, vol->v_sectorsize);
+		SET8(vmeta, vdc->Rotate_Parity_count,
+		    fls(vol->v_rotate_parity) - 1);
+		SET8(vmeta, vdc->MDF_Parity_Disks, vol->v_mdf_pdisks);
+		SET16(vmeta, vdc->MDF_Parity_Generator_Polynomial,
+		    vol->v_mdf_polynomial);
+		SET8(vmeta, vdc->MDF_Constant_Generation_Method,
+		    vol->v_mdf_method);
 
 		SET16(vmeta, vde->VD_Number, vol->v_global_id);
 		if (vol->v_state <= G_RAID_VOLUME_S_BROKEN)

Modified: head/sys/geom/raid/tr_raid5.c
==============================================================================
--- head/sys/geom/raid/tr_raid5.c	Sun May  6 11:02:53 2012	(r235075)
+++ head/sys/geom/raid/tr_raid5.c	Sun May  6 11:32:36 2012	(r235076)
@@ -112,10 +112,11 @@ g_raid_tr_taste_raid5(struct g_raid_tr_o
 	} else if ((tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID5 ||
 	     tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID5E ||
 	     tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID5EE ||
+	     tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID5R ||
 	     tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAID6 ||
 	     tr->tro_volume->v_raid_level == G_RAID_VOLUME_RL_RAIDMDF) &&
 	    qual >= 0 && qual <= 3) {
-		/* RAID5/5E/5EE/6/MDF */
+		/* RAID5/5E/5EE/5R/6/MDF */
 	} else
 		return (G_RAID_TR_TASTE_FAIL);
 	trs->trso_starting = 1;
@@ -210,7 +211,7 @@ g_raid_tr_iostart_raid5_read(struct g_ra
 	struct bio *cbp;
 	char *addr;
 	off_t offset, start, length, nstripe, remain;
-	int no, pno, ddisks, pdisks;
+	int no, pno, ddisks, pdisks, protate, pleft;
 	u_int strip_size, lvl, qual;
 
 	vol = tr->tro_volume;
@@ -218,6 +219,7 @@ g_raid_tr_iostart_raid5_read(struct g_ra
 	strip_size = vol->v_strip_size;
 	lvl = tr->tro_volume->v_raid_level;
 	qual = tr->tro_volume->v_raid_level_qualifier;
+	protate = tr->tro_volume->v_rotate_parity;
 
 	/* Stripe number. */
 	nstripe = bp->bio_offset / strip_size;
@@ -225,7 +227,7 @@ g_raid_tr_iostart_raid5_read(struct g_ra
 	start = bp->bio_offset % strip_size;
 	/* Number of data and parity disks. */
 	if (lvl == G_RAID_VOLUME_RL_RAIDMDF)
-		pdisks = 3;
+		pdisks = tr->tro_volume->v_mdf_pdisks;
 	else if (lvl == G_RAID_VOLUME_RL_RAID5EE ||
 	    lvl == G_RAID_VOLUME_RL_RAID6)
 		pdisks = 2;
@@ -238,8 +240,10 @@ g_raid_tr_iostart_raid5_read(struct g_ra
 			pno = 0;
 		else			/* PN */
 			pno = ddisks;
+		pleft = -1;
 	} else {
-		pno = (nstripe / ddisks) % vol->v_disks_count;
+		pno = (nstripe / (ddisks * protate)) % vol->v_disks_count;
+		pleft = protate - (nstripe / ddisks) % protate;
 		if (qual >= 2) {	/* PN/Left */
 			pno = ddisks - pno;
 			if (pno < 0)
@@ -281,11 +285,14 @@ g_raid_tr_iostart_raid5_read(struct g_ra
 		} else if (qual & 1) {	/* Continuation/Symmetric */
 			no %= vol->v_disks_count;
 			if (no == pno) {
-				if (qual < 2)	/* P0/Right */
-					pno++;
-				else		/* PN/Left */
-					pno += vol->v_disks_count - 1;
-				pno %= vol->v_disks_count;
+				if ((--pleft) <= 0) {
+					pleft += protate;
+					if (qual < 2)	/* P0/Right */
+						pno++;
+					else		/* PN/Left */
+						pno += vol->v_disks_count - 1;
+					pno %= vol->v_disks_count;
+				}
 				no = (pno + pdisks) % vol->v_disks_count;
 				offset += strip_size;
 			}
@@ -294,11 +301,14 @@ g_raid_tr_iostart_raid5_read(struct g_ra
 				no += pdisks;
 			if (no >= vol->v_disks_count) {
 				no -= vol->v_disks_count;
-				if (qual < 2)	/* P0/Right */
-					pno++;
-				else		/* PN/Left */
-					pno += vol->v_disks_count - 1;
-				pno %= vol->v_disks_count;
+				if ((--pleft) <= 0) {
+					pleft += protate;
+					if (qual < 2)	/* P0/Right */
+						pno++;
+					else		/* PN/Left */
+						pno += vol->v_disks_count - 1;
+					pno %= vol->v_disks_count;
+				}
 				if (no == pno)
 					no += pdisks;
 				else



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201205061132.q46BWbVq012106>