diff options
author | mav <mav@FreeBSD.org> | 2012-05-06 11:32:36 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2012-05-06 11:32:36 +0000 |
commit | 3d44dd0fea21a2108201e4e627a1ebb119cebdd4 (patch) | |
tree | ed63d20aa23c227e8285daf4feea70a2afa5a6d7 | |
parent | fd59ebc4f06a04b79a039c0d4b908b07693f886e (diff) | |
download | FreeBSD-src-3d44dd0fea21a2108201e4e627a1ebb119cebdd4.zip FreeBSD-src-3d44dd0fea21a2108201e4e627a1ebb119cebdd4.tar.gz |
Add support for RAID5R. Slightly improve support for RAIDMDF.
-rw-r--r-- | sbin/geom/class/raid/graid.8 | 6 | ||||
-rw-r--r-- | sys/geom/raid/g_raid.c | 1 | ||||
-rw-r--r-- | sys/geom/raid/g_raid.h | 6 | ||||
-rw-r--r-- | sys/geom/raid/md_ddf.c | 36 | ||||
-rw-r--r-- | sys/geom/raid/tr_raid5.c | 38 |
5 files changed, 63 insertions, 24 deletions
diff --git a/sbin/geom/class/raid/graid.8 b/sbin/geom/class/raid/graid.8 index 3885f48..92127dd 100644 --- a/sbin/geom/class/raid/graid.8 +++ b/sbin/geom/class/raid/graid.8 @@ -215,7 +215,7 @@ volumes per array, partitions per disk, etc. 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. diff --git a/sys/geom/raid/g_raid.c b/sys/geom/raid/g_raid.c index 646a48c..c3b627f 100644 --- a/sys/geom/raid/g_raid.c +++ b/sys/geom/raid/g_raid.c @@ -1856,6 +1856,7 @@ g_raid_create_volume(struct g_raid_softc *sc, const char *name, int id) 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); diff --git a/sys/geom/raid/g_raid.h b/sys/geom/raid/g_raid.h index 9def96d..a981f2a 100644 --- a/sys/geom/raid/g_raid.h +++ b/sys/geom/raid/g_raid.h @@ -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. */ diff --git a/sys/geom/raid/md_ddf.c b/sys/geom/raid/md_ddf.c index c9eb705..7d3bdae 100644 --- a/sys/geom/raid/md_ddf.c +++ b/sys/geom/raid/md_ddf.c @@ -1517,7 +1517,7 @@ g_raid_md_ddf_supported(int level, int qual, int disks, int force) 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) 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_object *md, 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_object *md, struct g_raid_volume *tvol, 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) diff --git a/sys/geom/raid/tr_raid5.c b/sys/geom/raid/tr_raid5.c index 19b2943..a8f946b 100644 --- a/sys/geom/raid/tr_raid5.c +++ b/sys/geom/raid/tr_raid5.c @@ -112,10 +112,11 @@ g_raid_tr_taste_raid5(struct g_raid_tr_object *tr, struct g_raid_volume *vol) } 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_raid_tr_object *tr, struct bio *bp) 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_raid_tr_object *tr, struct bio *bp) 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_raid_tr_object *tr, struct bio *bp) 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_raid_tr_object *tr, struct bio *bp) 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_raid_tr_object *tr, struct bio *bp) } 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_raid_tr_object *tr, struct bio *bp) 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 |