-) 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:
parent
1652a41e4b
commit
5b070780c0
@ -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_ */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user