summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authormaybee <none@none>2006-03-10 12:34:02 -0800
committermaybee <none@none>2006-03-10 12:34:02 -0800
commitbbf4a8df08a5ccce4c75fe2b82fafa4bb55b77db (patch)
tree188282fb3dbeeca47b2804eb41227ad6c8e9412d /usr/src
parente3c625046462319a7c7ce069b2d83c1923ffc094 (diff)
downloadillumos-gate-bbf4a8df08a5ccce4c75fe2b82fafa4bb55b77db.tar.gz
6395526 assertion failed: refcount_count(&ab->b_refcnt) == 1 (0x2 == 0x1)
6395628 panic:assertion failed: svp->v_count == 1 (0x2 == 0x1), file: ./common/fs/zfs/zfs_ctldir.c line: 939
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/fs/zfs/arc.c36
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ctldir.c30
2 files changed, 39 insertions, 27 deletions
diff --git a/usr/src/uts/common/fs/zfs/arc.c b/usr/src/uts/common/fs/zfs/arc.c
index 904e746721..9b5e279e7b 100644
--- a/usr/src/uts/common/fs/zfs/arc.c
+++ b/usr/src/uts/common/fs/zfs/arc.c
@@ -1565,7 +1565,7 @@ arc_getbuf_func(zio_t *zio, arc_buf_t *buf, void *arg)
static void
arc_read_done(zio_t *zio)
{
- arc_buf_hdr_t *hdr;
+ arc_buf_hdr_t *hdr, *found;
arc_buf_t *buf;
arc_buf_t *abuf; /* buffer we're assigning to callback */
kmutex_t *hash_lock;
@@ -1575,22 +1575,19 @@ arc_read_done(zio_t *zio)
buf = zio->io_private;
hdr = buf->b_hdr;
- if (!HDR_FREED_IN_READ(hdr)) {
- arc_buf_hdr_t *found;
-
- found = buf_hash_find(zio->io_spa, &hdr->b_dva, hdr->b_birth,
+ /*
+ * The hdr was inserted into hash-table and removed from lists
+ * prior to starting I/O. We should find this header, since
+ * it's in the hash table, and it should be legit since it's
+ * not possible to evict it during the I/O. The only possible
+ * reason for it not to be found is if we were freed during the
+ * read.
+ */
+ found = buf_hash_find(zio->io_spa, &hdr->b_dva, hdr->b_birth,
&hash_lock);
- /*
- * Buffer was inserted into hash-table and removed from lists
- * prior to starting I/O. We should find this header, since
- * it's in the hash table, and it should be legit since it's
- * not possible to evict it during the I/O.
- */
-
- ASSERT(found);
- ASSERT(DVA_EQUAL(&hdr->b_dva, BP_IDENTITY(zio->io_bp)));
- }
+ ASSERT((found == NULL && HDR_FREED_IN_READ(hdr) && hash_lock == NULL) ||
+ (found == hdr && DVA_EQUAL(&hdr->b_dva, BP_IDENTITY(zio->io_bp))));
/* byteswap if necessary */
callback_list = hdr->b_acb;
@@ -1656,7 +1653,7 @@ arc_read_done(zio_t *zio)
*/
cv_broadcast(&hdr->b_cv);
- if (!HDR_FREED_IN_READ(hdr)) {
+ if (hash_lock) {
/*
* Only call arc_access on anonymous buffers. This is because
* if we've issued an I/O for an evicted buffer, we've already
@@ -2246,7 +2243,12 @@ arc_free(zio_t *pio, spa_t *spa, uint64_t txg, blkptr_t *bp,
arc_hdr_destroy(ab);
atomic_add_64(&arc.deleted, 1);
} else {
- ASSERT3U(refcount_count(&ab->b_refcnt), ==, 1);
+ /*
+ * We could have an outstanding read on this
+ * block, so multiple active references are
+ * possible. But we should only have a single
+ * data buffer associated at this point.
+ */
ASSERT3U(ab->b_datacnt, ==, 1);
if (HDR_IO_IN_PROGRESS(ab))
ab->b_flags |= ARC_FREED_IN_READ;
diff --git a/usr/src/uts/common/fs/zfs/zfs_ctldir.c b/usr/src/uts/common/fs/zfs/zfs_ctldir.c
index 7b267b5a38..c4751b879c 100644
--- a/usr/src/uts/common/fs/zfs/zfs_ctldir.c
+++ b/usr/src/uts/common/fs/zfs/zfs_ctldir.c
@@ -431,8 +431,11 @@ zfsctl_unmount_snap(vnode_t *dvp, const char *name, int force, cred_t *cr)
return (err);
VN_HOLD(sep->se_root);
- if ((err = dounmount(vn_mountedvfs(sep->se_root), force, kcred)) != 0)
+ err = dounmount(vn_mountedvfs(sep->se_root), force, kcred);
+ if (err) {
+ VN_RELE(sep->se_root);
return (err);
+ }
ASSERT(sep->se_root->v_count == 1);
gfs_vop_inactive(sep->se_root, cr);
@@ -618,17 +621,20 @@ zfsctl_snapdir_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp,
if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) != NULL) {
*vpp = sep->se_root;
VN_HOLD(*vpp);
- /*
- * If the snapshot was unmounted behind our backs,
- * try to remount it.
- */
- if (traverse(vpp) != 0) {
- ASSERT(!vn_ismntpt(*vpp));
+ err = traverse(vpp);
+ if (err) {
+ VN_RELE(*vpp);
+ *vpp = NULL;
+ } else if (*vpp == sep->se_root) {
+ /*
+ * The snapshot was unmounted behind our backs,
+ * try to remount it.
+ */
goto domount;
}
mutex_exit(&sdp->sd_lock);
ZFS_EXIT(zfsvfs);
- return (0);
+ return (err);
}
/*
@@ -898,8 +904,12 @@ zfsctl_lookup_objset(vfs_t *vfsp, uint64_t objsetid, zfsvfs_t **zfsvfsp)
if (sep != NULL) {
VN_HOLD(vp);
error = traverse(&vp);
- if (error == 0)
- *zfsvfsp = VTOZ(vp)->z_zfsvfs;
+ if (error == 0) {
+ if (vp == sep->se_root)
+ error = EINVAL;
+ else
+ *zfsvfsp = VTOZ(vp)->z_zfsvfs;
+ }
mutex_exit(&sdp->sd_lock);
VN_RELE(vp);
} else {