Use a temporary geom when tasting vinumdrives and lock the 'real'

vinumdrive geom with an exclusive bit.  This should fix the problem
when underlying partitions overlap (i.e. the 'a' partition is at
the same offset as the 'c' partition).

Ideas borrowed from pjd@, quite a bit of testing by
Matthias Schuendehuette <msch@snafu.de>.
This commit is contained in:
Lukas Ertl 2004-07-24 22:26:40 +00:00
parent 62010d3541
commit c291a77678
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=132617
2 changed files with 33 additions and 5 deletions

View File

@ -540,6 +540,7 @@ static int
gv_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
{
struct g_geom *gp2;
struct g_consumer *cp;
struct gv_softc *sc;
struct gv_drive *d, *d2;
struct gv_plex *p, *p2;
@ -560,6 +561,9 @@ gv_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
*/
LIST_FOREACH(d, &sc->drives, drive) {
gp2 = d->geom;
cp = LIST_FIRST(&gp2->consumer);
if (cp != NULL)
g_access(cp, -1, -1, -1);
if (gv_is_open(gp2))
return (EBUSY);
}

View File

@ -181,12 +181,14 @@ gv_drive_access(struct g_provider *pp, int dr, int dw, int de)
}
}
#if 0
/* On first open, grab an extra "exclusive" bit */
if (cp->acr == 0 && cp->acw == 0 && cp->ace == 0)
de++;
/* ... and let go of it on last close */
if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1)
de--;
#endif
error = g_access(cp, dr, dw, de);
if (error) {
printf("FOOO: g_access failed: %d\n", error);
@ -294,6 +296,12 @@ gv_drive_orphan(struct g_consumer *cp)
g_wither_geom(gp, error);
}
static void
gv_drive_taste_orphan(struct g_consumer *cp)
{
KASSERT(1 == 0, ("gv_drive_taste_orphan called: %s", cp->geom->name));
}
static struct g_geom *
gv_drive_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
{
@ -323,11 +331,7 @@ gv_drive_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
sc = gp2->softc;
gp = g_new_geomf(mp, "%s.vinumdrive", pp->name);
gp->start = gv_drive_start;
gp->spoiled = gv_drive_orphan;
gp->orphan = gv_drive_orphan;
gp->access = gv_drive_access;
gp->start = gv_drive_start;
gp->orphan = gv_drive_taste_orphan;
cp = g_new_consumer(gp);
g_attach(cp, pp);
@ -357,6 +361,9 @@ gv_drive_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
*/
g_topology_lock();
g_access(cp, -1, 0, 0);
g_detach(cp);
g_wither_geom(gp, ENXIO);
gp = NULL;
d = gv_find_drive(sc, vhdr->label.name);
@ -387,6 +394,23 @@ gv_drive_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
LIST_INSERT_HEAD(&sc->drives, d, drive);
}
gp = g_new_geomf(mp, "%s.vinumdrive", pp->name);
gp->start = gv_drive_start;
gp->orphan = gv_drive_orphan;
gp->access = gv_drive_access;
gp->start = gv_drive_start;
cp = g_new_consumer(gp);
g_attach(cp, pp);
error = g_access(cp, 1, 1, 1);
if (error) {
g_free(vhdr);
g_detach(cp);
g_destroy_consumer(cp);
g_destroy_geom(gp);
return (NULL);
}
gp->softc = d;
d->geom = gp;
strncpy(d->device, pp->name, GV_MAXDRIVENAME);