summaryrefslogtreecommitdiffstats
path: root/sys/cddl
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2010-02-04 21:11:44 +0000
committerpjd <pjd@FreeBSD.org>2010-02-04 21:11:44 +0000
commitf55d6a38614b7438085dec27356c054cd790a021 (patch)
tree026d1f3d22ec8e126f14d094ea25f4d12896c964 /sys/cddl
parent78aa3f59ba3251a4cf2932410926cbeb7ede7284 (diff)
downloadFreeBSD-src-f55d6a38614b7438085dec27356c054cd790a021.zip
FreeBSD-src-f55d6a38614b7438085dec27356c054cd790a021.tar.gz
Open provider for writting when we find the right one. Opening too much
providers for writing provokes huge traffic related to taste events send by GEOM on close. This can lead to various problems with opening GEOM providers that are created on top of other GEOM providers. Reorted by: Kurt Touet <ktouet@gmail.com>, mr Tested by: mr, Baginski Darren <kickbsd@ya.ru> MFC after: 2 weeks
Diffstat (limited to 'sys/cddl')
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
index 4c41f90..d5c57e7 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
@@ -102,7 +102,7 @@ vdev_geom_orphan(struct g_consumer *cp)
}
static struct g_consumer *
-vdev_geom_attach(struct g_provider *pp, int write)
+vdev_geom_attach(struct g_provider *pp)
{
struct g_geom *gp;
struct g_consumer *cp;
@@ -126,7 +126,7 @@ vdev_geom_attach(struct g_provider *pp, int write)
g_wither_geom(gp, ENXIO);
return (NULL);
}
- if (g_access(cp, 1, write, 1) != 0) {
+ if (g_access(cp, 1, 0, 1) != 0) {
g_wither_geom(gp, ENXIO);
return (NULL);
}
@@ -145,14 +145,14 @@ vdev_geom_attach(struct g_provider *pp, int write)
g_destroy_consumer(cp);
return (NULL);
}
- if (g_access(cp, 1, write, 1) != 0) {
+ if (g_access(cp, 1, 0, 1) != 0) {
g_detach(cp);
g_destroy_consumer(cp);
return (NULL);
}
ZFS_LOG(1, "Created consumer for %s.", pp->name);
} else {
- if (g_access(cp, 1, cp->acw > 0 ? 0 : write, 1) != 0)
+ if (g_access(cp, 1, 0, 1) != 0)
return (NULL);
ZFS_LOG(1, "Used existing consumer for %s.", pp->name);
}
@@ -342,7 +342,6 @@ vdev_geom_read_guid(struct g_consumer *cp)
struct vdev_geom_find {
uint64_t guid;
- int write;
struct g_consumer *cp;
};
@@ -394,10 +393,10 @@ vdev_geom_attach_by_guid_event(void *arg, int flags __unused)
g_detach(zcp);
if (guid != ap->guid)
continue;
- ap->cp = vdev_geom_attach(pp, ap->write);
+ ap->cp = vdev_geom_attach(pp);
if (ap->cp == NULL) {
- printf("ZFS WARNING: Cannot open %s "
- "for writting.\n", pp->name);
+ printf("ZFS WARNING: Unable to attach to %s.",
+ pp->name);
continue;
}
goto end;
@@ -411,14 +410,13 @@ end:
}
static struct g_consumer *
-vdev_geom_attach_by_guid(uint64_t guid, int write)
+vdev_geom_attach_by_guid(uint64_t guid)
{
struct vdev_geom_find *ap;
struct g_consumer *cp;
ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
ap->guid = guid;
- ap->write = write;
g_waitfor_event(vdev_geom_attach_by_guid_event, ap, M_WAITOK, NULL);
cp = ap->cp;
kmem_free(ap, sizeof(*ap));
@@ -433,7 +431,7 @@ vdev_geom_open_by_guid(vdev_t *vd)
size_t len;
ZFS_LOG(1, "Searching by guid [%ju].", (uintmax_t)vd->vdev_guid);
- cp = vdev_geom_attach_by_guid(vd->vdev_guid, !!(spa_mode & FWRITE));
+ cp = vdev_geom_attach_by_guid(vd->vdev_guid);
if (cp != NULL) {
len = strlen(cp->provider->name) + strlen("/dev/") + 1;
buf = kmem_alloc(len, KM_SLEEP);
@@ -464,7 +462,7 @@ vdev_geom_open_by_path(vdev_t *vd, int check_guid)
pp = g_provider_by_name(vd->vdev_path + sizeof("/dev/") - 1);
if (pp != NULL) {
ZFS_LOG(1, "Found provider by name %s.", vd->vdev_path);
- cp = vdev_geom_attach(pp, !!(spa_mode & FWRITE));
+ cp = vdev_geom_attach(pp);
if (cp != NULL && check_guid) {
g_topology_unlock();
guid = vdev_geom_read_guid(cp);
@@ -492,7 +490,7 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
vdev_geom_ctx_t *ctx;
struct g_provider *pp;
struct g_consumer *cp;
- int owned;
+ int error, owned;
/*
* We must have a pathname, and it must be absolute.
@@ -506,6 +504,7 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
if ((owned = mtx_owned(&Giant)))
mtx_unlock(&Giant);
+ error = 0;
cp = vdev_geom_open_by_path(vd, 1);
if (cp == NULL) {
/*
@@ -519,13 +518,24 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
cp = vdev_geom_open_by_path(vd, 0);
if (cp == NULL) {
ZFS_LOG(1, "Provider %s not found.", vd->vdev_path);
- vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
- if (owned)
- mtx_lock(&Giant);
- return (EACCES);
+ error = ENOENT;
+ } else if (cp->acw == 0 && (spa_mode & FWRITE) != 0) {
+ g_topology_lock();
+ error = g_access(cp, 0, 1, 0);
+ if (error != 0) {
+ printf("ZFS WARNING: Unable to open %s for writing (error=%d).",
+ vd->vdev_path, error);
+ vdev_geom_detach(cp, 0);
+ cp = NULL;
+ }
+ g_topology_unlock();
}
if (owned)
mtx_lock(&Giant);
+ if (cp == NULL) {
+ vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
+ return (error);
+ }
cp->private = vd;
OpenPOWER on IntegriCloud