diff options
author | le <le@FreeBSD.org> | 2007-04-12 17:54:35 +0000 |
---|---|---|
committer | le <le@FreeBSD.org> | 2007-04-12 17:54:35 +0000 |
commit | 5b070780c00e9d2d81fcc39b3aef201725b8896b (patch) | |
tree | 758aa0a36272b2ad64f55e8a32257ca1d9e6203a | |
parent | 1652a41e4b9ce48931196652c9c82b2982168c05 (diff) | |
download | FreeBSD-src-5b070780c00e9d2d81fcc39b3aef201725b8896b.zip FreeBSD-src-5b070780c00e9d2d81fcc39b3aef201725b8896b.tar.gz |
-) 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 <lulf_AT_freebsd.org>
-rw-r--r-- | sys/geom/vinum/geom_vinum.h | 2 | ||||
-rw-r--r-- | sys/geom/vinum/geom_vinum_rm.c | 21 | ||||
-rw-r--r-- | 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 493c493..a4c3f5d 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 9b1247d..a6bc71b 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 323bb7c..1bd339c 100644 --- a/sys/geom/vinum/geom_vinum_subr.c +++ b/sys/geom/vinum/geom_vinum_subr.c @@ -54,6 +54,8 @@ __FBSDID("$FreeBSD$"); #include <geom/vinum/geom_vinum.h> #include <geom/vinum/geom_vinum_share.h> +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 |