From 5b070780c00e9d2d81fcc39b3aef201725b8896b Mon Sep 17 00:00:00 2001 From: le Date: Thu, 12 Apr 2007 17:54:35 +0000 Subject: [PATCH] -) Correct sdcount for a plex when removing or adding subdisks. -) Set correct sizes for plexes and volumes a subdisk has been removed. Submitted by: Ulf Lilleengen --- sys/geom/vinum/geom_vinum.h | 2 + sys/geom/vinum/geom_vinum_rm.c | 21 ++++++++- sys/geom/vinum/geom_vinum_subr.c | 73 +++++++++++++++++++++++++++++++- 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/sys/geom/vinum/geom_vinum.h b/sys/geom/vinum/geom_vinum.h index 493c49342e54..a4c3f5d8cecd 100644 --- a/sys/geom/vinum/geom_vinum.h +++ b/sys/geom/vinum/geom_vinum.h @@ -91,5 +91,7 @@ int gv_sd_to_drive(struct gv_softc *, struct gv_drive *, struct gv_sd *, int gv_sd_to_plex(struct gv_plex *, struct gv_sd *, int); void gv_update_plex_config(struct gv_plex *); 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 *); #endif /* !_GEOM_VINUM_H_ */ diff --git a/sys/geom/vinum/geom_vinum_rm.c b/sys/geom/vinum/geom_vinum_rm.c index 9b1247de7043..a6bc71b18c54 100644 --- a/sys/geom/vinum/geom_vinum_rm.c +++ b/sys/geom/vinum/geom_vinum_rm.c @@ -216,6 +216,7 @@ static int gv_rm_plex(struct gv_softc *sc, struct gctl_req *req, struct gv_plex *p, int flags) { struct g_geom *gp; + struct gv_volume *v; struct gv_sd *s, *s2; int err; @@ -245,7 +246,6 @@ gv_rm_plex(struct gv_softc *sc, struct gctl_req *req, struct gv_plex *p, int fla /* Remove the subdisks our plex has. */ LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2) { - p->sdcount--; #if 0 LIST_REMOVE(s, in_plex); s->plex_sc = NULL; @@ -256,12 +256,15 @@ gv_rm_plex(struct gv_softc *sc, struct gctl_req *req, struct gv_plex *p, int fla return (err); } + v = p->vol_sc; /* Clean up and let our geom fade away. */ LIST_REMOVE(p, plex); if (p->vol_sc != NULL) { p->vol_sc->plexcount--; LIST_REMOVE(p, in_volume); p->vol_sc = NULL; + /* Correctly update the volume size. */ + gv_update_vol_size(v, gv_vol_size(v)); } gv_kill_plex_thread(p); @@ -280,14 +283,28 @@ int gv_rm_sd(struct gv_softc *sc, struct gctl_req *req, struct gv_sd *s, int flags) { struct g_provider *pp; + struct gv_plex *p; + struct gv_volume *v; KASSERT(s != NULL, ("gv_rm_sd: NULL s")); pp = s->provider; + p = s->plex_sc; + v = NULL; /* Clean up. */ - if (s->plex_sc) + if (p != NULL) { LIST_REMOVE(s, in_plex); + + p->sdcount--; + /* Update the plexsize. */ + p->size = gv_plex_size(p); + v = p->vol_sc; + if (v != NULL) { + /* Update the size of our plex' volume. */ + gv_update_vol_size(v, gv_vol_size(v)); + } + } if (s->drive_sc) LIST_REMOVE(s, from_drive); LIST_REMOVE(s, sd); diff --git a/sys/geom/vinum/geom_vinum_subr.c b/sys/geom/vinum/geom_vinum_subr.c index 323bb7c8dc1b..1bd339cff3ea 100644 --- a/sys/geom/vinum/geom_vinum_subr.c +++ b/sys/geom/vinum/geom_vinum_subr.c @@ -54,6 +54,8 @@ __FBSDID("$FreeBSD$"); #include #include +static off_t gv_plex_smallest_sd(struct gv_plex *, off_t); + /* Find the VINUM class and it's associated geom. */ struct g_geom * find_vinum_geom(void) @@ -235,6 +237,20 @@ gv_format_config(struct gv_softc *sc, struct sbuf *sb, int ondisk, char *prefix) return; } +static off_t +gv_plex_smallest_sd(struct gv_plex *p, off_t smallest) +{ + struct gv_sd *s; + + KASSERT(p != NULL, ("gv_plex_smallest_sd: NULL p")); + + LIST_FOREACH(s, &p->subdisks, in_plex) { + if (s->size < smallest) + smallest = s->size; + } + return (smallest); +} + int gv_sd_to_plex(struct gv_plex *p, struct gv_sd *s, int check) { @@ -280,7 +296,7 @@ gv_sd_to_plex(struct gv_plex *p, struct gv_sd *s, int check) break; case GV_PLEX_RAID5: - p->size = (p->sdcount - 1) * s->size; + p->size = (p->sdcount - 1) * gv_plex_smallest_sd(p, s->size); break; default: @@ -329,6 +345,60 @@ gv_update_vol_size(struct gv_volume *v, off_t size) v->size = size; } +/* Calculates the plex size. */ +off_t +gv_plex_size(struct gv_plex *p) +{ + struct gv_sd *s; + off_t size; + + KASSERT(p != NULL, ("gv_plex_size: NULL p")); + + if (p->sdcount == 0) + return (0); + + /* Adjust the size of our plex. */ + size = 0; + switch (p->org) { + case GV_PLEX_CONCAT: + LIST_FOREACH(s, &p->subdisks, in_plex) + size += s->size; + break; + case GV_PLEX_STRIPED: + s = LIST_FIRST(&p->subdisks); + size = p->sdcount * s->size; + break; + case GV_PLEX_RAID5: + s = LIST_FIRST(&p->subdisks); + size = (p->sdcount - 1) * s->size; + break; + } + + return (size); +} + +/* Returns the size of a volume. */ +off_t +gv_vol_size(struct gv_volume *v) +{ + struct gv_plex *p; + off_t minplexsize; + + KASSERT(v != NULL, ("gv_vol_size: NULL v")); + + p = LIST_FIRST(&v->plexes); + if (p == NULL) + return (0); + + minplexsize = p->size; + LIST_FOREACH(p, &v->plexes, plex) { + if (p->size < minplexsize) { + minplexsize = p->size; + } + } + return (minplexsize); +} + void gv_update_plex_config(struct gv_plex *p) { @@ -676,6 +746,7 @@ gv_free_sd(struct gv_sd *s) } d->avail += s->size; + d->sdcount--; } void