Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F168265645
D5974.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D5974.diff
View Options
Index: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
===================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
@@ -61,6 +61,9 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
}
-
- g_destroy_consumer(zcp);
- g_destroy_geom(zgp);
g_topology_unlock();
PICKUP_GIANT();
@@ -570,21 +558,55 @@
}
}
+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 @@
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 @@
break;
}
end:
- g_destroy_consumer(zcp);
- g_destroy_geom(zgp);
return (cp);
}
@@ -667,7 +672,6 @@
{
struct g_provider *pp;
struct g_consumer *cp;
- uint64_t pguid, vguid;
g_topology_assert();
@@ -675,34 +679,8 @@
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);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 28, 6:50 AM (5 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37441509
Default Alt Text
D5974.diff (9 KB)
Attached To
Mode
D5974: Refactor vdev_geom_attach and friends to reduce code duplication
Attached
Detach File
Event Timeline
Log In to Comment