kern/132068: page fault when using ZFS over NFS on
7.1-RELEASE/amd64
Jaakko Heinonen
jh at saunalahti.fi
Thu Feb 26 09:50:03 PST 2009
The following reply was made to PR kern/132068; it has been noted by GNATS.
From: Jaakko Heinonen <jh at saunalahti.fi>
To: Edward Fisk <7ogcg7g02 at sneakemail.com>
Cc: bug-followup at FreeBSD.org
Subject: Re: kern/132068: page fault when using ZFS over NFS on
7.1-RELEASE/amd64
Date: Thu, 26 Feb 2009 19:44:21 +0200
On 2009-02-24, Edward Fisk wrote:
> (kgdb) p *nvp
> $1 = {v_type = VBAD, v_tag = 0xffffffff807e5627 "none", v_op = 0xffffffff80a18220, v_data = 0x0, v_mount = 0x0, v_nmntvnodes = {
Thanks for the info. If you can't try 8.0-CURRENT here is an attempt to
backport some bits from head to RELENG_7. I have only compile tested the
patch so be careful.
--- patch begins here ---
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c (revision 189044)
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c (working copy)
@@ -554,10 +554,10 @@ zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_
dmu_buf_t *db;
znode_t *zp;
vnode_t *vp;
- int err;
+ int err, first = 1;
*zpp = NULL;
-
+again:
ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num);
err = dmu_bonus_hold(zfsvfs->z_os, obj_num, NULL, &db);
@@ -574,64 +574,60 @@ zfs_zget(zfsvfs_t *zfsvfs, uint64_t obj_
return (EINVAL);
}
- ASSERT(db->db_object == obj_num);
- ASSERT(db->db_offset == -1);
- ASSERT(db->db_data != NULL);
-
zp = dmu_buf_get_user(db);
-
if (zp != NULL) {
mutex_enter(&zp->z_lock);
+ /*
+ * Since we do immediate eviction of the z_dbuf, we
+ * should never find a dbuf with a znode that doesn't
+ * know about the dbuf.
+ */
+ ASSERT3P(zp->z_dbuf, ==, db);
ASSERT3U(zp->z_id, ==, obj_num);
if (zp->z_unlinked) {
- dmu_buf_rele(db, NULL);
- mutex_exit(&zp->z_lock);
- ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
- return (ENOENT);
- } else if (zp->z_dbuf_held) {
- dmu_buf_rele(db, NULL);
+ err = ENOENT;
} else {
- zp->z_dbuf_held = 1;
- VFS_HOLD(zfsvfs->z_vfs);
- }
-
- if (ZTOV(zp) != NULL)
- VN_HOLD(ZTOV(zp));
- else {
- err = getnewvnode("zfs", zfsvfs->z_vfs, &zfs_vnodeops,
- &zp->z_vnode);
- ASSERT(err == 0);
- vp = ZTOV(zp);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
- vp->v_data = (caddr_t)zp;
- vp->v_vnlock->lk_flags |= LK_CANRECURSE;
- vp->v_vnlock->lk_flags &= ~LK_NOSHARE;
- vp->v_type = IFTOVT((mode_t)zp->z_phys->zp_mode);
- if (vp->v_type == VDIR)
- zp->z_zn_prefetch = B_TRUE; /* z_prefetch default is enabled */
- vp->v_vflag |= VV_FORCEINSMQ;
- err = insmntque(vp, zfsvfs->z_vfs);
- vp->v_vflag &= ~VV_FORCEINSMQ;
- KASSERT(err == 0, ("insmntque() failed: error %d", err));
- VOP_UNLOCK(vp, 0, curthread);
+ if (ZTOV(zp) != NULL)
+ VN_HOLD(ZTOV(zp));
+ else {
+ if (first) {
+ ZFS_LOG(1, "dying znode detected (zp=%p)", zp);
+ first = 0;
+ }
+ /*
+ * znode is dying so we can't reuse it, we must
+ * wait until destruction is completed.
+ */
+ dmu_buf_rele(db, NULL);
+ mutex_exit(&zp->z_lock);
+ ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+ tsleep(zp, 0, "zcollide", 1);
+ goto again;
+ }
+ *zpp = zp;
+ err = 0;
}
+ dmu_buf_rele(db, NULL);
mutex_exit(&zp->z_lock);
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
- *zpp = zp;
- return (0);
+ return (err);
}
/*
* Not found create new znode/vnode
*/
zp = zfs_znode_alloc(zfsvfs, db, obj_num, doi.doi_data_block_size);
- ASSERT3U(zp->z_id, ==, obj_num);
- zfs_znode_dmu_init(zp);
+
+ vp = ZTOV(zp);
+ vp->v_vflag |= VV_FORCEINSMQ;
+ err = insmntque(vp, zfsvfs->z_vfs);
+ vp->v_vflag &= ~VV_FORCEINSMQ;
+ KASSERT(err == 0, ("insmntque() failed: error %d", err));
+ VOP_UNLOCK(vp, 0, curthread);
+
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
*zpp = zp;
- if ((vp = ZTOV(zp)) != NULL)
- VOP_UNLOCK(vp, 0, curthread);
return (0);
}
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (revision 189044)
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (working copy)
@@ -3475,9 +3475,9 @@ zfs_freebsd_reclaim(ap)
ASSERT(zp->z_phys);
ASSERT(zp->z_dbuf_held);
zfsvfs = zp->z_zfsvfs;
+ ZTOV(zp) = NULL;
if (!zp->z_unlinked) {
zp->z_dbuf_held = 0;
- ZTOV(zp) = NULL;
mutex_exit(&zp->z_lock);
dmu_buf_rele(zp->z_dbuf, NULL);
} else {
--- patch ends here ---
--
Jaakko
More information about the freebsd-fs
mailing list