atom feed4 messages in org.freebsd.freebsd-fsRe: kern/132068: page fault when usin...
FromSent OnAttachments
Jaakko HeinonenFeb 24, 2009 11:39 am 
Edward FiskFeb 24, 2009 12:59 pm 
Edward FiskFeb 25, 2009 4:09 am 
Jaakko HeinonenFeb 26, 2009 9:49 am 
Subject:Re: kern/132068: page fault when using ZFS over NFS on 7.1-RELEASE/amd64
From:Jaakko Heinonen (jh@saunalahti.fi)
Date:Feb 26, 2009 9:49:37 am
List:org.freebsd.freebsd-fs

The following reply was made to PR kern/132068; it has been noted by GNATS.

From: Jaakko Heinonen <jh@saunalahti.fi> To: Edward Fisk <7ogc@sneakemail.com> Cc: bug-@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