mirror of
https://github.com/opnsense/src.git
synced 2026-03-01 04:40:53 -05:00
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:
parent
de0627d021
commit
71ee4ef0d9
3 changed files with 108 additions and 1 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue