Date: Sat, 5 May 2007 00:11:00 GMT From: Ulf Lilleengen <lulf@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 119260 for review Message-ID: <200705050011.l450B0Ev029681@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=119260 Change 119260 by lulf@lulf_carrot on 2007/05/05 00:10:12 - Add gv_set_plex_state to make it possible to set plex state. - Add gv_plexdown to count number of plexes down in a volume. - Hook this up in the event system. Affected files ... .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.c#6 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.h#5 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_state.c#7 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_subr.c#3 edit .. //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_var.h#4 edit Differences ... ==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum.c#6 (text+ko) ==== @@ -547,6 +547,19 @@ g_free(ev->arg3); break; + case GV_EVENT_SET_PLEX_STATE: + printf("VINUM: event 'setstate plex'\n"); + p = ev->arg1; + newstate = *(int *)ev->arg2; + flags = *(int *)ev->arg3; + err = gv_set_plex_state(p, newstate, flags); + if (err) + printf("VINUM: error setting plex " + "state\n"); + g_free(ev->arg2); + g_free(ev->arg3); + 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#5 (text+ko) ==== @@ -64,6 +64,7 @@ int gv_set_drive_state(struct gv_drive *, int, int); int gv_set_sd_state(struct gv_sd *, int, int); int gv_set_vol_state(struct gv_volume *, int, int); +int gv_set_plex_state(struct gv_plex *, int, int); void gv_update_sd_state(struct gv_sd *); void gv_update_plex_state(struct gv_plex *); void gv_update_vol_state(struct gv_volume *); @@ -87,6 +88,7 @@ void gv_update_vol_size(struct gv_volume *, off_t); off_t gv_vol_size(struct gv_volume *); off_t gv_plex_size(struct gv_plex *); +int gv_plexdown(struct gv_volume *); 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_state.c#7 (text+ko) ==== @@ -44,6 +44,7 @@ struct gv_sd *s; struct gv_drive *d; struct gv_volume *v; + struct gv_plex *p; char *obj, *state; int f, *flags, *newstatep, *flagp, type; @@ -79,6 +80,7 @@ } v = gv_find_vol(sc, obj); + /* XXX: Should try to avoid malloc. */ newstatep = g_malloc(sizeof(int), M_WAITOK | M_ZERO); *newstatep = gv_volstatei(state); flagp = g_malloc(sizeof(int), M_WAITOK | M_ZERO); @@ -87,7 +89,18 @@ break; case GV_TYPE_PLEX: - gctl_error(req, "plex state cannot be set currently"); + if (gv_plexstatei(state) < 0) { + gctl_error(req, "invalid plex state '%s'", state); + break; + } + p = gv_find_plex(sc, obj); + + /* XXX: Should try to avoid malloc. */ + newstatep = g_malloc(sizeof(int), M_WAITOK | M_ZERO); + *newstatep = gv_sdstatei(state); + flagp = g_malloc(sizeof(int), M_WAITOK | M_ZERO); + *flagp = f; + gv_post_event(sc, GV_EVENT_SET_PLEX_STATE, p, newstatep, flagp); break; case GV_TYPE_SD: @@ -277,6 +290,56 @@ } int +gv_set_plex_state(struct gv_plex *p, int newstate, int flags) +{ + struct gv_volume *v; + int oldstate, plexdown; + + KASSERT(p != NULL, ("gv_set_plex_state: NULL p")); + + oldstate = p->state; + v = p->vol_sc; + plexdown = 0; + + if (newstate == oldstate) + return (0); + + switch (newstate) { + case GV_PLEX_UP: + /* Let update_plex handle if the plex can come up */ + gv_update_plex_state(p); + if (p->state != GV_PLEX_UP && !(flags & GV_SETSTATE_FORCE)) + return (-1); /* XXX: ERROR CODES. */ + p->state = newstate; + break; + case GV_PLEX_DOWN: + /* + * Set state to GV_PLEX_DOWN only if no-one is using the plex, + * or if the state is forced. + */ + if (v != NULL) { + /* If the only one up, force is needed. */ + plexdown = gv_plexdown(v); + if ((v->plexcount == 1 || + (v->plexcount - plexdown == 1)) && + ((flags & GV_SETSTATE_FORCE) == 0)) + return (-1); /* XXX: ERROR CODES. */ + } + p->state = newstate; + break; + } + + /* Update our volume if we have one. */ + if (v != NULL) + gv_update_vol_state(v); + + /* Save config. */ + if (flags & GV_SETSTATE_CONFIG) + gv_save_config(p->vinumconf); + return (0); +} + +int gv_set_vol_state(struct gv_volume *v, int newstate, int flags) { int oldstate; @@ -298,7 +361,7 @@ break; case GV_VOL_DOWN: /* - * Set state to GV_VOL_DOWN only if noone is using the volume, + * Set state to GV_VOL_DOWN only if no-one is using the volume, * or if the state should be forced. */ if (!gv_provider_is_open(v->provider) && ==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_subr.c#3 (text+ko) ==== @@ -245,6 +245,24 @@ return (smallest); } +/* Walk over plexes in a volume and count how many are down. */ +int +gv_plexdown(struct gv_volume *v) +{ + int plexdown; + struct gv_plex *p; + + KASSERT(v != NULL, ("gv_plexdown: NULL v")); + + plexdown = 0; + + LIST_FOREACH(p, &v->plexes, plex) { + if (p->state == GV_PLEX_DOWN) + plexdown++; + } + return (plexdown); +} + int gv_sd_to_plex(struct gv_sd *s, struct gv_plex *p) { ==== //depot/projects/soc2007/lulf/gvinum_fixup/sys/geom/vinum/geom_vinum_var.h#4 (text+ko) ==== @@ -175,6 +175,7 @@ #define GV_EVENT_SET_SD_STATE 13 #define GV_EVENT_SET_DRIVE_STATE 14 #define GV_EVENT_SET_VOL_STATE 15 +#define GV_EVENT_SET_PLEX_STATE 16 struct gv_event { int type;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200705050011.l450B0Ev029681>