p4-projects@freebsd.org
[Top] [All Lists]

PERFORCE change 121535 for review

Subject: PERFORCE change 121535 for review
From: Ulf Lilleengen
Date: Tue, 12 Jun 2007 20:57:20 GMT
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;
_______________________________________________
p4-projects@xxxxxxxxxxx mailing list
http://lists.freebsd.org/mailman/listinfo/p4-projects
To unsubscribe, send any mail to "p4-projects-unsubscribe@xxxxxxxxxxx"

<Prev in Thread] Current Thread [Next in Thread>