Author: avg Date: Sat Sep 22 17:42:53 2012 New Revision: 240831 URL: http://svn.freebsd.org/changeset/base/240831
Log: zfs: allow a zvol to be used as a pool vdev, again Do this by checking if spa_namespace_lock is already held and not taking it again in that case. Add a comment explaining why that is done and why it is safe. Reviewed by: pjd MFC after: 24 days Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c ============================================================================== --- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Sat Sep 22 17:41:56 2012 (r240830) +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Sat Sep 22 17:42:53 2012 (r240831) @@ -878,27 +878,36 @@ zvol_open(struct g_provider *pp, int fla { zvol_state_t *zv; int err = 0; + boolean_t locked = B_FALSE; - if (MUTEX_HELD(&spa_namespace_lock)) { - /* - * If the spa_namespace_lock is being held, it means that ZFS - * is trying to open ZVOL as its VDEV. This is not supported. - */ - return (EOPNOTSUPP); + /* + * Protect against recursively entering spa_namespace_lock + * when spa_open() is used for a pool on a (local) ZVOL(s). + * This is needed since we replaced upstream zfsdev_state_lock + * with spa_namespace_lock in the ZVOL code. + * We are using the same trick as spa_open(). + * Note that calls in zvol_first_open which need to resolve + * pool name to a spa object will enter spa_open() + * recursively, but that function already has all the + * necessary protection. + */ + if (!MUTEX_HELD(&spa_namespace_lock)) { + mutex_enter(&spa_namespace_lock); + locked = B_TRUE; } - mutex_enter(&spa_namespace_lock); - zv = pp->private; if (zv == NULL) { - mutex_exit(&spa_namespace_lock); + if (locked) + mutex_exit(&spa_namespace_lock); return (ENXIO); } if (zv->zv_total_opens == 0) err = zvol_first_open(zv); if (err) { - mutex_exit(&spa_namespace_lock); + if (locked) + mutex_exit(&spa_namespace_lock); return (err); } if ((flag & FWRITE) && (zv->zv_flags & ZVOL_RDONLY)) { @@ -920,13 +929,15 @@ zvol_open(struct g_provider *pp, int fla #endif zv->zv_total_opens += count; - mutex_exit(&spa_namespace_lock); + if (locked) + mutex_exit(&spa_namespace_lock); return (err); out: if (zv->zv_total_opens == 0) zvol_last_close(zv); - mutex_exit(&spa_namespace_lock); + if (locked) + mutex_exit(&spa_namespace_lock); return (err); } @@ -936,12 +947,18 @@ zvol_close(struct g_provider *pp, int fl { zvol_state_t *zv; int error = 0; + boolean_t locked = B_FALSE; - mutex_enter(&spa_namespace_lock); + /* See comment in zvol_open(). */ + if (!MUTEX_HELD(&spa_namespace_lock)) { + mutex_enter(&spa_namespace_lock); + locked = B_TRUE; + } zv = pp->private; if (zv == NULL) { - mutex_exit(&spa_namespace_lock); + if (locked) + mutex_exit(&spa_namespace_lock); return (ENXIO); } @@ -964,7 +981,8 @@ zvol_close(struct g_provider *pp, int fl if (zv->zv_total_opens == 0) zvol_last_close(zv); - mutex_exit(&spa_namespace_lock); + if (locked) + mutex_exit(&spa_namespace_lock); return (error); } _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"