From owner-p4-projects@FreeBSD.ORG Tue Jun 12 20:57:21 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 5169816A468; Tue, 12 Jun 2007 20:57:21 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id EE6F816A46C for ; Tue, 12 Jun 2007 20:57:20 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id D350B13C483 for ; Tue, 12 Jun 2007 20:57:20 +0000 (UTC) (envelope-from lulf@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.8/8.13.8) with ESMTP id l5CKvKcX084020 for ; Tue, 12 Jun 2007 20:57:20 GMT (envelope-from lulf@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l5CKvKlc084001 for perforce@freebsd.org; Tue, 12 Jun 2007 20:57:20 GMT (envelope-from lulf@FreeBSD.org) Date: Tue, 12 Jun 2007 20:57:20 GMT Message-Id: <200706122057.l5CKvKlc084001@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to lulf@FreeBSD.org using -f From: Ulf Lilleengen To: Perforce Change Reviews Cc: Subject: PERFORCE change 121535 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Jun 2007 20:57:21 -0000 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] | "); + 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;