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