Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 4 Jun 2007 20:31:07 GMT
From:      Ulf Lilleengen <lulf@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 120928 for review
Message-ID:  <200706042031.l54KV71o067216@repoman.freebsd.org>

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

Change 120928 by lulf@lulf_carrot on 2007/06/04 20:30:43

	- Add attach routine. This is without rename and offset support for now
	  since I need detach to test it. (A bit of a backwards-error I made
	  when deciding to start on attach first.) Both userland support and
	  support for the kernel verbs are added.

Affected files ...

.. //depot/projects/soc2007/lulf/gvinum_fixup/sbin/gvinum/gvinum.c#6 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.c#13 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.h#11 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_subr.c#6 edit
.. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_var.h#11 edit

Differences ...

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

@@ -55,6 +55,7 @@
 
 #include "gvinum.h"
 
+void	gvinum_attach(int, char **);
 void	gvinum_create(int, char **);
 void	gvinum_help(void);
 void	gvinum_list(int, char **);
@@ -112,7 +113,44 @@
 	exit(0);
 }
 
+/* Attach a plex to a volume or a subdisk to a plex. */
 void
+gvinum_attach(int argc, char **argv)
+{
+	struct gctl_req *req;
+	const char *errstr;
+	int rename;
+	off_t offset;
+
+	rename = 0;
+	offset = -1;
+	if (argc < 3) {
+		warnx("usage:\tattach <subdisk> <plex> [rename] "
+		    "[<plexoffset>]\n"
+		    "\tattach <plex> <volume> [rename]");
+	}
+	if (argc > 3) {
+		if (!strcmp(argv[3], "rename")) {
+			rename = 1;
+			if (argc == 5)
+				offset = strtol(argv[4], NULL, 0);
+		} else
+			offset = strtol(argv[3], NULL, 0);
+	}
+	req = gctl_get_handle();
+	gctl_ro_param(req, "class", -1, "VINUM");
+	gctl_ro_param(req, "verb", -1, "attach");
+	gctl_ro_param(req, "child", -1, argv[1]);
+	gctl_ro_param(req, "parent", -1, argv[2]);
+	gctl_ro_param(req, "offset", sizeof(off_t), &offset);
+	gctl_ro_param(req, "rename", sizeof(int), &rename);
+	errstr = gctl_issue(req);
+	if (errstr != NULL)
+		warnx("attach failed: %s", errstr);
+	gctl_free(req);
+}
+
+void
 gvinum_create(int argc, char **argv)
 {
 	struct gctl_req *req;
@@ -332,6 +370,9 @@
 	    "        Check the parity blocks of a RAID-5 plex.\n"
 	    "create description-file\n"
 	    "        Create as per description-file or open editor.\n"
+	    "attach plex volume [rename]\n"
+	    "attach subdisk plex [offset] [rename]\n"
+	    "        Attach a plex to a volume, or a subdisk to a plex\n"
 	    "l | list [-r] [-v] [-V] [volume | plex | subdisk]\n"
 	    "        List information about specified objects.\n"
 	    "ld [-r] [-v] [-V] [volume]\n"
@@ -890,6 +931,8 @@
 		gvinum_create(argc, argv);
 	else if (!strcmp(argv[0], "exit") || !strcmp(argv[0], "quit"))
 		exit(0);
+	else if (!strcmp(argv[0], "attach"))
+		gvinum_attach(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#13 (text+ko) ====

@@ -51,6 +51,7 @@
 #endif
 
 int	gv_create(struct g_geom *, struct gctl_req *);
+void	gv_attach(struct gv_softc *, struct gctl_req *);
 
 static void
 gv_orphan(struct g_consumer *cp)
@@ -193,6 +194,64 @@
 	return (0);
 }
 
+/* Handle userland request of attaching object. */
+void
+gv_attach(struct gv_softc *sc, struct gctl_req *req)
+{
+	struct gv_volume *v;
+	struct gv_plex *p;
+	struct gv_sd *s;
+	off_t *offset;
+	int *rename, type_child, type_parent;
+	char *child, *parent;
+
+	child = gctl_get_param(req, "child", NULL);
+	if (child == NULL) {
+		gctl_error(req, "no child given");
+		return;
+	}
+	parent = gctl_get_param(req, "parent", NULL);
+	if (parent == NULL) {
+		gctl_error(req, "no parent given");
+		return;
+	}
+
+	offset = gctl_get_paraml(req, "offset", sizeof(*offset));
+	rename = gctl_get_paraml(req, "rename", sizeof(*rename));
+	type_child = gv_object_type(sc, child);
+	type_parent = gv_object_type(sc, parent);
+
+	switch (type_child) {
+	case GV_TYPE_PLEX:
+		if (type_parent != GV_TYPE_VOL) {
+			gctl_error(req, "no such volume to attach to");
+			return;
+		}
+		v = gv_find_vol(sc, parent);
+		p = gv_find_plex(sc, child);
+		/* XXX: Rename not supported yet. */
+		gv_post_event(sc, GV_EVENT_ATTACH_PLEX, p, v, NULL);
+		break;
+	case GV_TYPE_SD:
+		if (type_parent != GV_TYPE_PLEX) {
+			gctl_error(req, "no such plex to attach to");
+			return;
+		}
+		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;
+	default:
+		gctl_error(req, "invalid child type");
+		break;
+	}
+}
+
 /* Handle userland requests for creating new objects. */
 int
 gv_create(struct g_geom *gp, struct gctl_req *req)
@@ -310,7 +369,10 @@
 	gp = LIST_FIRST(&mp->geom);
 	sc = gp->softc;
 
-	if (!strcmp(verb, "list")) {
+	if (!strcmp(verb, "attach")) {
+		gv_attach(sc, req);
+
+	} else if (!strcmp(verb, "list")) {
 		gv_list(gp, req);
 
 	/* Save our configuration back to disk. */
@@ -610,6 +672,26 @@
 				/*gv_start_volume(v);*/
 				break;
 
+			case GV_EVENT_ATTACH_PLEX:
+				printf("VINUM: event 'attach'\n");
+				p = ev->arg1;
+				v = ev->arg2;
+				err = gv_attach_plex(p, v, 0);
+				if (err)
+					printf("VINUM: error attaching %s to "
+					    "%s\n", p->name, v->name);
+				break;
+
+			case GV_EVENT_ATTACH_SD:
+				printf("VINUM: event 'attach'\n");
+				s = ev->arg1;
+				p = ev->arg2;
+				err = gv_attach_sd(s, p, -1, 0);
+				if (err)
+					printf("VINUM: error attaching %s to "
+					    "%s\n", s->name, p->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#11 (text+ko) ====

@@ -90,6 +90,8 @@
 off_t	gv_vol_size(struct gv_volume *);
 off_t	gv_plex_size(struct gv_plex *);
 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);
 
 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_subr.c#6 (text+ko) ====

@@ -1043,3 +1043,87 @@
 	}
 	mtx_destroy(&sc->config_mtx);
 }
+
+/* General 'attach' routine. */
+int
+gv_attach_plex(struct gv_plex *p, struct gv_volume *v, int rename)
+{
+	struct gv_sd *s;
+
+	g_topology_assert();
+
+	if (p->vol_sc != NULL) {
+		printf("VINUM: plex %s already attached", p->name);
+		return (GV_ERR_ISATTACHED);
+	}
+
+	/* Stale all subdisks of this plex. */
+	LIST_FOREACH(s, &p->subdisks, in_plex) {
+		if (s->state != GV_SD_STALE)
+			gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE);
+	}
+	/* Attach to volume. Make sure volume is not up and running. */
+	if (gv_provider_is_open(v->provider)) {
+		printf("VINUM: volume %s is busy, cannot attach %s\n", v->name,
+		    p->name);
+		return (GV_ERR_ISOPEN);
+	}
+	p->vol_sc = v;
+	strlcpy(p->volume, v->name, GV_MAXVOLNAME);
+	v->plexcount++;
+	if (rename) {
+		/* XXX: Check if taken?. */
+		snprintf(p->name, GV_MAXPLEXNAME, "%s.p%d", v->name,
+		    v->plexcount - 1);
+		/* XXX: Rename subdisks? Original vinum does not. */
+/*		LIST_FOREACH(s, &p->subdisks, in_plex)
+			strlcpy(s->plex, newplexname, GV_MAXPLEXNAME);*/
+	}
+	LIST_INSERT_HEAD(&v->plexes, p, in_volume);
+
+	/* Get plex up again. */
+	gv_set_plex_state(p, GV_PLEX_UP, 0);
+	gv_save_config(p->vinumconf);
+	return (0);
+}
+
+int
+gv_attach_sd(struct gv_sd *s, struct gv_plex *p, off_t offset, int rename)
+{
+	struct gv_sd *s2;
+	int error;
+
+	g_topology_assert();
+
+	/* If subdisk is attached, don't do it. */
+	if (s->plex_sc != NULL) {
+		printf("VINUM: subdisk %s already attached", s->name);
+		return (GV_ERR_ISATTACHED);
+	}
+
+	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. */
+	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)))
+			return (GV_ERR_BADOFFSET);
+	}
+	/* Attach the subdisk to the plex at given offset. */
+	s->plex_offset = offset;
+	strlcpy(s->plex, p->name, GV_MAXPLEXNAME);
+
+	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);
+	}
+	gv_save_config(p->vinumconf);
+	/* We don't update the subdisk state since the user might have to
+	 * initiate a rebuild/sync first. */
+	return (0);
+}

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

@@ -130,6 +130,7 @@
 #define	GV_ERR_NOTFOUND		(-9)	/* Object not found. */
 #define	GV_ERR_NAMETAKEN	(-10)	/* Object name is taken. */
 #define	GV_ERR_NOSPACE		(-11)	/* No space left on drive/subdisk. */
+#define GV_ERR_BADOFFSET	(-12)	/* Invalid offset specified. */
 
 /*
  * hostname is 256 bytes long, but we don't need to shlep multiple copies in
@@ -194,6 +195,8 @@
 #define GV_EVENT_PARITY_CHECK		19
 #define GV_EVENT_START_PLEX		20
 #define GV_EVENT_START_VOLUME		21
+#define GV_EVENT_ATTACH_PLEX		22
+#define GV_EVENT_ATTACH_SD		23
 
 struct gv_event {
 	int	type;



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