Author: mav Date: Thu May 3 05:32:56 2012 New Revision: 234940 URL: http://svn.freebsd.org/changeset/base/234940
Log: Add optional -o argument to the `graid label ` to specify some metadata format options. Use it for specifying byte order for the DDF metadata: big-endian defined by specification and little-endian used by Adaptec. Modified: head/sbin/geom/class/raid/geom_raid.c 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/g_raid_ctl.c head/sys/geom/raid/g_raid_md_if.m head/sys/geom/raid/md_ddf.c Modified: head/sbin/geom/class/raid/geom_raid.c ============================================================================== --- head/sbin/geom/class/raid/geom_raid.c Thu May 3 05:04:37 2012 (r234939) +++ head/sbin/geom/class/raid/geom_raid.c Thu May 3 05:32:56 2012 (r234940) @@ -48,11 +48,12 @@ struct g_command class_commands[] = { { "label", G_FLAG_VERBOSE, NULL, { { 'f', "force", NULL, G_TYPE_BOOL }, + { 'o', "fmtopt", G_VAL_OPTIONAL, G_TYPE_STRING }, { 'S', "size", G_VAL_OPTIONAL, G_TYPE_NUMBER }, { 's', "strip", G_VAL_OPTIONAL, G_TYPE_NUMBER }, G_OPT_SENTINEL }, - "[-fv] [-S size] [-s stripsize] format label level prov ..." + "[-fv] [-o fmtopt] [-S size] [-s stripsize] format label level prov ..." }, { "add", G_FLAG_VERBOSE, NULL, { Modified: head/sbin/geom/class/raid/graid.8 ============================================================================== --- head/sbin/geom/class/raid/graid.8 Thu May 3 05:04:37 2012 (r234939) +++ head/sbin/geom/class/raid/graid.8 Thu May 3 05:32:56 2012 (r234940) @@ -34,6 +34,7 @@ .Nm .Cm label .Op Fl f +.Op Fl o Ar fmtopt .Op Fl S Ar size .Op Fl s Ar strip .Ar format @@ -119,6 +120,8 @@ Additional options include: .It Fl f Enforce specified configuration creation if it is officially unsupported, but technically can be created. +.It Fl o Ar fmtopt +Specifies metadata format options. .It Fl S Ar size Use .Ar size @@ -205,14 +208,18 @@ The format defined by the SNIA Common RA Used by some Adaptec RAID BIOSes and some hardware RAID controllers. Because of high format flexibility different implementations support different set of features and have different on-disk metadata layouts. -To provide compatibility, the GEOM RAID class mimics capabilities and -metadata layout of the first detected DDF array. +To provide compatibility, the GEOM RAID class mimics capabilities +of the first detected DDF array. Respecting that, it may support different number of disks per volume, 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). +.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 +controllers. .It Intel The format used by Intel RAID BIOS. Supports up to two volumes per array. Modified: head/sys/geom/raid/g_raid.c ============================================================================== --- head/sys/geom/raid/g_raid.c Thu May 3 05:04:37 2012 (r234939) +++ head/sys/geom/raid/g_raid.c Thu May 3 05:32:56 2012 (r234940) @@ -2143,7 +2143,7 @@ g_raid_taste(struct g_class *mp, struct g_trace(G_T_TOPOLOGY, "%s(%s, %s)", __func__, mp->name, pp->name); G_RAID_DEBUG(2, "Tasting provider %s.", pp->name); - gp = g_new_geomf(mp, "mirror:taste"); + gp = g_new_geomf(mp, "raid:taste"); /* * This orphan function should be never called. */ @@ -2173,7 +2173,8 @@ g_raid_taste(struct g_class *mp, struct } int -g_raid_create_node_format(const char *format, struct g_geom **gp) +g_raid_create_node_format(const char *format, struct gctl_req *req, + struct g_geom **gp) { struct g_raid_md_class *class; struct g_raid_md_object *obj; @@ -2191,7 +2192,7 @@ g_raid_create_node_format(const char *fo obj = (void *)kobj_create((kobj_class_t)class, M_RAID, M_WAITOK); obj->mdo_class = class; - status = G_RAID_MD_CREATE(obj, &g_raid_class, gp); + status = G_RAID_MD_CREATE_REQ(obj, &g_raid_class, req, gp); if (status != G_RAID_MD_TASTE_NEW) kobj_delete((kobj_t)obj, M_RAID); return (status); Modified: head/sys/geom/raid/g_raid.h ============================================================================== --- head/sys/geom/raid/g_raid.h Thu May 3 05:04:37 2012 (r234939) +++ head/sys/geom/raid/g_raid.h Thu May 3 05:32:56 2012 (r234940) @@ -382,7 +382,8 @@ const char * g_raid_disk_state2str(int s struct g_raid_softc * g_raid_create_node(struct g_class *mp, const char *name, struct g_raid_md_object *md); -int g_raid_create_node_format(const char *format, struct g_geom **gp); +int g_raid_create_node_format(const char *format, struct gctl_req *req, + struct g_geom **gp); struct g_raid_volume * g_raid_create_volume(struct g_raid_softc *sc, const char *name, int id); struct g_raid_disk * g_raid_create_disk(struct g_raid_softc *sc); Modified: head/sys/geom/raid/g_raid_ctl.c ============================================================================== --- head/sys/geom/raid/g_raid_ctl.c Thu May 3 05:04:37 2012 (r234939) +++ head/sys/geom/raid/g_raid_ctl.c Thu May 3 05:32:56 2012 (r234940) @@ -88,7 +88,7 @@ g_raid_ctl_label(struct gctl_req *req, s gctl_error(req, "No format recieved."); return; } - crstatus = g_raid_create_node_format(format, &geom); + crstatus = g_raid_create_node_format(format, req, &geom); if (crstatus == G_RAID_MD_TASTE_FAIL) { gctl_error(req, "Failed to create array with format '%s'.", format); Modified: head/sys/geom/raid/g_raid_md_if.m ============================================================================== --- head/sys/geom/raid/g_raid_md_if.m Thu May 3 05:04:37 2012 (r234939) +++ head/sys/geom/raid/g_raid_md_if.m Thu May 3 05:32:56 2012 (r234940) @@ -49,13 +49,22 @@ HEADER { # Default implementations of methods. CODE { static int - g_raid_md_create_default(struct g_raid_md_object *md) + g_raid_md_create_default(struct g_raid_md_object *md, + struct g_class *mp, struct g_geom **gp) { return (G_RAID_MD_TASTE_FAIL); } static int + g_raid_md_create_req_default(struct g_raid_md_object *md, + struct g_class *mp, struct gctl_req *req, struct g_geom **gp) + { + + return (G_RAID_MD_CREATE(md, mp, gp)); + } + + static int g_raid_md_ctl_default(struct g_raid_md_object *md, struct gctl_req *req) { @@ -95,6 +104,14 @@ METHOD int create { struct g_geom **gp; } DEFAULT g_raid_md_create_default; +# create_req() - create new node from scratch, with request argument. +METHOD int create_req { + struct g_raid_md_object *md; + struct g_class *mp; + struct gctl_req *req; + struct g_geom **gp; +} DEFAULT g_raid_md_create_req_default; + # taste() - taste disk and, if needed, create new node. METHOD int taste { struct g_raid_md_object *md; Modified: head/sys/geom/raid/md_ddf.c ============================================================================== --- head/sys/geom/raid/md_ddf.c Thu May 3 05:04:37 2012 (r234939) +++ head/sys/geom/raid/md_ddf.c Thu May 3 05:32:56 2012 (r234940) @@ -88,6 +88,7 @@ struct g_raid_md_ddf_pervolume { struct g_raid_md_ddf_object { struct g_raid_md_object mdio_base; + u_int mdio_bigendian; struct ddf_meta mdio_meta; int mdio_starting; struct callout mdio_start_co; /* STARTING state timer. */ @@ -95,7 +96,7 @@ struct g_raid_md_ddf_object { struct root_hold_token *mdio_rootmount; /* Root mount delay token. */ }; -static g_raid_md_create_t g_raid_md_create_ddf; +static g_raid_md_create_req_t g_raid_md_create_req_ddf; static g_raid_md_taste_t g_raid_md_taste_ddf; static g_raid_md_event_t g_raid_md_event_ddf; static g_raid_md_volume_event_t g_raid_md_volume_event_ddf; @@ -107,7 +108,7 @@ static g_raid_md_free_volume_t g_raid_md static g_raid_md_free_t g_raid_md_free_ddf; static kobj_method_t g_raid_md_ddf_methods[] = { - KOBJMETHOD(g_raid_md_create, g_raid_md_create_ddf), + KOBJMETHOD(g_raid_md_create_req, g_raid_md_create_req_ddf), KOBJMETHOD(g_raid_md_taste, g_raid_md_taste_ddf), KOBJMETHOD(g_raid_md_event, g_raid_md_event_ddf), KOBJMETHOD(g_raid_md_volume_event, g_raid_md_volume_event_ddf), @@ -562,6 +563,7 @@ ddf_meta_create(struct g_raid_disk *disk struct timespec ts; struct clocktime ct; struct g_raid_md_ddf_perdisk *pd; + struct g_raid_md_ddf_object *mdi; struct ddf_meta *meta; struct ddf_pd_entry *pde; off_t anchorlba; @@ -572,13 +574,14 @@ ddf_meta_create(struct g_raid_disk *disk if (sample->hdr == NULL) sample = NULL; + mdi = (struct g_raid_md_ddf_object *)disk->d_softc->sc_md; pd = (struct g_raid_md_ddf_perdisk *)disk->d_md_data; meta = &pd->pd_meta; ss = disk->d_consumer->provider->sectorsize; anchorlba = disk->d_consumer->provider->mediasize / ss - 1; meta->sectorsize = ss; - meta->bigendian = sample ? sample->bigendian : 0; + meta->bigendian = sample ? sample->bigendian : mdi->mdio_bigendian; getnanotime(&ts); clock_ts_to_ct(&ts, &ct); @@ -2012,11 +2015,26 @@ g_raid_md_ddf_new_disk(struct g_raid_dis } static int -g_raid_md_create_ddf(struct g_raid_md_object *md, struct g_class *mp, - struct g_geom **gp) +g_raid_md_create_req_ddf(struct g_raid_md_object *md, struct g_class *mp, + struct gctl_req *req, struct g_geom **gp) { struct g_geom *geom; struct g_raid_softc *sc; + struct g_raid_md_ddf_object *mdi, *mdi1; + char name[16]; + const char *fmtopt; + int be = 1; + + mdi = (struct g_raid_md_ddf_object *)md; + fmtopt = gctl_get_asciiparam(req, "fmtopt"); + if (fmtopt == NULL || strcasecmp(fmtopt, "BE") == 0) + be = 1; + else if (strcasecmp(fmtopt, "LE") == 0) + be = 0; + else { + gctl_error(req, "Incorrect fmtopt argument."); + return (G_RAID_MD_TASTE_FAIL); + } /* Search for existing node. */ LIST_FOREACH(geom, &mp->geom, geom) { @@ -2027,6 +2045,9 @@ g_raid_md_create_ddf(struct g_raid_md_ob continue; if (sc->sc_md->mdo_class != md->mdo_class) continue; + mdi1 = (struct g_raid_md_ddf_object *)sc->sc_md; + if (mdi1->mdio_bigendian != be) + continue; break; } if (geom != NULL) { @@ -2035,7 +2056,9 @@ g_raid_md_create_ddf(struct g_raid_md_ob } /* Create new one if not found. */ - sc = g_raid_create_node(mp, "DDF", md); + mdi->mdio_bigendian = be; + snprintf(name, sizeof(name), "DDF%s", be ? "" : "-LE"); + sc = g_raid_create_node(mp, name, md); if (sc == NULL) return (G_RAID_MD_TASTE_FAIL); md->mdo_softc = sc; @@ -2053,11 +2076,13 @@ g_raid_md_taste_ddf(struct g_raid_md_obj struct g_raid_disk *disk; struct ddf_meta meta; struct g_raid_md_ddf_perdisk *pd; + struct g_raid_md_ddf_object *mdi; struct g_geom *geom; - int error, result, len; + int error, result, len, be; char name[16]; G_RAID_DEBUG(1, "Tasting DDF on %s", cp->provider->name); + mdi = (struct g_raid_md_ddf_object *)md; pp = cp->provider; /* Read metadata from device. */ @@ -2070,6 +2095,7 @@ g_raid_md_taste_ddf(struct g_raid_md_obj g_access(cp, -1, 0, 0); if (error != 0) return (G_RAID_MD_TASTE_FAIL); + be = meta.bigendian; /* Metadata valid. Print it. */ g_raid_md_ddf_print(&meta); @@ -2084,6 +2110,9 @@ g_raid_md_taste_ddf(struct g_raid_md_obj continue; if (sc->sc_md->mdo_class != md->mdo_class) continue; + mdi = (struct g_raid_md_ddf_object *)sc->sc_md; + if (mdi->mdio_bigendian != be) + continue; break; } @@ -2094,7 +2123,8 @@ g_raid_md_taste_ddf(struct g_raid_md_obj } else { /* Not found matching node -- create one. */ result = G_RAID_MD_TASTE_NEW; - snprintf(name, sizeof(name), "DDF"); + mdi->mdio_bigendian = be; + snprintf(name, sizeof(name), "DDF%s", be ? "" : "-LE"); sc = g_raid_create_node(mp, name, md); md->mdo_softc = sc; geom = sc->sc_geom; _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"