kern/99186: [PATCH] Gvinum dumpconfig/setstate/stop implementation
Ulf Lilleengen
lulf at stud.ntnu.no
Mon Jun 19 20:00:38 UTC 2006
>Number: 99186
>Category: kern
>Synopsis: [PATCH] Gvinum dumpconfig/setstate/stop implementation
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Mon Jun 19 20:00:35 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator: Ulf Lilleengen
>Release: FreeBSD 7.0-CURRENT i386
>Organization:
>Environment:
System: FreeBSD vimes.studby.ntnu.no 7.0-CURRENT FreeBSD 7.0-CURRENT #6: Fri Jun 2 20:19:30 CEST 2006 lulf at vimes.studby.ntnu.no:/usr/obj/usr/src/sys/VIMES i386
>Description:
This patch does the following:
- Add gv_set_plex_state and gv_set_vol_state to make the setstate
command be able to set the states of volumes and plexes.
- Add a gv_plexdown function to count number of plexes down, used in
gv_set_plex_state.
- Add all these functions to geom_vinum.h.
- Add gv_dump_config to geom_vinum_subr.c
- Add gv_read_config to geom_vinum_drive.c
- Add gvinum_dumpconfig to sbin/gvinum/gvinum.c
- Add gvinum dumpconfig option.
- Add geom_vinum_stop.c, and add it to the build.
- geom_vinum_stop.c will contain code to stop gvinum objects.
- Add gv_stop_obj, for use by the gvinum stop option.
- The stop option now supports stopping invidual objects. The force flag
is also considered. Make gvinum.c in sbin/gvinum support this, and not
unload the kernel module if arguments are given.
- Add description of stop option to help.
Patch AND geom_vinum_stop.c attached (Not sure if having _stop.c in a
separate file, but i imagine i can put more stuff there later so).
>How-To-Repeat:
>Fix:
--- gvinum_patch.diff begins here ---
Index: sys/geom/vinum/geom_vinum.c
===================================================================
RCS file: /home/ncvs/src/sys/geom/vinum/geom_vinum.c,v
retrieving revision 1.21
diff -u -r1.21 geom_vinum.c
--- geom_vinum.c 30 Mar 2006 14:01:25 -0000 1.21
+++ geom_vinum.c 19 Jun 2006 19:45:01 -0000
@@ -411,6 +411,9 @@
gctl_set_param(req, "config", sbuf_data(sb), sbuf_len(sb) + 1);
sbuf_delete(sb);
+ } else if (!strcmp(verb, "dumpconfig")) {
+ gv_dump_config(sc, req);
+
} else if (!strcmp(verb, "create")) {
gv_create(gp, req);
@@ -432,6 +435,9 @@
} else if (!strcmp(verb, "start")) {
gv_start_obj(gp, req);
+ } else if (!strcmp(verb, "stop")) {
+ gv_stop_obj(gp, req);
+
} else if (!strcmp(verb, "setstate")) {
gv_setstate(gp, req);
Index: sys/geom/vinum/geom_vinum.h
===================================================================
RCS file: /home/ncvs/src/sys/geom/vinum/geom_vinum.h,v
retrieving revision 1.12
diff -u -r1.12 geom_vinum.h
--- geom_vinum.h 30 Mar 2006 14:01:25 -0000 1.12
+++ geom_vinum.h 19 Jun 2006 19:45:01 -0000
@@ -35,6 +35,7 @@
void gv_config_new_drive(struct gv_drive *);
void gv_drive_modify(struct gv_drive *);
void gv_save_config_all(struct gv_softc *);
+void gv_read_config(struct gv_drive *, struct sbuf *);
void gv_save_config(struct g_consumer *, struct gv_drive *,
struct gv_softc *);
@@ -63,13 +64,19 @@
/* geom_vinum_state.c */
int gv_sdstatemap(struct gv_plex *);
+int gv_plexdown(struct gv_volume *);
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);
+int gv_set_plex_state(struct gv_plex *, int, int);
+int gv_set_vol_state(struct gv_volume *, int, int);
void gv_update_sd_state(struct gv_sd *);
void gv_update_plex_state(struct gv_plex *);
void gv_update_vol_state(struct gv_volume *);
+/* geom_vinum_stop.c */
+void gv_stop_obj(struct g_geom *, struct gctl_req *);
+
/* geom_vinum_subr.c */
void gv_adjust_freespace(struct gv_sd *, off_t);
void gv_free_sd(struct gv_sd *);
@@ -79,6 +86,7 @@
struct gv_sd *gv_find_sd(struct gv_softc *, char *);
struct gv_volume *gv_find_vol(struct gv_softc *, char *);
void gv_format_config(struct gv_softc *, struct sbuf *, int, char *);
+void gv_dump_config(struct gv_softc *, struct gctl_req *);
int gv_is_striped(struct gv_plex *);
int gv_is_open(struct g_geom *);
void gv_kill_drive_thread(struct gv_drive *);
Index: sys/geom/vinum/geom_vinum_drive.c
===================================================================
RCS file: /home/ncvs/src/sys/geom/vinum/geom_vinum_drive.c,v
retrieving revision 1.25
diff -u -r1.25 geom_vinum_drive.c
--- geom_vinum_drive.c 6 Jan 2006 18:03:17 -0000 1.25
+++ geom_vinum_drive.c 19 Jun 2006 19:45:01 -0000
@@ -98,6 +98,45 @@
}
}
+/* Read the vinum configuration from disk */
+void
+gv_read_config(struct gv_drive *d, struct sbuf *sb)
+{
+ struct gv_plex *p;
+ struct gv_sd *s;
+ struct gv_volume *v;
+ struct gv_softc *vinumconf;
+
+ KASSERT(d != NULL, ("gv_read_config: null d"));
+ vinumconf = d->vinumconf;
+ sbuf_printf(sb, "Drive %s:\tDevice /dev/%s\n", d->name, d->device);
+ sbuf_printf(sb, "\t\t\tSize:\t %jd bytes (%jd MB)\n", (intmax_t)d->size,
+ (intmax_t)d->size / MEGABYTE);
+ LIST_FOREACH(v, &vinumconf->volumes, volume)
+ sbuf_printf(sb, "volume %s state %s\n", v->name,
+ gv_volstate(v->state));
+ LIST_FOREACH(p, &vinumconf->plexes, plex) {
+ sbuf_printf(sb, "plex name %s state %s org %s ", p->name,
+ gv_plexstate(p->state), gv_plexorg(p->org));
+ if (gv_is_striped(p))
+ sbuf_printf(sb, "%ds ", p->stripesize / 512);
+ if (p->vol_sc != NULL)
+ sbuf_printf(sb, "vol %s", p->volume);
+ }
+ LIST_FOREACH(s, &vinumconf->subdisks, sd) {
+ sbuf_printf(sb, "sd name %s drive %s len %jds "
+ "driveoffset %jds state %s", s->name, s->drive,
+ s->size / 512, s->drive_offset / 512,
+ gv_sdstate(s->state));
+ if (s->plex_sc != NULL)
+ sbuf_printf(sb, " plex %s plexoffset %jds",
+ s->plex, s->plex_offset / 512);
+ sbuf_printf(sb, "\n");
+ }
+ sbuf_printf(sb, "\nDrive /dev/%s: %jd MB (%jd bytes)\n", d->device,
+ (intmax_t)d->size / MEGABYTE, (intmax_t)d->size);
+}
+
/* Save the vinum configuration back to disk. */
void
gv_save_config(struct g_consumer *cp, struct gv_drive *d, struct gv_softc *sc)
Index: sys/geom/vinum/geom_vinum_state.c
===================================================================
RCS file: /home/ncvs/src/sys/geom/vinum/geom_vinum_state.c,v
retrieving revision 1.8
diff -u -r1.8 geom_vinum_state.c
--- geom_vinum_state.c 30 Mar 2006 14:01:25 -0000 1.8
+++ geom_vinum_state.c 19 Jun 2006 19:45:01 -0000
@@ -43,6 +43,8 @@
struct gv_softc *sc;
struct gv_sd *s;
struct gv_drive *d;
+ struct gv_plex *p;
+ struct gv_volume *v;
char *obj, *state;
int err, f, *flags, newstate, type;
@@ -72,8 +74,27 @@
type = gv_object_type(sc, obj);
switch (type) {
case GV_TYPE_VOL:
+ newstate = gv_volstatei(state);
+ if (newstate < 0) {
+ gctl_error(req, "invalid volume state '%s'", state);
+ break;
+ }
+ v = gv_find_vol(sc, obj);
+ err = gv_set_vol_state(v, newstate, f);
+ if (err)
+ gctl_error(req, "cannot set volume state");
+ break;
+
case GV_TYPE_PLEX:
- gctl_error(req, "volume or plex state cannot be set currently");
+ newstate = gv_plexstatei(state);
+ if (newstate < 0) {
+ gctl_error(req, "invalid plex state '%s'", state);
+ break;
+ }
+ p = gv_find_plex(sc, obj);
+ err = gv_set_plex_state(p, newstate, f);
+ if (err)
+ gctl_error(req, "cannot set plex state");
break;
case GV_TYPE_SD:
@@ -288,6 +309,81 @@
gv_update_plex_state(s->plex_sc);
}
+int
+gv_set_plex_state(struct gv_plex *p, int newstate, int flags)
+{
+ struct gv_volume *v;
+ struct gv_sd *s;
+ int oldstate, plexdown;
+
+ KASSERT(p != NULL, ("gv_set_plex_state: NULL p"));
+
+ oldstate = p->state;
+ v = p->vol_sc;
+ plexdown = 0;
+
+ if (newstate == oldstate)
+ return (0);
+
+ switch (newstate) {
+ case GV_PLEX_UP:
+ /* Let update_plex handle if the plex can come up */
+ gv_update_plex_state(p); /* XXX: Should return error if fail */
+ break;
+
+ case GV_PLEX_DOWN:
+ if (v != NULL) {
+ /* If the only one, or only one up, force is needed. */
+ plexdown = gv_plexdown(v);
+ if (((v->plexcount == 1) ||
+ ((v->plexcount - plexdown) == 1)) &&
+ ((flags & GV_SETSTATE_FORCE) == 0))
+ return (-1);
+ }
+ p->state = newstate;
+ /* Force down all subdisks. */
+ LIST_FOREACH(s, &p->subdisks, sd) {
+ if ((s->state == GV_SD_UP ||
+ s->state == GV_SD_REVIVING) &&
+ s->plex_sc == p) {
+ gv_set_sd_state(s, GV_SD_DOWN, flags);
+ }
+ }
+ break;
+
+ /*
+ * Added this for potential use internally as in vinum. We
+ * really do trust ourselves here.
+ */
+ case GV_PLEX_DEGRADED:
+ p->state = newstate;
+ LIST_FOREACH(s, &p->subdisks, sd) {
+ if ((s->state == GV_SD_UP ||
+ s->state == GV_SD_REVIVING) &&
+ s->plex_sc == p) {
+ gv_set_sd_state(s, GV_SD_DOWN, flags);
+ }
+ }
+ break;
+
+ case GV_PLEX_INITIALIZING:
+ /* XXX: As with vinum, consider what safeguards we need here */
+ if ((flags & GV_SETSTATE_FORCE) == 0)
+ return (-1);
+ p->state = newstate;
+ break;
+ }
+
+ /* Update our volume, if we have one. */
+ if (v != NULL)
+ gv_update_vol_state(v);
+
+ /* Save config */
+ if (flags & GV_SETSTATE_CONFIG)
+ gv_save_config_all(v->vinumconf);
+ return (0);
+}
+
/* Update the state of a plex based on its environment. */
void
gv_update_plex_state(struct gv_plex *p)
@@ -332,6 +428,40 @@
gv_update_vol_state(p->vol_sc);
}
+int
+gv_set_vol_state(struct gv_volume *v, int newstate, int flags)
+{
+ int oldstate;
+
+ KASSERT(v != NULL, ("gv_set_vol_state: NULL v"));
+
+ oldstate = v->state;
+
+ if (newstate == oldstate)
+ return (0);
+
+ switch (newstate) {
+ case GV_VOL_UP:
+ /* Let update handle if the volume can come up */
+ gv_update_vol_state(v); /* XXX: Should return error for this. */
+ break;
+ case GV_VOL_DOWN:
+ /*
+ * Set state to GV_VOL_DOWN only if noone is using the volume,
+ * or if the state should be forced.
+ */
+ if ((gv_is_open(v->geom) != 0) &&
+ ((flags & GV_SETSTATE_FORCE) == 0))
+ return (-1);
+ v->state = newstate;
+ break;
+ }
+ /* Save config */
+ if (flags & GV_SETSTATE_CONFIG)
+ gv_save_config_all(v->vinumconf);
+ return (0);
+}
+
/* Update the volume state based on its plexes. */
void
gv_update_vol_state(struct gv_volume *v)
@@ -364,6 +494,32 @@
v->state = GV_VOL_DOWN;
}
+/* Walk over plexes in a volume and count how many are down. */
+int
+gv_plexdown(struct gv_volume *v)
+{
+ int plexdown;
+ struct gv_plex *p;
+
+ KASSERT(v != NULL, ("gv_plexdown: NULL v"));
+
+ plexdown = 0;
+
+ LIST_FOREACH(p, &v->plexes, plex) {
+ switch (p->state) {
+ case GV_PLEX_DOWN:
+ plexdown++;
+ break;
+ case GV_PLEX_DEGRADED:
+ case GV_PLEX_UP:
+ plexdown--;
+ break;
+ }
+ }
+
+ return (plexdown);
+}
+
/* Return a state map for the subdisks of a plex. */
int
gv_sdstatemap(struct gv_plex *p)
Index: sys/geom/vinum/geom_vinum_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/geom/vinum/geom_vinum_subr.c,v
retrieving revision 1.15
diff -u -r1.15 geom_vinum_subr.c
--- geom_vinum_subr.c 30 Mar 2006 14:01:25 -0000 1.15
+++ geom_vinum_subr.c 19 Jun 2006 19:45:01 -0000
@@ -169,6 +169,63 @@
}
}
+/* Get configuration from all disks */
+void
+gv_dump_config(struct gv_softc *sc, struct gctl_req *req)
+{
+ struct gv_drive *d;
+ struct sbuf *sb;
+ int *argc, drives, i, type;
+ char *object, buf[64];
+
+ drives = 0;
+ i = 0;
+ argc = gctl_get_paraml(req, "argc", sizeof(*argc));
+ if (argc == NULL || *argc == 0) {
+ gctl_error(req, "No argument given");
+ return;
+ }
+
+ if (*argc > 1) {
+ /* Only if argument is specified */
+ sb = sbuf_new(NULL, NULL, GV_CFG_LEN * (*argc), SBUF_FIXEDLEN);
+ for (i = 0; i < *argc; i++) {
+ snprintf(buf, sizeof(buf), "argv%d", i);
+ object = gctl_get_param(req, buf, NULL);
+ if (object == NULL)
+ continue;
+ type = gv_object_type(sc, object);
+ if (type == GV_TYPE_DRIVE) {
+ d = gv_find_drive(sc, object);
+ gv_read_config(d, sb);
+ } else {
+ LIST_FOREACH(d, &sc->drives, drive) {
+ snprintf(buf, sizeof(buf), "/dev/%s",
+ d->device);
+ if (!strcmp(d->device, object) ||
+ !strcmp(buf, object)) {
+ gv_read_config(d, sb);
+ }
+ }
+ }
+ }
+ } else {
+ /*
+ * First count number of drives, then allocate enough space for
+ * them.
+ */
+ LIST_FOREACH(d, &sc->drives, drive)
+ drives++;
+ sb = sbuf_new(NULL, NULL, GV_CFG_LEN * drives, SBUF_FIXEDLEN);
+ LIST_FOREACH(d, &sc->drives, drive) {
+ gv_read_config(d, sb);
+ }
+ }
+ sbuf_finish(sb);
+ gctl_set_param(req, "config", sbuf_data(sb), sbuf_len(sb) + 1);
+ sbuf_delete(sb);
+}
+
/*
* Format the vinum configuration properly. If ondisk is non-zero then the
* configuration is intended to be written to disk later.
Index: sys/modules/geom/geom_vinum/Makefile
===================================================================
RCS file: /home/ncvs/src/sys/modules/geom/geom_vinum/Makefile,v
retrieving revision 1.4
diff -u -r1.4 Makefile
--- Makefile 24 Nov 2005 15:11:41 -0000 1.4
+++ Makefile 19 Jun 2006 19:47:22 -0000
@@ -6,7 +6,7 @@
SRCS= geom_vinum.c geom_vinum_drive.c geom_vinum_plex.c \
geom_vinum_volume.c geom_vinum_subr.c geom_vinum_raid5.c \
geom_vinum_share.c geom_vinum_list.c geom_vinum_rm.c \
- geom_vinum_init.c geom_vinum_state.c geom_vinum_rename.c \
- geom_vinum_move.c
+ geom_vinum_init.c geom_vinum_state.c geom_vinum_stop.c \
+ geom_vinum_rename.c geom_vinum_move.c
.include <bsd.kmod.mk>
Index: sbin/gvinum/gvinum.c
===================================================================
RCS file: /home/ncvs/src/sbin/gvinum/gvinum.c,v
retrieving revision 1.8
diff -u -r1.8 gvinum.c
--- gvinum.c 23 Mar 2006 19:58:43 -0000 1.8
+++ gvinum.c 19 Jun 2006 19:50:41 -0000
@@ -55,6 +55,7 @@
#include "gvinum.h"
void gvinum_create(int, char **);
+void gvinum_dumpconfig(FILE *, int, char **);
void gvinum_help(void);
void gvinum_list(int, char **);
void gvinum_move(int, char **);
@@ -323,6 +324,32 @@
gvinum_list(0, NULL);
}
+/* Dump config from specified disk drives */
+void
+gvinum_dumpconfig(FILE *of, int argc, char **argv)
+{
+ char buf[(GV_CFG_LEN * 4) + 1];
+ const char *errstr;
+ struct gctl_req *req;
+ int i;
+
+ req = gctl_get_handle();
+ gctl_ro_param(req, "class", -1, "VINUM");
+ gctl_ro_param(req, "verb", -1, "dumpconfig");
+ gctl_ro_param(req, "argc", sizeof(int), &argc);
+ gctl_rw_param(req, "config", sizeof(buf), buf);
+
+ for (i = 1; i < argc; i++) {
+ snprintf(buf, sizeof(buf), "argv%d", i);
+ gctl_ro_param(req, buf, -1, argv[i]);
+ }
+ errstr = gctl_issue(req);
+ if (errstr != NULL)
+ warnx("can't dump configuration of drive(s): %s", errstr);
+ gctl_free(req);
+ fprintf(of, buf);
+}
+
void
gvinum_help(void)
{
@@ -331,6 +358,9 @@
" Check the parity blocks of a RAID-5 plex.\n"
"create description-file\n"
" Create as per description-file or open editor.\n"
+ "dumpconfig [drive ...]\n"
+ " List the configuration information stored on the\n"
+ " specified drives or all drives if none specified\n"
"l | list [-r] [-v] [-V] [volume | plex | subdisk]\n"
" List information about specified objects.\n"
"ld [-r] [-v] [-V] [volume]\n"
@@ -363,6 +393,9 @@
" poses only.\n"
"start [-S size] volume | plex | subdisk\n"
" Allow the system to access the objects.\n"
+ "stop [-f] volume | plex | subdisk\n"
+ " Terminate access to these objects, or stop gvinum if no"
+ " parameters are specified\n"
);
return;
@@ -839,20 +872,64 @@
void
gvinum_stop(int argc, char **argv)
{
+ struct gctl_req *req;
+ int flags, i;
+ const char *errstr;
+ char buf[30];
int fileid;
- fileid = kldfind(GVINUMMOD);
- if (fileid == -1) {
- warn("cannot find " GVINUMMOD);
- return;
- }
- if (kldunload(fileid) != 0) {
- warn("cannot unload " GVINUMMOD);
- return;
- }
+ flags = 0;
+ i = 0;
+ req = NULL;
- warnx(GVINUMMOD " unloaded");
- exit(0);
+ optreset = 1;
+ optind = 1;
+
+ /* Do not unload the kernel module if we have arguments. */
+ if (argc > 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;
+
+ req = gctl_get_handle();
+ gctl_ro_param(req, "class", -1, "VINUM");
+ gctl_ro_param(req, "verb", -1, "stop");
+ gctl_ro_param(req, "argc", sizeof(int), &argc);
+ gctl_ro_param(req, "flags", sizeof(int), &flags);
+ for (i = 0; i < argc; i++) {
+ snprintf(buf, sizeof(buf), "argv%d", i);
+ gctl_ro_param(req, buf, -1, argv[i]);
+ }
+ errstr = gctl_issue(req);
+ if (errstr != NULL)
+ warnx("can't stop object(s): %s", errstr);
+ gctl_free(req);
+
+ } else {
+ fileid = kldfind(GVINUMMOD);
+ if (fileid == -1) {
+ warn("cannot find " GVINUMMOD);
+ return;
+ }
+ if (kldunload(fileid) != 0) {
+ warn("cannot unload " GVINUMMOD);
+ return;
+ }
+
+ warnx(GVINUMMOD " unloaded");
+ exit(0);
+ }
}
void
@@ -883,6 +960,8 @@
gvinum_move(argc, argv);
else if (!strcmp(argv[0], "printconfig"))
gvinum_printconfig(argc, argv);
+ else if (!strcmp(argv[0], "dumpconfig"))
+ gvinum_dumpconfig(stdout, argc, argv);
else if (!strcmp(argv[0], "rename"))
gvinum_rename(argc, argv);
else if (!strcmp(argv[0], "resetconfig"))
--- gvinum_patch.diff ends here ---
--- geom_vinum_stop.c begins here ---
/*-
* Copyright (c) 2006 Ulf Lilleengen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/libkern.h>
#include <sys/malloc.h>
#include <geom/geom.h>
#include <geom/vinum/geom_vinum_var.h>
#include <geom/vinum/geom_vinum.h>
#include <geom/vinum/geom_vinum_share.h>
void
gv_stop_obj(struct g_geom *gp, struct gctl_req *req)
{
struct gv_softc *sc;
struct gv_volume *v;
struct gv_plex *p;
struct gv_drive *d;
struct gv_sd *s;
char buf[30], *object;
int *argc, i, type, err, *flags, object_flags;
object_flags = GV_SETSTATE_CONFIG; /* Save configuration. */
sc = gp->softc;
argc = gctl_get_paraml(req, "argc", sizeof(*argc));
if (argc == NULL || *argc == 0) {
gctl_error(req, "No arguments given");
return;
}
/* Check if we have the -f flag. */
flags = gctl_get_paraml(req, "flags", sizeof(*flags));
if (*flags & GV_FLAG_F)
object_flags |= GV_SETSTATE_FORCE;
for (i = 0; i < *argc; i++) {
snprintf(buf, sizeof(buf), "argv%d", i);
object = gctl_get_param(req, buf, NULL);
if (object == NULL)
continue;
type = gv_object_type(sc, object);
switch (type) {
case GV_TYPE_VOL:
v = gv_find_vol(sc, object);
err = gv_set_vol_state(v, GV_VOL_DOWN,
object_flags);
if (err) {
gctl_error(req, "cannot stop volume "
"'%s'", object);
return;
}
break;
case GV_TYPE_PLEX:
p = gv_find_plex(sc, object);
err = gv_set_plex_state(p, GV_PLEX_DOWN,
object_flags);
if (err) {
gctl_error(req, "cannot stop plex "
"'%s'", object);
return;
}
break;
case GV_TYPE_SD:
s = gv_find_sd(sc, object);
err = gv_set_sd_state(s, GV_SD_DOWN,
object_flags);
if (err) {
gctl_error(req, "cannot stop sd "
"'%s'", object);
return;
}
break;
case GV_TYPE_DRIVE:
d = gv_find_drive(sc, object);
err = gv_set_drive_state(d, GV_DRIVE_DOWN,
object_flags);
if (err) {
gctl_error(req, "cannot stop drive "
"'%s'", object);
return;
}
break;
default:
gctl_error(req, "unknown object '%s'", object);
break;
}
}
}
--- geom_vinum_stop.c ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list