Implement 'setstate' to allow setting the state of drives and subdisks
for debugging and emergency purposes.
This commit is contained in:
parent
3514b3b581
commit
997337fd20
@ -59,6 +59,7 @@ void gvinum_parityop(int, char **, int);
|
||||
void gvinum_printconfig(int, char **);
|
||||
void gvinum_rm(int, char **);
|
||||
void gvinum_saveconfig(void);
|
||||
void gvinum_setstate(int, char **);
|
||||
void gvinum_start(int, char **);
|
||||
void gvinum_stop(int, char **);
|
||||
void parseline(int, char **);
|
||||
@ -481,6 +482,61 @@ gvinum_init(int argc, char **argv)
|
||||
gvinum_list(0, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gvinum_setstate(int argc, char **argv)
|
||||
{
|
||||
struct gctl_req *req;
|
||||
int flags, i;
|
||||
const char *errstr;
|
||||
|
||||
flags = 0;
|
||||
|
||||
optreset = 1;
|
||||
optind = 1;
|
||||
|
||||
while ((i = getopt(argc, argv, "f")) != -1) {
|
||||
switch (i) {
|
||||
case 'f':
|
||||
flags |= GV_FLAG_F;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
warn("invalid flag: %c", i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 2) {
|
||||
warnx("usage: setstate [-f] <state> <obj>");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: This hack is needed to avoid tripping over (now) invalid
|
||||
* 'classic' vinum states and will go away later.
|
||||
*/
|
||||
if (strcmp(argv[0], "up") && strcmp(argv[0], "down") &&
|
||||
strcmp(argv[0], "stale")) {
|
||||
warnx("invalid state '%s'", argv[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
req = gctl_get_handle();
|
||||
gctl_ro_param(req, "class", -1, "VINUM");
|
||||
gctl_ro_param(req, "verb", -1, "setstate");
|
||||
gctl_ro_param(req, "state", -1, argv[0]);
|
||||
gctl_ro_param(req, "object", -1, argv[1]);
|
||||
gctl_ro_param(req, "flags", sizeof(int), &flags);
|
||||
|
||||
errstr = gctl_issue(req);
|
||||
if (errstr != NULL)
|
||||
warnx("%s", errstr);
|
||||
gctl_free(req);
|
||||
}
|
||||
|
||||
void
|
||||
gvinum_list(int argc, char **argv)
|
||||
{
|
||||
@ -801,6 +857,8 @@ parseline(int argc, char **argv)
|
||||
gvinum_rm(argc, argv);
|
||||
else if (!strcmp(argv[0], "saveconfig"))
|
||||
gvinum_saveconfig();
|
||||
else if (!strcmp(argv[0], "setstate"))
|
||||
gvinum_setstate(argc, argv);
|
||||
else if (!strcmp(argv[0], "start"))
|
||||
gvinum_start(argc, argv);
|
||||
else if (!strcmp(argv[0], "stop"))
|
||||
|
@ -512,6 +512,9 @@ gv_config(struct gctl_req *req, struct g_class *mp, char const *verb)
|
||||
} else if (!strcmp(verb, "start")) {
|
||||
gv_start_obj(gp, req);
|
||||
|
||||
} else if (!strcmp(verb, "setstate")) {
|
||||
gv_setstate(gp, req);
|
||||
|
||||
} else
|
||||
gctl_error(req, "Unknown verb parameter");
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ void gv_remove(struct g_geom *, struct gctl_req *);
|
||||
|
||||
/* geom_vinum_state.c */
|
||||
int gv_sdstatemap(struct gv_plex *);
|
||||
void gv_setstate(struct g_geom *, struct gctl_req *);
|
||||
int gv_set_drive_state(struct gv_drive *, int, int);
|
||||
int gv_set_sd_state(struct gv_sd *, int, int);
|
||||
void gv_update_sd_state(struct gv_sd *);
|
||||
|
@ -37,7 +37,78 @@ __FBSDID("$FreeBSD$");
|
||||
#include <geom/vinum/geom_vinum.h>
|
||||
#include <geom/vinum/geom_vinum_share.h>
|
||||
|
||||
/* Update drive state; return 1 if the state changes, otherwise 0. */
|
||||
void
|
||||
gv_setstate(struct g_geom *gp, struct gctl_req *req)
|
||||
{
|
||||
struct gv_softc *sc;
|
||||
struct gv_sd *s;
|
||||
struct gv_drive *d;
|
||||
char *obj, *state;
|
||||
int err, f, *flags, newstate, type;
|
||||
|
||||
f = 0;
|
||||
obj = gctl_get_param(req, "object", NULL);
|
||||
if (obj == NULL) {
|
||||
gctl_error(req, "no object given");
|
||||
return;
|
||||
}
|
||||
|
||||
state = gctl_get_param(req, "state", NULL);
|
||||
if (state == NULL) {
|
||||
gctl_error(req, "no state given");
|
||||
return;
|
||||
}
|
||||
|
||||
flags = gctl_get_paraml(req, "flags", sizeof(*flags));
|
||||
if (flags == NULL) {
|
||||
gctl_error(req, "no flags given");
|
||||
return;
|
||||
}
|
||||
|
||||
if (*flags & GV_FLAG_F)
|
||||
f = GV_SETSTATE_FORCE;
|
||||
|
||||
sc = gp->softc;
|
||||
type = gv_object_type(sc, obj);
|
||||
switch (type) {
|
||||
case GV_TYPE_VOL:
|
||||
case GV_TYPE_PLEX:
|
||||
gctl_error(req, "volume or plex state cannot be set currently");
|
||||
break;
|
||||
|
||||
case GV_TYPE_SD:
|
||||
newstate = gv_sdstatei(state);
|
||||
if (newstate < 0) {
|
||||
gctl_error(req, "invalid subdisk state '%s'", state);
|
||||
break;
|
||||
}
|
||||
s = gv_find_sd(sc, obj);
|
||||
err = gv_set_sd_state(s, newstate, f);
|
||||
if (err)
|
||||
gctl_error(req, "cannot set subdisk state");
|
||||
break;
|
||||
|
||||
case GV_TYPE_DRIVE:
|
||||
newstate = gv_drivestatei(state);
|
||||
if (newstate < 0) {
|
||||
gctl_error(req, "invalid drive state '%s'", state);
|
||||
break;
|
||||
}
|
||||
d = gv_find_drive(sc, obj);
|
||||
err = gv_set_drive_state(d, newstate, f);
|
||||
if (err)
|
||||
gctl_error(req, "cannot set drive state");
|
||||
break;
|
||||
|
||||
default:
|
||||
gctl_error(req, "unknown object '%s'", obj);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Update drive state; return 0 if the state changes, otherwise -1. */
|
||||
int
|
||||
gv_set_drive_state(struct gv_drive *d, int newstate, int flags)
|
||||
{
|
||||
@ -49,12 +120,12 @@ gv_set_drive_state(struct gv_drive *d, int newstate, int flags)
|
||||
oldstate = d->state;
|
||||
|
||||
if (newstate == oldstate)
|
||||
return (1);
|
||||
return (0);
|
||||
|
||||
/* We allow to take down an open drive only with force. */
|
||||
if ((newstate == GV_DRIVE_DOWN) && gv_is_open(d->geom) &&
|
||||
(!(flags & GV_SETSTATE_FORCE)))
|
||||
return (0);
|
||||
return (-1);
|
||||
|
||||
d->state = newstate;
|
||||
|
||||
@ -67,7 +138,7 @@ gv_set_drive_state(struct gv_drive *d, int newstate, int flags)
|
||||
if (flags & GV_SETSTATE_CONFIG)
|
||||
gv_save_config_all(d->vinumconf);
|
||||
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -130,6 +201,8 @@ gv_set_sd_state(struct gv_sd *s, int newstate, int flags)
|
||||
|
||||
if (p->org != GV_PLEX_RAID5)
|
||||
break;
|
||||
else if (flags & GV_SETSTATE_FORCE)
|
||||
break;
|
||||
else
|
||||
s->state = GV_SD_STALE;
|
||||
|
||||
@ -145,7 +218,7 @@ gv_set_sd_state(struct gv_sd *s, int newstate, int flags)
|
||||
* first.
|
||||
*/
|
||||
p = s->plex_sc;
|
||||
if (p == NULL)
|
||||
if (p == NULL || flags & GV_SETSTATE_FORCE)
|
||||
break;
|
||||
|
||||
if ((p->org != GV_PLEX_RAID5) &&
|
||||
|
Loading…
x
Reference in New Issue
Block a user