summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/geom/class/raid/geom_raid.c3
-rw-r--r--sbin/geom/class/raid/graid.811
-rw-r--r--sys/geom/raid/g_raid.c7
-rw-r--r--sys/geom/raid/g_raid.h3
-rw-r--r--sys/geom/raid/g_raid_ctl.c2
-rw-r--r--sys/geom/raid/g_raid_md_if.m19
-rw-r--r--sys/geom/raid/md_ddf.c46
7 files changed, 74 insertions, 17 deletions
diff --git a/sbin/geom/class/raid/geom_raid.c b/sbin/geom/class/raid/geom_raid.c
index 2f16295..d3383bc 100644
--- a/sbin/geom/class/raid/geom_raid.c
+++ b/sbin/geom/class/raid/geom_raid.c
@@ -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,
{
diff --git a/sbin/geom/class/raid/graid.8 b/sbin/geom/class/raid/graid.8
index 75c0bd9..108b3b9 100644
--- a/sbin/geom/class/raid/graid.8
+++ b/sbin/geom/class/raid/graid.8
@@ -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 RAID Disk Data Format v2.0 specification.
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.
diff --git a/sys/geom/raid/g_raid.c b/sys/geom/raid/g_raid.c
index 85074f8..7688ec3 100644
--- a/sys/geom/raid/g_raid.c
+++ b/sys/geom/raid/g_raid.c
@@ -2143,7 +2143,7 @@ g_raid_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
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 g_provider *pp, int flags __unused)
}
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 *format, struct g_geom **gp)
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);
diff --git a/sys/geom/raid/g_raid.h b/sys/geom/raid/g_raid.h
index 1572320..9def96d 100644
--- a/sys/geom/raid/g_raid.h
+++ b/sys/geom/raid/g_raid.h
@@ -382,7 +382,8 @@ const char * g_raid_disk_state2str(int state);
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);
diff --git a/sys/geom/raid/g_raid_ctl.c b/sys/geom/raid/g_raid_ctl.c
index 028aa94..4d0147f 100644
--- a/sys/geom/raid/g_raid_ctl.c
+++ b/sys/geom/raid/g_raid_ctl.c
@@ -88,7 +88,7 @@ g_raid_ctl_label(struct gctl_req *req, struct g_class *mp)
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);
diff --git a/sys/geom/raid/g_raid_md_if.m b/sys/geom/raid/g_raid_md_if.m
index 05e9f66..3fcbab4 100644
--- a/sys/geom/raid/g_raid_md_if.m
+++ b/sys/geom/raid/g_raid_md_if.m
@@ -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;
diff --git a/sys/geom/raid/md_ddf.c b/sys/geom/raid/md_ddf.c
index 08d6f4b..068f7fa 100644
--- a/sys/geom/raid/md_ddf.c
+++ b/sys/geom/raid/md_ddf.c
@@ -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_free_volume_ddf;
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 ddf_meta *sample)
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, struct ddf_meta *sample)
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_disk *disk)
}
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_object *md, struct g_class *mp,
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_object *md, struct g_class *mp,
}
/* 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_object *md, struct g_class *mp,
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_object *md, struct g_class *mp,
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_object *md, struct g_class *mp,
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_object *md, struct g_class *mp,
} 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;
OpenPOWER on IntegriCloud