From owner-svn-src-head@FreeBSD.ORG Sun May 6 11:32:37 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5FDD01065670; Sun, 6 May 2012 11:32:37 +0000 (UTC) (envelope-from mav@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 496D28FC08; Sun, 6 May 2012 11:32:37 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q46BWbtf012112; Sun, 6 May 2012 11:32:37 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q46BWbVq012106; Sun, 6 May 2012 11:32:37 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201205061132.q46BWbVq012106@svn.freebsd.org> From: Alexander Motin Date: Sun, 6 May 2012 11:32:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r235076 - in head: sbin/geom/class/raid sys/geom/raid X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 06 May 2012 11:32:37 -0000 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