-) 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>
This commit is contained in:
le 2007-04-12 17:54:35 +00:00
parent 1652a41e4b
commit 5b070780c0
3 changed files with 93 additions and 3 deletions

View File

@ -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_ */

View File

@ -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);

View File

@ -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