New command "gmultipath prefer" to force selection of a specified

provider in an Active/Passive configuration.

Reviewed by:	mav
MFC after:	4 weeks
This commit is contained in:
Thomas Quinot 2012-08-03 14:55:35 +00:00
parent de0627d021
commit 71ee4ef0d9
3 changed files with 108 additions and 1 deletions

View file

@ -49,6 +49,7 @@ uint32_t version = G_MULTIPATH_VERSION;
static void mp_main(struct gctl_req *, unsigned int);
static void mp_label(struct gctl_req *);
static void mp_clear(struct gctl_req *);
static void mp_prefer(struct gctl_req *);
struct g_command class_commands[] = {
{
@ -86,6 +87,10 @@ struct g_command class_commands[] = {
"remove", G_FLAG_VERBOSE, NULL, G_NULL_OPTS,
"[-v] name prov"
},
{
"prefer", G_FLAG_VERBOSE, mp_main, G_NULL_OPTS,
"[-v] prov ..."
},
{
"fail", G_FLAG_VERBOSE, NULL, G_NULL_OPTS,
"[-v] name prov"
@ -131,6 +136,8 @@ mp_main(struct gctl_req *req, unsigned int flags __unused)
mp_label(req);
} else if (strcmp(name, "clear") == 0) {
mp_clear(req);
} else if (strcmp(name, "prefer") == 0) {
mp_prefer(req);
} else {
gctl_error(req, "Unknown command: %s.", name);
}
@ -294,3 +301,22 @@ mp_clear(struct gctl_req *req)
}
}
static void
mp_prefer(struct gctl_req *req)
{
const char *name, *comp, *errstr;
int nargs;
nargs = gctl_get_int(req, "nargs");
if (nargs != 2) {
gctl_error(req, "Usage: prefer GEOM PROVIDER");
return;
}
name = gctl_get_ascii(req, "arg0");
comp = gctl_get_ascii(req, "arg1");
errstr = gctl_issue (req);
if (errstr != NULL) {
fprintf(stderr, "Can't set %s preferred provider to %s: %s.\n",
name, comp, errstr);
}
}

View file

@ -66,6 +66,11 @@
.Op Fl v
.Ar name
.Nm
.Cm prefer
.Op Fl v
.Ar name
.Ar prov
.Nm
.Cm getactive
.Op Fl v
.Ar name
@ -171,7 +176,9 @@ If there are other paths present, new requests will be forwarded there.
Mark specified provider as a path of the specified multipath device as
operational, allowing it to handle requests.
.It Cm rotate
Change the active provider/path in Active/Passive mode.
Change the active provider/path to the next available provider in Active/Passive mode.
.It Cm prefer
Change the active provider/path to the specified provider in Active/Passive mode.
.It Cm getactive
Get the currently active provider(s)/path(s).
.It Cm destroy

View file

@ -848,6 +848,78 @@ g_multipath_ctl_add_name(struct gctl_req *req, struct g_class *mp,
(void) g_multipath_add_disk(gp, pp);
}
static void
g_multipath_ctl_prefer(struct gctl_req *req, struct g_class *mp)
{
struct g_geom *gp;
struct g_multipath_softc *sc;
struct g_consumer *cp;
const char *name, *mpname;
static const char devpf[6] = "/dev/";
int *nargs;
g_topology_assert();
mpname = gctl_get_asciiparam(req, "arg0");
if (mpname == NULL) {
gctl_error(req, "No 'arg0' argument");
return;
}
gp = g_multipath_find_geom(mp, mpname);
if (gp == NULL) {
gctl_error(req, "Device %s is invalid", mpname);
return;
}
sc = gp->softc;
nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
if (nargs == NULL) {
gctl_error(req, "No 'nargs' argument");
return;
}
if (*nargs != 2) {
gctl_error(req, "missing device");
return;
}
name = gctl_get_asciiparam(req, "arg1");
if (name == NULL) {
gctl_error(req, "No 'arg1' argument");
return;
}
if (strncmp(name, devpf, 5) == 0) {
name += 5;
}
LIST_FOREACH(cp, &gp->consumer, consumer) {
if (cp->provider != NULL
&& strcmp(cp->provider->name, name) == 0)
break;
}
if (cp == NULL) {
gctl_error(req, "Provider %s not found", name);
return;
}
mtx_lock(&sc->sc_mtx);
if (cp->index & MP_BAD) {
gctl_error(req, "Consumer %s is invalid", name);
mtx_unlock(&sc->sc_mtx);
return;
}
/* Here when the consumer is present and in good shape */
sc->sc_active = cp;
if (!sc->sc_active_active)
printf("GEOM_MULTIPATH: %s now active path in %s\n",
sc->sc_active->provider->name, sc->sc_name);
mtx_unlock(&sc->sc_mtx);
}
static void
g_multipath_ctl_add(struct gctl_req *req, struct g_class *mp)
{
@ -1278,6 +1350,8 @@ g_multipath_config(struct gctl_req *req, struct g_class *mp, const char *verb)
gctl_error(req, "Userland and kernel parts are out of sync");
} else if (strcmp(verb, "add") == 0) {
g_multipath_ctl_add(req, mp);
} else if (strcmp(verb, "prefer") == 0) {
g_multipath_ctl_prefer(req, mp);
} else if (strcmp(verb, "create") == 0) {
g_multipath_ctl_create(req, mp);
} else if (strcmp(verb, "configure") == 0) {