summaryrefslogtreecommitdiffstats
path: root/sys/geom
diff options
context:
space:
mode:
authorle <le@FreeBSD.org>2007-04-12 17:54:35 +0000
committerle <le@FreeBSD.org>2007-04-12 17:54:35 +0000
commit5b070780c00e9d2d81fcc39b3aef201725b8896b (patch)
tree758aa0a36272b2ad64f55e8a32257ca1d9e6203a /sys/geom
parent1652a41e4b9ce48931196652c9c82b2982168c05 (diff)
downloadFreeBSD-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>
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/vinum/geom_vinum.h2
-rw-r--r--sys/geom/vinum/geom_vinum_rm.c21
-rw-r--r--sys/geom/vinum/geom_vinum_subr.c73
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
OpenPOWER on IntegriCloud