diff options
author | le <le@FreeBSD.org> | 2004-07-24 22:26:40 +0000 |
---|---|---|
committer | le <le@FreeBSD.org> | 2004-07-24 22:26:40 +0000 |
commit | 9795b96112070c79a1bd42f4f7a64debfb11889d (patch) | |
tree | e868592d11ae6a43efce2556fc076c05f469bb41 /sys/geom/vinum/geom_vinum_drive.c | |
parent | 4eaecd41f31309b86bf7e73c017f01bd2f1f14b4 (diff) | |
download | FreeBSD-src-9795b96112070c79a1bd42f4f7a64debfb11889d.zip FreeBSD-src-9795b96112070c79a1bd42f4f7a64debfb11889d.tar.gz |
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>.
Diffstat (limited to 'sys/geom/vinum/geom_vinum_drive.c')
-rw-r--r-- | sys/geom/vinum/geom_vinum_drive.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/sys/geom/vinum/geom_vinum_drive.c b/sys/geom/vinum/geom_vinum_drive.c index 7a83c77..86eec15 100644 --- a/sys/geom/vinum/geom_vinum_drive.c +++ b/sys/geom/vinum/geom_vinum_drive.c @@ -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); |