summaryrefslogtreecommitdiffstats
path: root/sys/geom/vinum/geom_vinum_volume.c
diff options
context:
space:
mode:
authorle <le@FreeBSD.org>2004-08-26 21:04:41 +0000
committerle <le@FreeBSD.org>2004-08-26 21:04:41 +0000
commit0fd3e9eb56be2620350465b205f67aaee14318b1 (patch)
tree0bb8537c7ef17954c98a3256667255a422a7a49e /sys/geom/vinum/geom_vinum_volume.c
parent1871435a01ae850271367e795a906a7160fc8a92 (diff)
downloadFreeBSD-src-0fd3e9eb56be2620350465b205f67aaee14318b1.zip
FreeBSD-src-0fd3e9eb56be2620350465b205f67aaee14318b1.tar.gz
When attaching a consumer from a volume to a plex, check if the
volume already has a plex attached and adjust the access counts of the new consumer accordingly.
Diffstat (limited to 'sys/geom/vinum/geom_vinum_volume.c')
-rw-r--r--sys/geom/vinum/geom_vinum_volume.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/sys/geom/vinum/geom_vinum_volume.c b/sys/geom/vinum/geom_vinum_volume.c
index c6cc128..a2f262d 100644
--- a/sys/geom/vinum/geom_vinum_volume.c
+++ b/sys/geom/vinum/geom_vinum_volume.c
@@ -176,11 +176,11 @@ gv_volume_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
{
struct g_geom *gp;
struct g_provider *pp2;
- struct g_consumer *cp;
+ struct g_consumer *cp, *ocp;
struct gv_softc *sc;
struct gv_volume *v;
struct gv_plex *p;
- int first;
+ int error, first;
g_trace(G_T_TOPOLOGY, "gv_volume_taste(%s, %s)", mp->name, pp->name);
g_topology_assert();
@@ -214,8 +214,27 @@ gv_volume_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
} else
gp = v->geom;
+ /*
+ * Create a new consumer and attach it to the plex geom. Since this
+ * volume might already have a plex attached, we need to adjust the
+ * access counts of the new consumer.
+ */
+ ocp = LIST_FIRST(&gp->consumer);
cp = g_new_consumer(gp);
g_attach(cp, pp);
+ if ((ocp != NULL) && (ocp->acr > 0 || ocp->acw > 0 || ocp->ace > 0)) {
+ error = g_access(cp, ocp->acr, ocp->acw, ocp->ace);
+ if (error) {
+ printf("GEOM_VINUM: failed g_access %s -> %s; "
+ "errno %d\n", v->name, p->name, error);
+ g_detach(cp);
+ g_destroy_consumer(cp);
+ if (first)
+ g_destroy_geom(gp);
+ return (NULL);
+ }
+ }
+
p->consumer = cp;
if (p->vol_sc != v) {
OpenPOWER on IntegriCloud