svn commit: r298786 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Alan Somers
asomers at FreeBSD.org
Fri Apr 29 15:23:52 UTC 2016
Author: asomers
Date: Fri Apr 29 15:23:51 2016
New Revision: 298786
URL: https://svnweb.freebsd.org/changeset/base/298786
Log:
Refactor vdev_geom_attach and friends to reduce code duplication
sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
Move checks for provider's sectorsize and mediasize into a single
location in vdev_geom_attach. Remove the zfs::vdev::taste class;
it's ok to use the regular vdev class for tasting. Consolidate guid
checks into a single location in vdev_attach_ok. Consolidate some
error handling code from vdev_geom_attach into vdev_geom_detach,
closing a resource leak of geom consumers in the process.
Reviewed by: avg
MFC after: 4 weeks
Sponsored by: Spectra Logic Corp
Differential Revision: https://reviews.freebsd.org/D5974
Modified:
head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c Fri Apr 29 13:58:01 2016 (r298785)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c Fri Apr 29 15:23:51 2016 (r298786)
@@ -61,6 +61,9 @@ static int vdev_geom_bio_delete_disable;
SYSCTL_INT(_vfs_zfs_vdev, OID_AUTO, bio_delete_disable, CTLFLAG_RWTUN,
&vdev_geom_bio_delete_disable, 0, "Disable BIO_DELETE");
+/* Declare local functions */
+static void vdev_geom_detach(struct g_consumer *cp, boolean_t open_for_read);
+
/*
* Thread local storage used to indicate when a thread is probing geoms
* for their guids. If NULL, this thread is not tasting geoms. If non NULL,
@@ -168,6 +171,17 @@ vdev_geom_attach(struct g_provider *pp,
g_topology_assert();
ZFS_LOG(1, "Attaching to %s.", pp->name);
+
+ if (pp->sectorsize > VDEV_PAD_SIZE || !ISP2(pp->sectorsize)) {
+ ZFS_LOG(1, "Failing attach of %s. Incompatible sectorsize %d\n",
+ pp->name, pp->sectorsize);
+ return (NULL);
+ } else if (pp->mediasize < SPA_MINDEVSIZE) {
+ ZFS_LOG(1, "Failing attach of %s. Incompatible mediasize %ju\n",
+ pp->name, pp->mediasize);
+ return (NULL);
+ }
+
/* Do we have geom already? No? Create one. */
LIST_FOREACH(gp, &zfs_vdev_class.geom, geom) {
if (gp->flags & G_GEOM_WITHER)
@@ -185,14 +199,14 @@ vdev_geom_attach(struct g_provider *pp,
if (error != 0) {
ZFS_LOG(1, "%s(%d): g_attach failed: %d\n", __func__,
__LINE__, error);
- g_wither_geom(gp, ENXIO);
+ vdev_geom_detach(cp, B_FALSE);
return (NULL);
}
error = g_access(cp, 1, 0, 1);
if (error != 0) {
ZFS_LOG(1, "%s(%d): g_access failed: %d\n", __func__,
__LINE__, error);
- g_wither_geom(gp, ENXIO);
+ vdev_geom_detach(cp, B_FALSE);
return (NULL);
}
ZFS_LOG(1, "Created geom and consumer for %s.", pp->name);
@@ -210,15 +224,14 @@ vdev_geom_attach(struct g_provider *pp,
if (error != 0) {
ZFS_LOG(1, "%s(%d): g_attach failed: %d\n",
__func__, __LINE__, error);
- g_destroy_consumer(cp);
+ vdev_geom_detach(cp, B_FALSE);
return (NULL);
}
error = g_access(cp, 1, 0, 1);
if (error != 0) {
ZFS_LOG(1, "%s(%d): g_access failed: %d\n",
__func__, __LINE__, error);
- g_detach(cp);
- g_destroy_consumer(cp);
+ vdev_geom_detach(cp, B_FALSE);
return (NULL);
}
ZFS_LOG(1, "Created consumer for %s.", pp->name);
@@ -244,39 +257,41 @@ vdev_geom_attach(struct g_provider *pp,
* 2) Set it to a linked list of vdevs, not just a single vdev
*/
cp->private = vd;
- vd->vdev_tsd = cp;
+ if (vd != NULL)
+ vd->vdev_tsd = cp;
cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
return (cp);
}
static void
-vdev_geom_close_locked(vdev_t *vd)
+vdev_geom_detach(struct g_consumer *cp, boolean_t open_for_read)
{
struct g_geom *gp;
- struct g_consumer *cp;
+ vdev_t *vd;
g_topology_assert();
- cp = vd->vdev_tsd;
- if (cp == NULL)
- return;
+ ZFS_LOG(1, "Detaching consumer. Provider %s.",
+ cp->provider && cp->provider->name ? cp->provider->name : "NULL");
- ZFS_LOG(1, "Closing access to %s.", cp->provider->name);
- KASSERT(vd->vdev_tsd == cp, ("%s: vdev_tsd is not cp", __func__));
- vd->vdev_tsd = NULL;
- vd->vdev_delayed_close = B_FALSE;
+ vd = cp->private;
+ if (vd != NULL) {
+ vd->vdev_tsd = NULL;
+ vd->vdev_delayed_close = B_FALSE;
+ }
cp->private = NULL;
gp = cp->geom;
- g_access(cp, -1, 0, -1);
+ if (open_for_read)
+ g_access(cp, -1, 0, -1);
/* Destroy consumer on last close. */
if (cp->acr == 0 && cp->ace == 0) {
if (cp->acw > 0)
g_access(cp, 0, -cp->acw, 0);
if (cp->provider != NULL) {
- ZFS_LOG(1, "Destroyed consumer to %s.",
- cp->provider->name);
+ ZFS_LOG(1, "Destroying consumer to %s.",
+ cp->provider->name ? cp->provider->name : "NULL");
g_detach(cp);
}
g_destroy_consumer(cp);
@@ -289,6 +304,22 @@ vdev_geom_close_locked(vdev_t *vd)
}
static void
+vdev_geom_close_locked(vdev_t *vd)
+{
+ struct g_consumer *cp;
+
+ g_topology_assert();
+
+ cp = vd->vdev_tsd;
+ if (cp == NULL)
+ return;
+
+ ZFS_LOG(1, "Closing access to %s.", cp->provider->name);
+
+ vdev_geom_detach(cp, B_TRUE);
+}
+
+static void
nvlist_get_guids(nvlist_t *list, uint64_t *pguid, uint64_t *vguid)
{
@@ -331,13 +362,6 @@ vdev_geom_io(struct g_consumer *cp, int
return (error);
}
-static void
-vdev_geom_taste_orphan(struct g_consumer *cp)
-{
- ZFS_LOG(0, "WARNING: Orphan %s while tasting its VDev GUID.",
- cp->provider->name);
-}
-
static int
vdev_geom_read_config(struct g_consumer *cp, nvlist_t **config)
{
@@ -470,41 +494,12 @@ ignore:
nvlist_free(cfg);
}
-static int
-vdev_geom_attach_taster(struct g_consumer *cp, struct g_provider *pp)
-{
- int error;
-
- if (pp->flags & G_PF_WITHER)
- return (EINVAL);
- g_attach(cp, pp);
- error = g_access(cp, 1, 0, 0);
- if (error == 0) {
- if (pp->sectorsize > VDEV_PAD_SIZE || !ISP2(pp->sectorsize))
- error = EINVAL;
- else if (pp->mediasize < SPA_MINDEVSIZE)
- error = EINVAL;
- if (error != 0)
- g_access(cp, -1, 0, 0);
- }
- if (error != 0)
- g_detach(cp);
- return (error);
-}
-
-static void
-vdev_geom_detach_taster(struct g_consumer *cp)
-{
- g_access(cp, -1, 0, 0);
- g_detach(cp);
-}
-
int
vdev_geom_read_pool_label(const char *name,
nvlist_t ***configs, uint64_t *count)
{
struct g_class *mp;
- struct g_geom *gp, *zgp;
+ struct g_geom *gp;
struct g_provider *pp;
struct g_consumer *zcp;
nvlist_t *vdev_cfg;
@@ -514,11 +509,6 @@ vdev_geom_read_pool_label(const char *na
DROP_GIANT();
g_topology_lock();
- zgp = g_new_geomf(&zfs_vdev_class, "zfs::vdev::taste");
- /* This orphan function should be never called. */
- zgp->orphan = vdev_geom_taste_orphan;
- zcp = g_new_consumer(zgp);
-
*configs = NULL;
*count = 0;
pool_guid = 0;
@@ -531,12 +521,13 @@ vdev_geom_read_pool_label(const char *na
LIST_FOREACH(pp, &gp->provider, provider) {
if (pp->flags & G_PF_WITHER)
continue;
- if (vdev_geom_attach_taster(zcp, pp) != 0)
+ zcp = vdev_geom_attach(pp, NULL);
+ if (zcp == NULL)
continue;
g_topology_unlock();
error = vdev_geom_read_config(zcp, &vdev_cfg);
g_topology_lock();
- vdev_geom_detach_taster(zcp);
+ vdev_geom_detach(zcp, B_TRUE);
if (error)
continue;
ZFS_LOG(1, "successfully read vdev config");
@@ -546,9 +537,6 @@ vdev_geom_read_pool_label(const char *na
}
}
}
-
- g_destroy_consumer(zcp);
- g_destroy_geom(zgp);
g_topology_unlock();
PICKUP_GIANT();
@@ -570,21 +558,55 @@ vdev_geom_read_guids(struct g_consumer *
}
}
+static boolean_t
+vdev_attach_ok(vdev_t *vd, struct g_provider *pp)
+{
+ uint64_t pool_guid;
+ uint64_t vdev_guid;
+ struct g_consumer *zcp;
+ boolean_t pool_ok;
+ boolean_t vdev_ok;
+
+ zcp = vdev_geom_attach(pp, NULL);
+ if (zcp == NULL) {
+ ZFS_LOG(1, "Unable to attach tasting instance to %s.",
+ pp->name);
+ return (B_FALSE);
+ }
+ g_topology_unlock();
+ vdev_geom_read_guids(zcp, &pool_guid, &vdev_guid);
+ g_topology_lock();
+ vdev_geom_detach(zcp, B_TRUE);
+
+ /*
+ * Check that the label's vdev guid matches the desired guid. If the
+ * label has a pool guid, check that it matches too. (Inactive spares
+ * and L2ARCs do not have any pool guid in the label.)
+ */
+ if ((pool_guid == 0 || pool_guid == spa_guid(vd->vdev_spa)) &&
+ vdev_guid == vd->vdev_guid) {
+ ZFS_LOG(1, "guids match for provider %s.", vd->vdev_path);
+ return (B_TRUE);
+ } else {
+ ZFS_LOG(1, "guid mismatch for provider %s: "
+ "%ju:%ju != %ju:%ju.", vd->vdev_path,
+ (uintmax_t)spa_guid(vd->vdev_spa),
+ (uintmax_t)vd->vdev_guid,
+ (uintmax_t)pool_guid, (uintmax_t)vdev_guid);
+ return (B_FALSE);
+ }
+}
+
static struct g_consumer *
vdev_geom_attach_by_guids(vdev_t *vd)
{
struct g_class *mp;
- struct g_geom *gp, *zgp;
+ struct g_geom *gp;
struct g_provider *pp;
- struct g_consumer *cp, *zcp;
- uint64_t pguid, vguid;
+ struct g_consumer *cp;
g_topology_assert();
- zgp = g_new_geomf(&zfs_vdev_class, "zfs::vdev::taste");
- zgp->orphan = vdev_geom_taste_orphan;
- zcp = g_new_consumer(zgp);
-
cp = NULL;
LIST_FOREACH(mp, &g_classes, class) {
if (mp == &zfs_vdev_class)
@@ -593,22 +615,7 @@ vdev_geom_attach_by_guids(vdev_t *vd)
if (gp->flags & G_GEOM_WITHER)
continue;
LIST_FOREACH(pp, &gp->provider, provider) {
- if (vdev_geom_attach_taster(zcp, pp) != 0)
- continue;
- g_topology_unlock();
- vdev_geom_read_guids(zcp, &pguid, &vguid);
- g_topology_lock();
- vdev_geom_detach_taster(zcp);
- /*
- * Check that the label's vdev guid matches the
- * desired guid. If the label has a pool guid,
- * check that it matches too. (Inactive spares
- * and L2ARCs do not have any pool guid in the
- * label.)
- */
- if ((pguid != 0 &&
- pguid != spa_guid(vd->vdev_spa)) ||
- vguid != vd->vdev_guid)
+ if (!vdev_attach_ok(vd, pp))
continue;
cp = vdev_geom_attach(pp, vd);
if (cp == NULL) {
@@ -625,8 +632,6 @@ vdev_geom_attach_by_guids(vdev_t *vd)
break;
}
end:
- g_destroy_consumer(zcp);
- g_destroy_geom(zgp);
return (cp);
}
@@ -667,7 +672,6 @@ vdev_geom_open_by_path(vdev_t *vd, int c
{
struct g_provider *pp;
struct g_consumer *cp;
- uint64_t pguid, vguid;
g_topology_assert();
@@ -675,34 +679,8 @@ vdev_geom_open_by_path(vdev_t *vd, int c
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, vd);
- if (cp != NULL && check_guid && ISP2(pp->sectorsize) &&
- pp->sectorsize <= VDEV_PAD_SIZE) {
- g_topology_unlock();
- vdev_geom_read_guids(cp, &pguid, &vguid);
- g_topology_lock();
- /*
- * Check that the label's vdev guid matches the
- * desired guid. If the label has a pool guid,
- * check that it matches too. (Inactive spares
- * and L2ARCs do not have any pool guid in the
- * label.)
- */
- if ((pguid != 0 &&
- pguid != spa_guid(vd->vdev_spa)) ||
- vguid != vd->vdev_guid) {
- vdev_geom_close_locked(vd);
- cp = NULL;
- ZFS_LOG(1, "guid mismatch for provider %s: "
- "%ju:%ju != %ju:%ju.", vd->vdev_path,
- (uintmax_t)spa_guid(vd->vdev_spa),
- (uintmax_t)vd->vdev_guid,
- (uintmax_t)pguid, (uintmax_t)vguid);
- } else {
- ZFS_LOG(1, "guid match for provider %s.",
- vd->vdev_path);
- }
- }
+ if (!check_guid || vdev_attach_ok(vd, pp))
+ cp = vdev_geom_attach(pp, vd);
}
return (cp);
More information about the svn-src-head
mailing list