summaryrefslogtreecommitdiffstats
path: root/sys/geom/vinum
diff options
context:
space:
mode:
authorle <le@FreeBSD.org>2004-11-26 12:31:36 +0000
committerle <le@FreeBSD.org>2004-11-26 12:31:36 +0000
commitc2bd948f6822dbbdb059d792f1e6150a26618d4f (patch)
tree73b2f06a9c68badfecce3952b7fda1b373c9d6b5 /sys/geom/vinum
parent1ce692dc6551a683467623fc437c34f027de50d1 (diff)
downloadFreeBSD-src-c2bd948f6822dbbdb059d792f1e6150a26618d4f.zip
FreeBSD-src-c2bd948f6822dbbdb059d792f1e6150a26618d4f.tar.gz
Implement 'setstate' to allow setting the state of drives and subdisks
for debugging and emergency purposes.
Diffstat (limited to 'sys/geom/vinum')
-rw-r--r--sys/geom/vinum/geom_vinum.c3
-rw-r--r--sys/geom/vinum/geom_vinum.h1
-rw-r--r--sys/geom/vinum/geom_vinum_state.c83
3 files changed, 82 insertions, 5 deletions
diff --git a/sys/geom/vinum/geom_vinum.c b/sys/geom/vinum/geom_vinum.c
index 5a54bee..7b5b456 100644
--- a/sys/geom/vinum/geom_vinum.c
+++ b/sys/geom/vinum/geom_vinum.c
@@ -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");
}
diff --git a/sys/geom/vinum/geom_vinum.h b/sys/geom/vinum/geom_vinum.h
index c215e2e..15216dc 100644
--- a/sys/geom/vinum/geom_vinum.h
+++ b/sys/geom/vinum/geom_vinum.h
@@ -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 *);
diff --git a/sys/geom/vinum/geom_vinum_state.c b/sys/geom/vinum/geom_vinum_state.c
index 4e17108..6913a4b 100644
--- a/sys/geom/vinum/geom_vinum_state.c
+++ b/sys/geom/vinum/geom_vinum_state.c
@@ -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) &&
OpenPOWER on IntegriCloud