Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Jun 2007 20:57:20 GMT
From:      Ulf Lilleengen <lulf@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 121535 for review
Message-ID:  <200706122057.l5CKvKlc084001@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=121535

Change 121535 by lulf@lulf_carrot on 2007/06/12 20:57:13

	- Allow subdisks to be added to raid5 plexes again.
	- Add detach to userland gvinum tool
	- Add gv_detach general request handler for detaching
	- Add gv_detach_sd and gv_detach_plex to detach a subdisk and a plex.
	- Make gv_sd_to_plex use the standard plex-size calculation.
	- Add a sddetached-variable to gv_plex do be able to detect wether a
	  plex misses a subdisk or not. This variable is increased when a
	  subdisk is detached, and increased when a subdisk is attached.
	- Remove weird offset-check with a correct one.
	- Hook it up in the event system.
	- Looks like handling a crashed drive, and replacing it is working so
	  far!  

Affected files ...

.. //depot/projects/soc2007/lulf/gvinum_fixup/sbin/gvinum/gvinum.c#7 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.c#14 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.h#12 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_raid5.c#4 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_subr.c#7 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_var.h#12 edit

Differences ...

==== //depot/projects/soc2007/lulf/gvinum_fixup/sbin/gvinum/gvinum.c#7 (text+ko) ====

@@ -57,6 +57,7 @@
 
 void	gvinum_attach(int, char **);
 void	gvinum_create(int, char **);
+void	gvinum_detach(int, char **);
 void	gvinum_help(void);
 void	gvinum_list(int, char **);
 void	gvinum_move(int, char **);
@@ -362,7 +363,46 @@
 	gvinum_list(0, NULL);
 }
 
+/* Detach a plex or subdisk from its parent. */
 void
+gvinum_detach(int argc, char **argv)
+{
+	const char *errstr;
+	struct gctl_req *req;
+	int flags, i;
+
+	optreset = 1;
+	optind = 1;
+	while ((i = getopt(argc, argv, "f")) != -1) {
+		switch(i) {
+		case 'f':
+			flags |= GV_FLAG_F;
+			break;
+		default:
+			warn("invalid flag: %c", i);
+			return;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	if (argc != 1) {
+		warnx("usage: detach [-f] <subdisk> | <plex>");
+		return;
+	}
+
+	req = gctl_get_handle();
+	gctl_ro_param(req, "class", -1, "VINUM");
+	gctl_ro_param(req, "verb", -1, "detach");
+	gctl_ro_param(req, "object", -1, argv[0]);
+	gctl_ro_param(req, "flags", sizeof(int), &flags);
+
+	errstr = gctl_issue(req);
+	if (errstr != NULL)
+		warnx("detach failed: %s", errstr);
+	gctl_free(req);
+}
+
+void
 gvinum_help(void)
 {
 	printf("COMMANDS\n"
@@ -373,6 +413,9 @@
 	    "attach plex volume [rename]\n"
 	    "attach subdisk plex [offset] [rename]\n"
 	    "        Attach a plex to a volume, or a subdisk to a plex\n"
+	    "detach [-f] [plex | subdisk]\n"
+	    "        Detach a plex or a subdisk from the volume or plex to\n"
+	    "        which it is attached.\n"
 	    "l | list [-r] [-v] [-V] [volume | plex | subdisk]\n"
 	    "        List information about specified objects.\n"
 	    "ld [-r] [-v] [-V] [volume]\n"
@@ -933,6 +976,8 @@
 		exit(0);
 	else if (!strcmp(argv[0], "attach"))
 		gvinum_attach(argc, argv);
+	else if (!strcmp(argv[0], "detach"))
+		gvinum_detach(argc, argv);
 	else if (!strcmp(argv[0], "help"))
 		gvinum_help();
 	else if (!strcmp(argv[0], "list") || !strcmp(argv[0], "l"))

==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.c#14 (text+ko) ====

@@ -52,6 +52,7 @@
 
 int	gv_create(struct g_geom *, struct gctl_req *);
 void	gv_attach(struct gv_softc *, struct gctl_req *);
+void	gv_detach(struct gv_softc *, struct gctl_req *);
 
 static void
 gv_orphan(struct g_consumer *cp)
@@ -239,10 +240,6 @@
 		}
 		p = gv_find_plex(sc, parent);
 		s = gv_find_sd(sc, child);
-		if (p->org == GV_PLEX_RAID5) {
-			gctl_error(req, "cannot add subdisk to a raid5 plex");
-			return;
-		}
 		/* XXX: Rename not supported yet. */
 		gv_post_event(sc, GV_EVENT_ATTACH_SD, s, p, NULL);
 		break;
@@ -252,6 +249,40 @@
 	}
 }
 
+/* Handle userland request of detaching object. */
+void
+gv_detach(struct gv_softc *sc, struct gctl_req *req)
+{
+	struct gv_plex *p;
+	struct gv_sd *s;
+	int *flags, type;
+	char *object;
+
+	object = gctl_get_param(req, "object", NULL);
+	if (object == NULL) {
+		gctl_error(req, "no argument given");
+		return;
+	}
+
+	flags = gctl_get_paraml(req, "flags", sizeof(*flags));
+	type = gv_object_type(sc, object);
+	switch (type) {
+	case GV_TYPE_PLEX:
+		/* XXX: Support flags. */
+		p = gv_find_plex(sc, object);
+		gv_post_event(sc, GV_EVENT_DETACH_PLEX, p, NULL, NULL);
+		break;
+	case GV_TYPE_SD:
+		/* XXX: Support flags. */
+		s = gv_find_sd(sc, object);
+		gv_post_event(sc, GV_EVENT_DETACH_SD, s, NULL, NULL);
+		break;
+	default:
+		gctl_error(req, "invalid object type");
+		break;
+	}
+}
+
 /* Handle userland requests for creating new objects. */
 int
 gv_create(struct g_geom *gp, struct gctl_req *req)
@@ -372,6 +403,9 @@
 	if (!strcmp(verb, "attach")) {
 		gv_attach(sc, req);
 
+	} else if (!strcmp(verb, "detach")) {
+		gv_detach(sc, req);
+
 	} else if (!strcmp(verb, "list")) {
 		gv_list(gp, req);
 
@@ -429,8 +463,8 @@
 
 	vhdr = NULL;
 
+ 	g_topology_assert();
 	g_trace(G_T_TOPOLOGY, "gv_taste(%s, %s)", mp->name, pp->name);
-	g_topology_assert();
 
 	gp = LIST_FIRST(&mp->geom);
 	if (gp == NULL) {
@@ -692,6 +726,24 @@
 					    "%s\n", s->name, p->name);
 				break;
 
+			case GV_EVENT_DETACH_PLEX:
+				printf("VINUM: event 'detach'\n");
+				p = ev->arg1;
+				err = gv_detach_plex(p, 0);
+				if (err)
+					printf("VINUM: error detaching %s\n",
+					    p->name);
+				break;
+
+			case GV_EVENT_DETACH_SD:
+				printf("VINUM: event 'detach'\n");
+				s = ev->arg1;
+				err = gv_detach_sd(s, 0);
+				if (err)
+					printf("VINUM: error detaching %s\n",
+					    s->name);
+				break;
+
 			case GV_EVENT_THREAD_EXIT:
 				printf("VINUM: event 'thread exit'\n");
 				g_free(ev);

==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.h#12 (text+ko) ====

@@ -92,6 +92,8 @@
 int	gv_plexdown(struct gv_volume *);
 int	gv_attach_plex(struct gv_plex *, struct gv_volume *, int);
 int	gv_attach_sd(struct gv_sd *, struct gv_plex *, off_t, int);
+int	gv_detach_plex(struct gv_plex *, int);
+int	gv_detach_sd(struct gv_sd *, int);
 
 void	gv_worker(void *);
 void	gv_post_event(struct gv_softc *, int, void *, void *, void *);

==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_raid5.c#4 (text+ko) ====


==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_subr.c#7 (text+ko) ====

@@ -267,6 +267,7 @@
 gv_sd_to_plex(struct gv_sd *s, struct gv_plex *p)
 {
 	struct gv_sd *s2;
+	off_t psizeorig;
 
 	/* If this subdisk was already given to this plex, do nothing. */
 	if (s->plex_sc == p)
@@ -296,23 +297,6 @@
 			s->plex_offset = 0;
 	}
 
-	p->sdcount++;
-
-	/* Adjust the size of our plex. */
-	switch (p->org) {
-	case GV_PLEX_CONCAT:
-	case GV_PLEX_STRIPED:
-		p->size += s->size;
-		break;
-
-	case GV_PLEX_RAID5:
-		p->size = (p->sdcount - 1) * gv_plex_smallest_sd(p, s->size);
-		break;
-
-	default:
-		break;
-	}
-
 	/* There are no subdisks for this plex yet, just insert it. */
 	if (LIST_EMPTY(&p->subdisks)) {
 		LIST_INSERT_HEAD(&p->subdisks, s, in_plex);
@@ -331,6 +315,23 @@
 	}
 
 	s->plex_sc = p;
+        /* Adjust the size of our plex. We check if the plex misses a subdisk,
+	 * so we don't make the plex smaller than it actually should be.
+	 */
+	psizeorig = p->size;
+	p->size = gv_plex_size(p);
+	/* Make sure the size is not changed. */
+	if (p->sddetached > 0) {
+		if (p->size < psizeorig) {
+			p->size = psizeorig;
+			/* We make sure wee need another subdisk. */
+			if (p->sddetached == 1)
+				p->sddetached++;
+		}
+		p->sddetached--;
+	} else {
+		p->sdcount++;
+	}
 
 	return (0);
 }
@@ -1082,6 +1083,7 @@
 	LIST_INSERT_HEAD(&v->plexes, p, in_volume);
 
 	/* Get plex up again. */
+	gv_update_vol_size(v, gv_vol_size(v));
 	gv_set_plex_state(p, GV_PLEX_UP, 0);
 	gv_save_config(p->vinumconf);
 	return (0);
@@ -1102,15 +1104,15 @@
 	}
 
 	gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE);
-	/* First check that this subdisk doesn't overlap with another of the
-	 * plexes subdisks. */
+	/* First check that this subdisk has a correct offset. If none other
+	 * starts at the same, and it's correct module stripesize, it is */
+	if (offset != -1 && offset % p->stripesize != 0)
+		return (GV_ERR_BADOFFSET);
 	LIST_FOREACH(s2, &p->subdisks, in_plex) {
-		if (((s2->plex_offset > offset) &&
-		    (s2->plex_offset < s->size + offset)) ||
-		    ((offset > s2->plex_offset) &&
-		    (offset < s2->size + s2->plex_offset)))
+		if (s2->plex_offset == offset)
 			return (GV_ERR_BADOFFSET);
 	}
+
 	/* Attach the subdisk to the plex at given offset. */
 	s->plex_offset = offset;
 	strlcpy(s->plex, p->name, GV_MAXPLEXNAME);
@@ -1118,6 +1120,7 @@
 	error = gv_sd_to_plex(s, p);
 	if (error)
 		return (error);
+
 	if (rename) {
 		snprintf(s->name, GV_MAXSDNAME, "%s.%d", s->plex,
 		    p->sdcount - 1);
@@ -1127,3 +1130,65 @@
 	 * initiate a rebuild/sync first. */
 	return (0);
 }
+
+/* Detach a plex from a volume. */
+int
+gv_detach_plex(struct gv_plex *p, int flags)
+{
+	struct gv_volume *v;
+
+	g_topology_assert();
+	v = p->vol_sc;
+
+	if (v == NULL) {
+		printf("VINUM: plex %s already detached\n", p->name);
+		return (0); /* Not an error. */
+	}
+
+	/*
+	 * Only proceed if forced or volume inactive.
+	 * XXX: Safe dropout if we're mirrored. 
+	 */
+	if (!(flags & GV_FLAG_F) && (gv_provider_is_open(v->provider) ||
+	    p->state == GV_PLEX_UP)) {
+		printf("VINUM: volume busy\n");
+		return (GV_ERR_ISOPEN);
+	}
+	v->plexcount--;
+	LIST_REMOVE(p, in_volume);
+	p->vol_sc = NULL;
+	memset(p->volume, 0, GV_MAXVOLNAME);
+	gv_update_vol_size(v, gv_vol_size(v));
+	gv_save_config(p->vinumconf);
+	return (0);
+}
+
+/* Detach a subdisk from a plex. */
+int
+gv_detach_sd(struct gv_sd *s, int flags)
+{
+	struct gv_plex *p;
+
+	g_topology_assert();
+	p = s->plex_sc;
+
+	if (p == NULL) {
+		printf("VINUM: subdisk %s already detached\n", s->name);
+		return (0); /* Not an error. */
+	}
+
+	/*
+	 * Don't proceed if we're not forcing, and the plex is up, or degraded
+	 * with this subdisk up.
+	 */
+	if (!(flags & GV_FLAG_F) && ((p->state != GV_PLEX_DOWN) ||
+	    ((p->state == GV_PLEX_DEGRADED) && (s->state == GV_SD_UP))))
+		return (GV_ERR_ISOPEN);
+
+	LIST_REMOVE(s, in_plex);
+	s->plex_sc = NULL;
+	memset(s->plex, 0, GV_MAXPLEXNAME);
+	p->sddetached++;
+	gv_save_config(s->vinumconf);
+	return (0);
+}

==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_var.h#12 (text+ko) ====

@@ -197,6 +197,8 @@
 #define GV_EVENT_START_VOLUME		21
 #define GV_EVENT_ATTACH_PLEX		22
 #define GV_EVENT_ATTACH_SD		23
+#define GV_EVENT_DETACH_PLEX		24
+#define GV_EVENT_DETACH_SD		25
 
 struct gv_event {
 	int	type;
@@ -311,6 +313,7 @@
 	char	volume[GV_MAXVOLNAME];	/* Name of associated volume. */
 	struct gv_volume *vol_sc;	/* Pointer to associated volume. */
 
+	int	sddetached;		/* Number of detached subdisks. */
 	int	sdcount;		/* Number of subdisks in this plex. */
 	int	sddown;			/* Number of subdisks that are down. */
 	int	flags;



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