From owner-p4-projects@FreeBSD.ORG Mon Jun 4 20:31:08 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 AFB9116A469; Mon, 4 Jun 2007 20:31:08 +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 3C79216A421 for ; Mon, 4 Jun 2007 20:31:08 +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 2AB4E13C45A for ; Mon, 4 Jun 2007 20:31:08 +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 l54KV8he067255 for ; Mon, 4 Jun 2007 20:31:08 GMT (envelope-from lulf@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l54KV71o067216 for perforce@freebsd.org; Mon, 4 Jun 2007 20:31:07 GMT (envelope-from lulf@FreeBSD.org) Date: Mon, 4 Jun 2007 20:31:07 GMT Message-Id: <200706042031.l54KV71o067216@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 120928 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: Mon, 04 Jun 2007 20:31:09 -0000 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 [rename] " + "[]\n" + "\tattach [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;