Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107197852
D10391.id27426.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D10391.id27426.diff
View Options
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
@@ -49,6 +49,13 @@
.attrchanged = vdev_geom_attrchanged,
};
+struct consumer_vdev_elem {
+ vdev_t *vd;
+ SLIST_ENTRY(consumer_vdev_elem) elems;
+};
+
+SLIST_HEAD(consumer_priv_t, consumer_vdev_elem);
+
DECLARE_GEOM_CLASS(zfs_vdev_class, zfs_vdev);
SYSCTL_DECL(_vfs_zfs_vdev);
@@ -85,21 +92,16 @@
}
static void
-vdev_geom_set_physpath(struct g_consumer *cp, boolean_t do_null_update)
+vdev_geom_set_physpath(vdev_t *vd, struct g_consumer *cp,
+ boolean_t do_null_update)
{
boolean_t needs_update = B_FALSE;
- vdev_t *vd;
char *physpath;
int error, physpath_len;
- if (g_access(cp, 1, 0, 0) != 0)
- return;
-
- vd = cp->private;
physpath_len = MAXPATHLEN;
physpath = g_malloc(physpath_len, M_WAITOK|M_ZERO);
error = g_io_getattr("GEOM::physpath", cp, &physpath_len, physpath);
- g_access(cp, -1, 0, 0);
if (error == 0) {
char *old_physpath;
@@ -130,37 +132,40 @@
static void
vdev_geom_attrchanged(struct g_consumer *cp, const char *attr)
{
- vdev_t *vd;
char *old_physpath;
+ struct consumer_priv_t *priv;
+ struct consumer_vdev_elem *elem;
int error;
- vd = cp->private;
- if (vd == NULL)
+ priv = (struct consumer_priv_t*)&cp->private;
+ if (SLIST_EMPTY(priv))
return;
- if (strcmp(attr, "GEOM::rotation_rate") == 0) {
- vdev_geom_set_rotation_rate(vd, cp);
- return;
+ SLIST_FOREACH(elem, priv, elems) {
+ vdev_t *vd = elem->vd;
+ if (strcmp(attr, "GEOM::rotation_rate") == 0) {
+ vdev_geom_set_rotation_rate(vd, cp);
+ return;
+ }
+ if (strcmp(attr, "GEOM::physpath") == 0) {
+ vdev_geom_set_physpath(vd, cp, /*null_update*/B_TRUE);
+ return;
+ }
}
-
- if (strcmp(attr, "GEOM::physpath") == 0) {
- vdev_geom_set_physpath(cp, /*do_null_update*/B_TRUE);
- return;
- }
}
static void
vdev_geom_orphan(struct g_consumer *cp)
{
- vdev_t *vd;
+ struct consumer_priv_t *priv;
+ struct consumer_vdev_elem *elem;
g_topology_assert();
- vd = cp->private;
- if (vd == NULL) {
+ priv = (struct consumer_priv_t*)&cp->private;
+ if (SLIST_EMPTY(priv))
/* Vdev close in progress. Ignore the event. */
return;
- }
/*
* Orphan callbacks occur from the GEOM event thread.
@@ -176,8 +181,12 @@
* async removal support to invoke a close on this
* vdev once it is safe to do so.
*/
- vd->vdev_remove_wanted = B_TRUE;
- spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE);
+ SLIST_FOREACH(elem, priv, elems) {
+ vdev_t *vd = elem->vd;
+
+ vd->vdev_remove_wanted = B_TRUE;
+ spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE);
+ }
}
static struct g_consumer *
@@ -265,21 +274,8 @@
}
}
- /*
- * BUG: cp may already belong to a vdev. This could happen if:
- * 1) That vdev is a shared spare, or
- * 2) We are trying to reopen a missing vdev and we are scanning by
- * guid. In that case, we'll ultimately fail to open this consumer,
- * but not until after setting the private field.
- * The solution is to:
- * 1) Don't set the private field until after the open succeeds, and
- * 2) Set it to a linked list of vdevs, not just a single vdev
- */
- cp->private = vd;
- if (vd != NULL) {
+ if (vd != NULL)
vd->vdev_tsd = cp;
- vdev_geom_set_physpath(cp, /*do_null_update*/B_FALSE);
- }
cp->flags |= G_CF_DIRECT_SEND | G_CF_DIRECT_RECEIVE;
return (cp);
@@ -289,16 +285,12 @@
vdev_geom_detach(struct g_consumer *cp, boolean_t open_for_read)
{
struct g_geom *gp;
- vdev_t *vd;
g_topology_assert();
ZFS_LOG(1, "Detaching from %s.",
cp->provider && cp->provider->name ? cp->provider->name : "NULL");
- vd = cp->private;
- cp->private = NULL;
-
gp = cp->geom;
if (open_for_read)
g_access(cp, -1, 0, -1);
@@ -324,16 +316,26 @@
vdev_geom_close_locked(vdev_t *vd)
{
struct g_consumer *cp;
+ struct consumer_priv_t *priv;
+ struct consumer_vdev_elem *elem, *elem_temp;
g_topology_assert();
cp = vd->vdev_tsd;
- vd->vdev_tsd = NULL;
vd->vdev_delayed_close = B_FALSE;
if (cp == NULL)
return;
ZFS_LOG(1, "Closing access to %s.", cp->provider->name);
+ KASSERT(cp->private != NULL, ("%s: cp->private is NULL", __func__));
+ priv = (struct consumer_priv_t*)&cp->private;
+ vd->vdev_tsd = NULL;
+ SLIST_FOREACH_SAFE(elem, priv, elems, elem_temp) {
+ if (elem->vd == vd) {
+ SLIST_REMOVE(priv, elem, consumer_vdev_elem, elems);
+ g_free(elem);
+ }
+ }
vdev_geom_detach(cp, B_TRUE);
}
@@ -870,11 +872,36 @@
cp = NULL;
}
}
+ if (cp != NULL) {
+ struct consumer_priv_t *priv;
+ struct consumer_vdev_elem *elem;
+ if (cp->private == NULL) {
+
+ KASSERT(sizeof(cp->private) == sizeof(priv),
+ ("%s: consumer_priv_t can't be stored in "
+ "g_consumer.private", __func__));
+ priv = (struct consumer_priv_t*)&cp->private;
+ SLIST_INIT(priv);
+ } else
+ priv = (struct consumer_priv_t*)(&cp->private);
+ elem = g_malloc(sizeof(*elem), M_WAITOK|M_ZERO);
+ elem->vd = vd;
+ SLIST_INSERT_HEAD(priv, elem, elems);
+ }
+
/* Fetch initial physical path information for this device. */
if (cp != NULL)
vdev_geom_attrchanged(cp, "GEOM::physpath");
+ /*
+ * Set other GEOM characteristics
+ */
+ if (cp != NULL) {
+ vdev_geom_set_physpath(vd, cp, /*do_null_update*/B_FALSE);
+ vdev_geom_set_rotation_rate(vd, cp);
+ }
+
g_topology_unlock();
PICKUP_GIANT();
if (cp == NULL) {
@@ -904,11 +931,6 @@
* we will try again.
*/
vd->vdev_nowritecache = B_FALSE;
-
- /*
- * Determine the device's rotation rate.
- */
- vdev_geom_set_rotation_rate(vd, cp);
return (0);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jan 12, 1:04 PM (19 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15769644
Default Alt Text
D10391.id27426.diff (5 KB)
Attached To
Mode
D10391: vdev_geom may associate multiple vdevs per g_consumer
Attached
Detach File
Event Timeline
Log In to Comment