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.
This commit is contained in:
parent
62cde8b2a2
commit
6a0688c8fd
@ -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,
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -49,12 +49,21 @@ 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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user