mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-19 15:33:56 +00:00
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:
parent
62010d3541
commit
c291a77678
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=132617
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user