kern/125149: [zfs][nfs] changing into .zfs dir from nfs clientcauses endless panic loop

Jaakko Heinonen jh at saunalahti.fi
Thu Oct 9 19:50:04 UTC 2008


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

From: Jaakko Heinonen <jh at saunalahti.fi>
To: Weldon Godfrey <wgodfrey at ena.com>
Cc: bug-followup at freebsd.org
Subject: Re: kern/125149: [zfs][nfs] changing into .zfs dir from nfs
	clientcauses endless panic loop
Date: Thu, 9 Oct 2008 22:44:38 +0300

 On 2008-10-09, Weldon Godfrey wrote:
 > Is this patch based on 8-CURRENT or 7-RELEASE?  If 8-CURRENT, I don't
 > know if I can test as I would like to stick with 7-RELEASE for now.
 
 Patches are against head. Sorry that I didn't mention that. The nfs
 patch applies against RELENG_7 with offset and here's the zfs patch
 against RELENG_7. (Disclaimer: compile tested only)
 
 %%%
 Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
 ===================================================================
 --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	(revision 183727)
 +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	(working copy)
 @@ -759,9 +759,10 @@ zfs_vget(vfs_t *vfsp, ino_t ino, int fla
  		VN_RELE(ZTOV(zp));
  		err = EINVAL;
  	}
 -	if (err != 0)
 -		*vpp = NULL;
 -	else {
 +	if (err != 0) {
 +		/* try .zfs control directory */
 +		err = zfsctl_vget(vfsp, ino, flags, vpp);
 +	} else {
  		*vpp = ZTOV(zp);
  		vn_lock(*vpp, flags, curthread);
  	}
 Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
 ===================================================================
 --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	(revision 183727)
 +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	(working copy)
 @@ -1044,6 +1044,63 @@ zfsctl_lookup_objset(vfs_t *vfsp, uint64
  	return (error);
  }
  
 +int
 +zfsctl_vget(vfs_t *vfsp, uint64_t nodeid, int flags, vnode_t **vpp)
 +{
 +	zfsvfs_t *zfsvfs = vfsp->vfs_data;
 +	vnode_t *dvp, *vp;
 +	zfsctl_snapdir_t *sdp;
 +	zfsctl_node_t *zcp;
 +	zfs_snapentry_t *sep;
 +	int error;
 +
 +	*vpp = NULL;
 +
 +	ASSERT(zfsvfs->z_ctldir != NULL);
 +	error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp,
 +	    NULL, 0, NULL, kcred);
 +	if (error != 0)
 +		return (error);
 +
 +	if (nodeid == ZFSCTL_INO_ROOT || nodeid == ZFSCTL_INO_SNAPDIR) {
 +		if (nodeid == ZFSCTL_INO_SNAPDIR)
 +			*vpp = dvp;
 +		else {
 +			VN_RELE(dvp);
 +			*vpp = zfsvfs->z_ctldir;
 +			VN_HOLD(*vpp);
 +		}
 +		/* XXX: LK_RETRY? */
 +		vn_lock(*vpp, flags | LK_RETRY, curthread);
 +		return (0);
 +	}
 +		
 +	sdp = dvp->v_data;
 +
 +	mutex_enter(&sdp->sd_lock);
 +	sep = avl_first(&sdp->sd_snaps);
 +	while (sep != NULL) {
 +		vp = sep->se_root;
 +		zcp = vp->v_data;
 +		if (zcp->zc_id == nodeid)
 +			break;
 +
 +		sep = AVL_NEXT(&sdp->sd_snaps, sep);
 +	}
 +
 +	if (sep != NULL) {
 +		VN_HOLD(vp);
 +		*vpp = vp;
 +		vn_lock(*vpp, flags, curthread);
 +	} else
 +		error = EINVAL;
 +
 +	mutex_exit(&sdp->sd_lock);
 +
 +	VN_RELE(dvp);
 +
 +	return (error);
 +}
  /*
   * Unmount any snapshots for the given filesystem.  This is called from
   * zfs_umount() - if we have a ctldir, then go through and unmount all the
 Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ctldir.h
 ===================================================================
 --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ctldir.h	(revision 183727)
 +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ctldir.h	(working copy)
 @@ -60,6 +60,7 @@ int zfsctl_root_lookup(vnode_t *dvp, cha
      int flags, vnode_t *rdir, cred_t *cr);
  
  int zfsctl_lookup_objset(vfs_t *vfsp, uint64_t objsetid, zfsvfs_t **zfsvfsp);
 +int zfsctl_vget(vfs_t *vfsp, uint64_t nodeid, int flags, vnode_t **vpp);
  
  #define	ZFSCTL_INO_ROOT		0x1
  #define	ZFSCTL_INO_SNAPDIR	0x2
 %%%
 
 -- 
 Jaakko


More information about the freebsd-fs mailing list