PERFORCE change 121535 for review
Ulf Lilleengen
lulf at FreeBSD.org
Tue Jun 12 20:57:21 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=121535
Change 121535 by lulf at 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;
More information about the p4-projects
mailing list