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
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to