Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 19 Jun 2006 21:57:32 +0200 (CEST)
From:      Ulf Lilleengen <lulf@stud.ntnu.no>
To:        FreeBSD-gnats-submit@FreeBSD.org
Cc:        le@FreeBSD.org
Subject:   kern/99186: [PATCH] Gvinum dumpconfig/setstate/stop implementation
Message-ID:  <20060619195732.4D81533C3B@studby.ntnu.no>
Resent-Message-ID: <200606192000.k5JK0bop099503@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>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@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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060619195732.4D81533C3B>