summaryrefslogtreecommitdiffstats
path: root/sys/geom/vinum/geom_vinum_drive.c
diff options
context:
space:
mode:
authorle <le@FreeBSD.org>2004-07-24 22:26:40 +0000
committerle <le@FreeBSD.org>2004-07-24 22:26:40 +0000
commit9795b96112070c79a1bd42f4f7a64debfb11889d (patch)
treee868592d11ae6a43efce2556fc076c05f469bb41 /sys/geom/vinum/geom_vinum_drive.c
parent4eaecd41f31309b86bf7e73c017f01bd2f1f14b4 (diff)
downloadFreeBSD-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.c34
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);
OpenPOWER on IntegriCloud