Date: Thu, 26 Feb 2009 17:50:02 GMT From: Jaakko Heinonen <jh@saunalahti.fi> To: freebsd-fs@FreeBSD.org Subject: Re: kern/132068: page fault when using ZFS over NFS on 7.1-RELEASE/amd64 Message-ID: <200902261750.n1QHo2Vc050101@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/132068; it has been noted by GNATS. From: Jaakko Heinonen <jh@saunalahti.fi> To: Edward Fisk <7ogcg7g02@sneakemail.com> Cc: bug-followup@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902261750.n1QHo2Vc050101>