From nobody@FreeBSD.org  Wed Oct 21 01:34:56 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 6A6F2106568D
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 21 Oct 2009 01:34:56 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 598008FC16
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 21 Oct 2009 01:34:56 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n9L1Yu48034219
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 21 Oct 2009 01:34:56 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id n9L1Yu2m034218;
	Wed, 21 Oct 2009 01:34:56 GMT
	(envelope-from nobody)
Message-Id: <200910210134.n9L1Yu2m034218@www.freebsd.org>
Date: Wed, 21 Oct 2009 01:34:56 GMT
From: Carl Chave <online@chave.us>
To: freebsd-gnats-submit@FreeBSD.org
Subject: Write attempt to file in ZFS snapshot dir causes panic
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         139806
>Category:       kern
>Synopsis:       [zfs] [panic] Write attempt to file in ZFS snapshot dir causes panic
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pjd
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Oct 21 01:40:02 UTC 2009
>Closed-Date:    Sat Nov 14 14:28:46 UTC 2009
>Last-Modified:  Thu Jan  7 09:40:06 UTC 2010
>Originator:     Carl Chave
>Release:        8.0-RC1-amd64-dvd1.iso
>Organization:
>Environment:
8.0-RC1-amd64-dvd1.iso booted to Fixit environment in vmware.
>Description:
Attempting to modify a file in a zfs snapshot directory causes kernel panic with the following message:

panic: dirtying snapshot!

Maybe related to this PR:

http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/138764
>How-To-Repeat:
1. load zfs from bootloader prompt and then boot.
2. enter fixit environment.
3. import zpool (in this case a 2 disk vmware mirror named sodpool)
4. cd to previously created snapshot at sodpool/test/myfs/.zfs/snapshot/one
5. attempting to create a new file here results in:

Fixit# echo hello > hello.txt
cannot create hello.txt: Read-only file system

6. That seems like the desired response.  Next, attempt to modify a
file that already exists in the snapshot:

Fixit# echo hello >> test.txt
panic: dirtying snapshot!
>Fix:
Unknown

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-amd64->freebsd-fs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Wed Oct 21 20:15:16 UTC 2009 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=139806 

From: Jaakko Heinonen <jh@FreeBSD.org>
To: Carl Chave <online@chave.us>
Cc: bug-followup@FreeBSD.org
Subject: Re: kern/139806: [zfs] [panic] Write attempt to file in ZFS
	snapshot dir causes panic
Date: Thu, 22 Oct 2009 22:50:56 +0300

 Hi,
 
 On 2009-10-21, Carl Chave wrote:
 > Fixit# echo hello >> test.txt
 > panic: dirtying snapshot!
 
 The problem seems to be that in certain conditions zfs_freebsd_access()
 uses only vaccess(9) for access check. However vaccess(9) doesn't handle
 the read-only file system case.
 
 Could you try this patch?
 
 --- patch begins here ---
 Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
 ===================================================================
 --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	(revision 198368)
 +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	(working copy)
 @@ -3989,7 +3989,12 @@
  		struct thread *a_td;
  	} */ *ap;
  {
 +	int error;
  
 +	error = zfs_access(ap->a_vp, ap->a_accmode, 0, ap->a_cred, NULL);
 +	if (error != 0)
 +		return (error);
 +
  	/*
  	 * ZFS itself only knowns about VREAD, VWRITE and VEXEC, the rest
  	 * we have to handle by calling vaccess().
 @@ -3999,11 +4004,11 @@
  		znode_t *zp = VTOZ(vp);
  		znode_phys_t *zphys = zp->z_phys;
  
 -		return (vaccess(vp->v_type, zphys->zp_mode, zphys->zp_uid,
 -		    zphys->zp_gid, ap->a_accmode, ap->a_cred, NULL));
 +		error = vaccess(vp->v_type, zphys->zp_mode, zphys->zp_uid,
 +		    zphys->zp_gid, ap->a_accmode, ap->a_cred, NULL);
  	}
  
 -	return (zfs_access(ap->a_vp, ap->a_accmode, 0, ap->a_cred, NULL));
 +	return (error);
  }
  
  static int
 --- patch ends here ---
 
 -- 
 Jaakko

From: Carl Chave <carl@chave.us>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/139806: [zfs] [panic] Write attempt to file in ZFS snapshot 
	dir causes panic
Date: Sun, 25 Oct 2009 10:47:40 -0400

 Rebuilt zfs.ko using:
 
 head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
 (version 197861 + this patch)
 head/sys/cddl/compat/opensolaris/kern/opensolaris_policy.c (version 197861)
 head/sys/cddl/compat/opensolaris/sys/policy.h (version 197861)
 
 Resulting zfs.ko works as expected and does not panic when attempting
 to modify an existing snapshot file as described in the original PR.
 
 On Thu, Oct 22, 2009 at 3:50 PM, Jaakko Heinonen <jh@freebsd.org> wrote:
 >
 > Hi,
 >
 > On 2009-10-21, Carl Chave wrote:
 >> Fixit# echo hello >> test.txt
 >> panic: dirtying snapshot!
 >
 > The problem seems to be that in certain conditions zfs_freebsd_access()
 > uses only vaccess(9) for access check. However vaccess(9) doesn't handle
 > the read-only file system case.
 >
 > Could you try this patch?
 >
 > --- patch begins here ---
 > Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 > --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c =A0(revisi=
 on 198368)
 > +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c =A0(workin=
 g copy)
 > @@ -3989,7 +3989,12 @@
 > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct thread *a_td;
 > =A0 =A0 =A0 =A0} */ *ap;
 > =A0{
 > + =A0 =A0 =A0 int error;
 >
 > + =A0 =A0 =A0 error =3D zfs_access(ap->a_vp, ap->a_accmode, 0, ap->a_cred=
 , NULL);
 > + =A0 =A0 =A0 if (error !=3D 0)
 > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return (error);
 > +
 > =A0 =A0 =A0 =A0/*
 > =A0 =A0 =A0 =A0 * ZFS itself only knowns about VREAD, VWRITE and VEXEC, t=
 he rest
 > =A0 =A0 =A0 =A0 * we have to handle by calling vaccess().
 > @@ -3999,11 +4004,11 @@
 > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0znode_t *zp =3D VTOZ(vp);
 > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0znode_phys_t *zphys =3D zp->z_phys;
 >
 > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 return (vaccess(vp->v_type, zphys->zp_mode,=
  zphys->zp_uid,
 > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 zphys->zp_gid, ap->a_accmode, ap->a=
 _cred, NULL));
 > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 error =3D vaccess(vp->v_type, zphys->zp_mod=
 e, zphys->zp_uid,
 > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 zphys->zp_gid, ap->a_accmode, ap->a=
 _cred, NULL);
 > =A0 =A0 =A0 =A0}
 >
 > - =A0 =A0 =A0 return (zfs_access(ap->a_vp, ap->a_accmode, 0, ap->a_cred, =
 NULL));
 > + =A0 =A0 =A0 return (error);
 > =A0}
 >
 > =A0static int
 > --- patch ends here ---
 >
 > --
 > Jaakko
 >
State-Changed-From-To: open->patched 
State-Changed-By: pjd 
State-Changed-When: ptk 30 pa 2009 23:33:39 UTC 
State-Changed-Why:  
Fix committed to HEAD. Thank you for the report! 


Responsible-Changed-From-To: freebsd-fs->pjd 
Responsible-Changed-By: pjd 
Responsible-Changed-When: ptk 30 pa 2009 23:33:39 UTC 
Responsible-Changed-Why:  
I'll take this one. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=139806 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/139806: commit references a PR
Date: Fri, 30 Oct 2009 23:33:20 +0000 (UTC)

 Author: pjd
 Date: Fri Oct 30 23:33:06 2009
 New Revision: 198703
 URL: http://svn.freebsd.org/changeset/base/198703
 
 Log:
   - zfs_zaccess() can handle VAPPEND too, so map V_APPEND to VAPPEND and call
     zfs_access() instead of vaccess() in this case as well.
   - If VADMIN is specified with another V* flag (unlikely) call both
     zfs_access() and vaccess() after spliting V* flags.
   
   This fixes "dirtying snapshot!" panic.
   
   PR:		kern/139806
   Reported by:	Carl Chave <carl@chave.us>
   In co-operation with:	jh
   MFC after:	3 days
 
 Modified:
   head/sys/cddl/compat/opensolaris/sys/vnode.h
   head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
   head/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
 
 Modified: head/sys/cddl/compat/opensolaris/sys/vnode.h
 ==============================================================================
 --- head/sys/cddl/compat/opensolaris/sys/vnode.h	Fri Oct 30 21:54:53 2009	(r198702)
 +++ head/sys/cddl/compat/opensolaris/sys/vnode.h	Fri Oct 30 23:33:06 2009	(r198703)
 @@ -57,6 +57,8 @@ typedef	struct vop_vector	vnodeops_t;
  
  #define	v_count	v_usecount
  
 +#define	V_APPEND	VAPPEND
 +
  static __inline int
  vn_is_readonly(vnode_t *vp)
  {
 
 Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
 ==============================================================================
 --- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Fri Oct 30 21:54:53 2009	(r198702)
 +++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Fri Oct 30 23:33:06 2009	(r198703)
 @@ -3989,21 +3989,33 @@ zfs_freebsd_access(ap)
  		struct thread *a_td;
  	} */ *ap;
  {
 +	accmode_t accmode;
 +	int error = 0;
  
  	/*
 -	 * ZFS itself only knowns about VREAD, VWRITE and VEXEC, the rest
 -	 * we have to handle by calling vaccess().
 +	 * ZFS itself only knowns about VREAD, VWRITE, VEXEC and VAPPEND,
  	 */
 -	if ((ap->a_accmode & ~(VREAD|VWRITE|VEXEC)) != 0) {
 -		vnode_t *vp = ap->a_vp;
 -		znode_t *zp = VTOZ(vp);
 -		znode_phys_t *zphys = zp->z_phys;
 +	accmode = ap->a_accmode & (VREAD|VWRITE|VEXEC|VAPPEND);
 +	if (accmode != 0)
 +		error = zfs_access(ap->a_vp, accmode, 0, ap->a_cred, NULL);
  
 -		return (vaccess(vp->v_type, zphys->zp_mode, zphys->zp_uid,
 -		    zphys->zp_gid, ap->a_accmode, ap->a_cred, NULL));
 +	/*
 +	 * VADMIN has to be handled by vaccess().
 +	 */
 +	if (error == 0) {
 +		accmode = ap->a_accmode & ~(VREAD|VWRITE|VEXEC|VAPPEND);
 +		if (accmode != 0) {
 +			vnode_t *vp = ap->a_vp;
 +			znode_t *zp = VTOZ(vp);
 +			znode_phys_t *zphys = zp->z_phys;
 +
 +			error = vaccess(vp->v_type, zphys->zp_mode,
 +			    zphys->zp_uid, zphys->zp_gid, accmode, ap->a_cred,
 +			    NULL);
 +		}
  	}
  
 -	return (zfs_access(ap->a_vp, ap->a_accmode, 0, ap->a_cred, NULL));
 +	return (error);
  }
  
  static int
 
 Modified: head/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
 ==============================================================================
 --- head/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h	Fri Oct 30 21:54:53 2009	(r198702)
 +++ head/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h	Fri Oct 30 23:33:06 2009	(r198703)
 @@ -304,7 +304,6 @@ typedef struct xvattr {
   * VOP_ACCESS flags
   */
  #define	V_ACE_MASK	0x1	/* mask represents  NFSv4 ACE permissions */
 -#define	V_APPEND	0x2	/* want to do append only check */
  
  /*
   * Flags for vnode operations.
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/139806: commit references a PR
Date: Sat, 14 Nov 2009 12:00:23 +0000 (UTC)

 Author: pjd
 Date: Sat Nov 14 11:59:59 2009
 New Revision: 199266
 URL: http://svn.freebsd.org/changeset/base/199266
 
 Log:
   MFC r198703,r199156,r199157:
   
   r198703:
   
   - zfs_zaccess() can handle VAPPEND too, so map V_APPEND to VAPPEND and call
     zfs_access() instead of vaccess() in this case as well.
   - If VADMIN is specified with another V* flag (unlikely) call both
     zfs_access() and vaccess() after spliting V* flags.
   
   This fixes "dirtying snapshot!" panic.
   
   PR:	kern/139806
   Reported by:	Carl Chave <carl@chave.us>
   In co-operation with:	jh
   
   r199156:
   
   Avoid passing invalid mountpoint to getnewvnode().
   
   Reported by:	rwatson
   Tested by:	rwatson
   
   r199157:
   
   Be careful which vattr fields are set during setattr replay.
   Without this fix strange things can appear after unclean shutdown like
   files with mode set to 07777.
   
   Reported by:	des
 
 Modified:
   stable/8/sys/cddl/compat/opensolaris/sys/vnode.h
   stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_replay.c
   stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
   stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
   stable/8/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
 Directory Properties:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
   stable/8/sys/dev/xen/xenpci/   (props changed)
   stable/8/sys/netinet6/   (props changed)
 
 Modified: stable/8/sys/cddl/compat/opensolaris/sys/vnode.h
 ==============================================================================
 --- stable/8/sys/cddl/compat/opensolaris/sys/vnode.h	Sat Nov 14 09:33:51 2009	(r199265)
 +++ stable/8/sys/cddl/compat/opensolaris/sys/vnode.h	Sat Nov 14 11:59:59 2009	(r199266)
 @@ -57,6 +57,8 @@ typedef	struct vop_vector	vnodeops_t;
  
  #define	v_count	v_usecount
  
 +#define	V_APPEND	VAPPEND
 +
  static __inline int
  vn_is_readonly(vnode_t *vp)
  {
 
 Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_replay.c
 ==============================================================================
 --- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_replay.c	Sat Nov 14 09:33:51 2009	(r199265)
 +++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_replay.c	Sat Nov 14 11:59:59 2009	(r199266)
 @@ -60,10 +60,14 @@ zfs_init_vattr(vattr_t *vap, uint64_t ma
  {
  	VATTR_NULL(vap);
  	vap->va_mask = (uint_t)mask;
 -	vap->va_type = IFTOVT(mode);
 -	vap->va_mode = mode & MODEMASK;
 -	vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid;
 -	vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid;
 +	if (mask & AT_TYPE)
 +		vap->va_type = IFTOVT(mode);
 +	if (mask & AT_MODE)
 +		vap->va_mode = mode & MODEMASK;
 +	if (mask & AT_UID)
 +		vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid;
 +	if (mask & AT_GID)
 +		vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid;
  	vap->va_rdev = zfs_cmpldev(rdev);
  	vap->va_nodeid = nodeid;
  }
 
 Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
 ==============================================================================
 --- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Sat Nov 14 09:33:51 2009	(r199265)
 +++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Sat Nov 14 11:59:59 2009	(r199266)
 @@ -3981,21 +3981,33 @@ zfs_freebsd_access(ap)
  		struct thread *a_td;
  	} */ *ap;
  {
 +	accmode_t accmode;
 +	int error = 0;
  
  	/*
 -	 * ZFS itself only knowns about VREAD, VWRITE and VEXEC, the rest
 -	 * we have to handle by calling vaccess().
 +	 * ZFS itself only knowns about VREAD, VWRITE, VEXEC and VAPPEND,
  	 */
 -	if ((ap->a_accmode & ~(VREAD|VWRITE|VEXEC)) != 0) {
 -		vnode_t *vp = ap->a_vp;
 -		znode_t *zp = VTOZ(vp);
 -		znode_phys_t *zphys = zp->z_phys;
 +	accmode = ap->a_accmode & (VREAD|VWRITE|VEXEC|VAPPEND);
 +	if (accmode != 0)
 +		error = zfs_access(ap->a_vp, accmode, 0, ap->a_cred, NULL);
  
 -		return (vaccess(vp->v_type, zphys->zp_mode, zphys->zp_uid,
 -		    zphys->zp_gid, ap->a_accmode, ap->a_cred, NULL));
 +	/*
 +	 * VADMIN has to be handled by vaccess().
 +	 */
 +	if (error == 0) {
 +		accmode = ap->a_accmode & ~(VREAD|VWRITE|VEXEC|VAPPEND);
 +		if (accmode != 0) {
 +			vnode_t *vp = ap->a_vp;
 +			znode_t *zp = VTOZ(vp);
 +			znode_phys_t *zphys = zp->z_phys;
 +
 +			error = vaccess(vp->v_type, zphys->zp_mode,
 +			    zphys->zp_uid, zphys->zp_gid, accmode, ap->a_cred,
 +			    NULL);
 +		}
  	}
  
 -	return (zfs_access(ap->a_vp, ap->a_accmode, 0, ap->a_cred, NULL));
 +	return (error);
  }
  
  static int
 
 Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
 ==============================================================================
 --- stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Sat Nov 14 09:33:51 2009	(r199265)
 +++ stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Sat Nov 14 11:59:59 2009	(r199266)
 @@ -143,16 +143,19 @@ zfs_znode_cache_constructor(void *buf, v
  
  	POINTER_INVALIDATE(&zp->z_zfsvfs);
  	ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
 -	ASSERT(vfsp != NULL);
  
 -	error = getnewvnode("zfs", vfsp, &zfs_vnodeops, &vp);
 -	if (error != 0 && (kmflags & KM_NOSLEEP))
 -		return (-1);
 -	ASSERT(error == 0);
 -	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 -	zp->z_vnode = vp;
 -	vp->v_data = (caddr_t)zp;
 -	VN_LOCK_AREC(vp);
 +	if (vfsp != NULL) {
 +		error = getnewvnode("zfs", vfsp, &zfs_vnodeops, &vp);
 +		if (error != 0 && (kmflags & KM_NOSLEEP))
 +			return (-1);
 +		ASSERT(error == 0);
 +		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 +		zp->z_vnode = vp;
 +		vp->v_data = (caddr_t)zp;
 +		VN_LOCK_AREC(vp);
 +	} else {
 +		zp->z_vnode = NULL;
 +	}
  
  	list_link_init(&zp->z_link_node);
  
 @@ -1435,7 +1438,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, 
  	nvpair_t	*elem;
  	int		error;
  	znode_t		*rootzp = NULL;
 -	vnode_t		*vp;
 +	vnode_t		vnode;
  	vattr_t		vattr;
  	znode_t		*zp;
  
 @@ -1504,13 +1507,13 @@ zfs_create_fs(objset_t *os, cred_t *cr, 
  	vattr.va_gid = crgetgid(cr);
  
  	rootzp = kmem_cache_alloc(znode_cache, KM_SLEEP);
 -	zfs_znode_cache_constructor(rootzp, &zfsvfs, 0);
 +	zfs_znode_cache_constructor(rootzp, NULL, 0);
  	rootzp->z_unlinked = 0;
  	rootzp->z_atime_dirty = 0;
  
 -	vp = ZTOV(rootzp);
 -	vp->v_type = VDIR;
 -	VN_LOCK_ASHARE(vp);
 +	vnode.v_type = VDIR;
 +	vnode.v_data = rootzp;
 +	rootzp->z_vnode = &vnode;
  
  	bzero(&zfsvfs, sizeof (zfsvfs_t));
  
 @@ -1539,16 +1542,10 @@ zfs_create_fs(objset_t *os, cred_t *cr, 
  	ASSERT(error == 0);
  	POINTER_INVALIDATE(&rootzp->z_zfsvfs);
  
 -	VI_LOCK(vp);
 -	ZTOV(rootzp)->v_data = NULL;
 -	ZTOV(rootzp)->v_count = 0;
 -	ZTOV(rootzp)->v_holdcnt = 0;
 -	rootzp->z_vnode = NULL;
 -	VOP_UNLOCK(vp, 0);
 -	vdestroy(vp);
  	dmu_buf_rele(rootzp->z_dbuf, NULL);
  	rootzp->z_dbuf = NULL;
  	mutex_destroy(&zfsvfs.z_znodes_lock);
 +	rootzp->z_vnode = NULL;
  	kmem_cache_free(znode_cache, rootzp);
  }
  
 
 Modified: stable/8/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
 ==============================================================================
 --- stable/8/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h	Sat Nov 14 09:33:51 2009	(r199265)
 +++ stable/8/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h	Sat Nov 14 11:59:59 2009	(r199266)
 @@ -304,7 +304,6 @@ typedef struct xvattr {
   * VOP_ACCESS flags
   */
  #define	V_ACE_MASK	0x1	/* mask represents  NFSv4 ACE permissions */
 -#define	V_APPEND	0x2	/* want to do append only check */
  
  /*
   * Flags for vnode operations.
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: pjd 
State-Changed-When: sob 14 lis 2009 14:28:14 UTC 
State-Changed-Why:  
Fix committed to stable/8. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=139806 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/139806: commit references a PR
Date: Thu,  7 Jan 2010 09:38:11 +0000 (UTC)

 Author: netchild
 Date: Thu Jan  7 09:37:59 2010
 New Revision: 201723
 URL: http://svn.freebsd.org/changeset/base/201723
 
 Log:
   MFC several ZFS related commits:
   
   r197459:
   ---snip---
       Before calling vflush(FORCECLOSE) mark file system as unmounted so the
       following vnops will fail. This is very important, because without this change
       vnode could be reclaimed at any point, even if we increased usecount. The only
       way to ensure that vnode won't be reclaimed was to lock it, which would be very
       hard to do in ZFS without changing a lot of code. With this change simply
       increasing usecount is enough to be sure vnode won't be reclaimed from under
       us. To be precise it can still be reclaimed but we won't be able to see it,
       because every try to enter ZFS through VFS will result in EIO.
   
       The only function that cannot return EIO, because it is needed for vflush() is
       zfs_root(). Introduce ZFS_ENTER_NOERROR() macro that only locks
       z_teardown_lock and never returns EIO.
   ---snip---
   
   r197512:
   ---snip---
       - Don't depend on value returned by gfs_*_inactive(), it doesn't work
         well with forced unmounts when GFS vnodes are referenced.
       - Make other preparations to GFS for forced unmounts.
   
       PR:			kern/139062
       Reported by:	trasz
   ---snip---
   
   r197513:
   ---snip---
       Use traverse() function to find and return mount point's vnode instead of
   cov    ered vnode when snapshot is already mounted.
   ---snip---
   
   r197513:
   ---snip---
       Handle cases where virtual (GFS) vnodes are referenced when doing forced
       unmount. In that case we cannot depend on the proper order of invalidating
       vnodes, so we have to free resources when we have a chance.
   
       PR:			kern/139062
       Reported by:	trasz
   ---snip---
   
   r197683:
   ---snip---
       Return EOPNOTSUPP instead of EINVAL when doing chflags(2) over an old
       format ZFS, as defined in the manual page.
   
       Submitted by:	pjd (response of my original patch but bugs are mine)
   ---snip---
   
   r198703:
   ---snip---
       - zfs_zaccess() can handle VAPPEND too, so map V_APPEND to VAPPEND and call
         zfs_access() instead of vaccess() in this case as well.
       - If VADMIN is specified with another V* flag (unlikely) call both
         zfs_access() and vaccess() after spliting V* flags.
   
       This fixes "dirtying snapshot!" panic.
   
       PR:				kern/139806
       Reported by:		Carl Chave <carl@chave.us>
       In co-operation with:	jh
   ---snip---
   While I'm here: fix two comments regarding the members of vop_access_args
   to comply what is in RELENG_7.
   
   r199156:
   ---snip---
       Avoid passing invalid mountpoint to getnewvnode().
   
       Reported by:	rwatson
       Tested by:	rwatson
   ---snip---
   
   r200724:
   ---snip---
       Apply fix Solaris bug 6462803 zfs snapshot -r failed because
       filesystem was busy. (onnv-gate revision 8989)
   
       Submitted by:	mm
       Approved by:	pjd
   ---snip---
   
   r200726:
   ---snip---
       Apply fix for Solaris bug 6801979: zfs recv can fail with E2BIG
       (onnv revision 8986)
   
       Requested by:	mm
       Submitted by:	pjd
       Obtained from:	OpenSolaris
   ---snip---
   
   r200727 (following is the corrected commit log):
   ---snip---
       Apply fix for Solaris bug 6764159: restore_object() makes a call
       that can block while having a tx open but not yet committed
       (onnv revision 7994)
   
       Submitted by:	mm
       Obtained from:	OpenSolaris
   ---snip---
 
 Modified:
   stable/7/sys/cddl/compat/opensolaris/sys/vnode.h
   stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c
   stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
   stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
   stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
   stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
   stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h
   stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h
   stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
   stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
   stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
   stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
   stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
   stable/7/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
 Directory Properties:
   stable/7/sys/   (props changed)
   stable/7/sys/cddl/contrib/opensolaris/   (props changed)
   stable/7/sys/contrib/dev/acpica/   (props changed)
   stable/7/sys/contrib/pf/   (props changed)
 
 Modified: stable/7/sys/cddl/compat/opensolaris/sys/vnode.h
 ==============================================================================
 --- stable/7/sys/cddl/compat/opensolaris/sys/vnode.h	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/compat/opensolaris/sys/vnode.h	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -57,6 +57,8 @@ typedef	struct vop_vector	vnodeops_t;
  
  #define	v_count	v_usecount
  
 +#define	V_APPEND	VAPPEND
 +
  static __inline int
  vn_is_readonly(vnode_t *vp)
  {
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -595,7 +595,6 @@ found:
  	if (vp->v_flag & V_XATTRDIR)
  		VI_LOCK(fp->gfs_parent);
  	VI_LOCK(vp);
 -	ASSERT(vp->v_count < 2);
  	/*
  	 * Really remove this vnode
  	 */
 @@ -607,12 +606,7 @@ found:
  		 */
  		ge->gfse_vnode = NULL;
  	}
 -	if (vp->v_count == 1) {
 -		vp->v_usecount--;
 -		vdropl(vp);
 -	} else {
 -		VI_UNLOCK(vp);
 -	}
 +	VI_UNLOCK(vp);
  
  	/*
  	 * Free vnode and release parent
 @@ -1084,18 +1078,16 @@ gfs_vop_inactive(ap)
  {
  	vnode_t *vp = ap->a_vp;
  	gfs_file_t *fp = vp->v_data;
 -	void *data;
  
  	if (fp->gfs_type == GFS_DIR)
 -		data = gfs_dir_inactive(vp);
 +		gfs_dir_inactive(vp);
  	else
 -		data = gfs_file_inactive(vp);
 -
 -	if (data != NULL)
 -		kmem_free(data, fp->gfs_size);
 +		gfs_file_inactive(vp);
  
  	VI_LOCK(vp);
  	vp->v_data = NULL;
  	VI_UNLOCK(vp);
 +	kmem_free(fp, fp->gfs_size);
 +
  	return (0);
  }
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -19,12 +19,10 @@
   * CDDL HEADER END
   */
  /*
 - * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   * Use is subject to license terms.
   */
  
 -#pragma ident	"%Z%%M%	%I%	%E% SMI"
 -
  #include <sys/dmu.h>
  #include <sys/dmu_objset.h>
  #include <sys/dmu_tx.h>
 @@ -108,19 +106,51 @@ dmu_object_claim(objset_t *os, uint64_t 
  
  int
  dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot,
 -    int blocksize, dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
 +    int blocksize, dmu_object_type_t bonustype, int bonuslen)
  {
  	dnode_t *dn;
 +	dmu_tx_t *tx;
 +	int nblkptr;
  	int err;
  
 -	if (object == DMU_META_DNODE_OBJECT && !dmu_tx_private_ok(tx))
 +	if (object == DMU_META_DNODE_OBJECT)
  		return (EBADF);
  
  	err = dnode_hold_impl(os->os, object, DNODE_MUST_BE_ALLOCATED,
  	    FTAG, &dn);
  	if (err)
  		return (err);
 +
 +	if (dn->dn_type == ot && dn->dn_datablksz == blocksize &&
 +	    dn->dn_bonustype == bonustype && dn->dn_bonuslen == bonuslen) {
 +		/* nothing is changing, this is a noop */
 +		dnode_rele(dn, FTAG);
 +		return (0);
 +	}
 +
 +	tx = dmu_tx_create(os);
 +	dmu_tx_hold_bonus(tx, object);
 +	err = dmu_tx_assign(tx, TXG_WAIT);
 +	if (err) {
 +		dmu_tx_abort(tx);
 +		dnode_rele(dn, FTAG);
 +		return (err);
 +	}
 +
 +	nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
 +
 +	/*
 +	 * If we are losing blkptrs or changing the block size this must
 +	 * be a new file instance.   We must clear out the previous file
 +	 * contents before we can change this type of metadata in the dnode.
 +	 */
 +	if (dn->dn_nblkptr > nblkptr || dn->dn_datablksz != blocksize)
 +		dmu_free_long_range(os, object, 0, DMU_OBJECT_END);
 +
  	dnode_reallocate(dn, ot, blocksize, bonustype, bonuslen, tx);
 +
 +	dmu_tx_commit(tx);
 +
  	dnode_rele(dn, FTAG);
  
  	return (0);
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -828,11 +828,7 @@ restore_object(struct restorearg *ra, ob
  {
  	int err;
  	dmu_tx_t *tx;
 -
 -	err = dmu_object_info(os, drro->drr_object, NULL);
 -
 -	if (err != 0 && err != ENOENT)
 -		return (EINVAL);
 +	void *data = NULL;
  
  	if (drro->drr_type == DMU_OT_NONE ||
  	    drro->drr_type >= DMU_OT_NUMTYPES ||
 @@ -846,12 +842,15 @@ restore_object(struct restorearg *ra, ob
  		return (EINVAL);
  	}
  
 -	tx = dmu_tx_create(os);
 +	err = dmu_object_info(os, drro->drr_object, NULL);
 +
 +	if (err != 0 && err != ENOENT)
 +		return (EINVAL);
  
  	if (err == ENOENT) {
  		/* currently free, want to be allocated */
 +		tx = dmu_tx_create(os);
  		dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
 -		dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, 1);
  		err = dmu_tx_assign(tx, TXG_WAIT);
  		if (err) {
  			dmu_tx_abort(tx);
 @@ -860,45 +859,41 @@ restore_object(struct restorearg *ra, ob
  		err = dmu_object_claim(os, drro->drr_object,
  		    drro->drr_type, drro->drr_blksz,
  		    drro->drr_bonustype, drro->drr_bonuslen, tx);
 +		dmu_tx_commit(tx);
  	} else {
  		/* currently allocated, want to be allocated */
 -		dmu_tx_hold_bonus(tx, drro->drr_object);
 -		/*
 -		 * We may change blocksize and delete old content,
 -		 * so need to hold_write and hold_free.
 -		 */
 -		dmu_tx_hold_write(tx, drro->drr_object, 0, 1);
 -		dmu_tx_hold_free(tx, drro->drr_object, 0, DMU_OBJECT_END);
 -		err = dmu_tx_assign(tx, TXG_WAIT);
 -		if (err) {
 -			dmu_tx_abort(tx);
 -			return (err);
 -		}
  
  		err = dmu_object_reclaim(os, drro->drr_object,
  		    drro->drr_type, drro->drr_blksz,
 -		    drro->drr_bonustype, drro->drr_bonuslen, tx);
 +		    drro->drr_bonustype, drro->drr_bonuslen);
  	}
 -	if (err) {
 -		dmu_tx_commit(tx);
 +	if (err)
  		return (EINVAL);
 +
 +	if (drro->drr_bonuslen) {
 +		data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8));
 +		if (ra->err)
 +			return (ra->err);
 +	}
 +
 +	tx = dmu_tx_create(os);
 +	dmu_tx_hold_bonus(tx, drro->drr_object);
 +	err = dmu_tx_assign(tx, TXG_WAIT);
 +	if (err) {
 +		dmu_tx_abort(tx);
 +		return (err);
  	}
  
  	dmu_object_set_checksum(os, drro->drr_object, drro->drr_checksum, tx);
  	dmu_object_set_compress(os, drro->drr_object, drro->drr_compress, tx);
  
 -	if (drro->drr_bonuslen) {
 +	if (data != NULL) {
  		dmu_buf_t *db;
 -		void *data;
 +
  		VERIFY(0 == dmu_bonus_hold(os, drro->drr_object, FTAG, &db));
  		dmu_buf_will_dirty(db, tx);
  
  		ASSERT3U(db->db_size, >=, drro->drr_bonuslen);
 -		data = restore_read(ra, P2ROUNDUP(drro->drr_bonuslen, 8));
 -		if (data == NULL) {
 -			dmu_tx_commit(tx);
 -			return (ra->err);
 -		}
  		bcopy(data, db->db_data, drro->drr_bonuslen);
  		if (ra->byteswap) {
  			dmu_ot[drro->drr_bonustype].ot_byteswap(db->db_data,
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -415,8 +415,7 @@ void
  dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
      dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
  {
 -	int i, nblkptr;
 -	dmu_buf_impl_t *db = NULL;
 +	int nblkptr;
  
  	ASSERT3U(blocksize, >=, SPA_MINBLOCKSIZE);
  	ASSERT3U(blocksize, <=, SPA_MAXBLOCKSIZE);
 @@ -428,42 +427,25 @@ dnode_reallocate(dnode_t *dn, dmu_object
  	ASSERT3U(bonustype, <, DMU_OT_NUMTYPES);
  	ASSERT3U(bonuslen, <=, DN_MAX_BONUSLEN);
  
 -	for (i = 0; i < TXG_SIZE; i++)
 -		ASSERT(!list_link_active(&dn->dn_dirty_link[i]));
 -
  	/* clean up any unreferenced dbufs */
  	dnode_evict_dbufs(dn);
 -	ASSERT3P(list_head(&dn->dn_dbufs), ==, NULL);
 -
 -	/*
 -	 * XXX I should really have a generation number to tell if we
 -	 * need to do this...
 -	 */
 -	if (blocksize != dn->dn_datablksz ||
 -	    dn->dn_bonustype != bonustype || dn->dn_bonuslen != bonuslen) {
 -		/* free all old data */
 -		dnode_free_range(dn, 0, -1ULL, tx);
 -	}
 -
 -	nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
  
 -	/* change blocksize */
  	rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
 -	if (blocksize != dn->dn_datablksz &&
 -	    (!BP_IS_HOLE(&dn->dn_phys->dn_blkptr[0]) ||
 -	    list_head(&dn->dn_dbufs) != NULL)) {
 -		db = dbuf_hold(dn, 0, FTAG);
 -		dbuf_new_size(db, blocksize, tx);
 -	}
 -	dnode_setdblksz(dn, blocksize);
  	dnode_setdirty(dn, tx);
 -	dn->dn_next_bonuslen[tx->tx_txg&TXG_MASK] = bonuslen;
 -	dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = blocksize;
 +	if (dn->dn_datablksz != blocksize) {
 +		/* change blocksize */
 +		ASSERT(dn->dn_maxblkid == 0 &&
 +		    (BP_IS_HOLE(&dn->dn_phys->dn_blkptr[0]) ||
 +		    dnode_block_freed(dn, 0)));
 +		dnode_setdblksz(dn, blocksize);
 +		dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = blocksize;
 +	}
 +	if (dn->dn_bonuslen != bonuslen)
 +		dn->dn_next_bonuslen[tx->tx_txg&TXG_MASK] = bonuslen;
 +	nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
  	if (dn->dn_nblkptr != nblkptr)
  		dn->dn_next_nblkptr[tx->tx_txg&TXG_MASK] = nblkptr;
  	rw_exit(&dn->dn_struct_rwlock);
 -	if (db)
 -		dbuf_rele(db, FTAG);
  
  	/* change type */
  	dn->dn_type = ot;
 @@ -1187,11 +1169,6 @@ dnode_block_freed(dnode_t *dn, uint64_t 
  	if (dn->dn_free_txg)
  		return (TRUE);
  
 -	/*
 -	 * If dn_datablkshift is not set, then there's only a single
 -	 * block, in which case there will never be a free range so it
 -	 * won't matter.
 -	 */
  	range_tofind.fr_blkid = blkid;
  	mutex_enter(&dn->dn_mtx);
  	for (i = 0; i < TXG_SIZE; i++) {
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -19,7 +19,7 @@
   * CDDL HEADER END
   */
  /*
 - * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   * Use is subject to license terms.
   */
  
 @@ -237,7 +237,7 @@ uint64_t dmu_object_alloc(objset_t *os, 
  int dmu_object_claim(objset_t *os, uint64_t object, dmu_object_type_t ot,
      int blocksize, dmu_object_type_t bonus_type, int bonus_len, dmu_tx_t *tx);
  int dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot,
 -    int blocksize, dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx);
 +    int blocksize, dmu_object_type_t bonustype, int bonuslen);
  
  /*
   * Free an object from this objset.
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -255,6 +255,7 @@ VTOZ(vnode_t *vp)
  
  /*
   * ZFS_ENTER() is called on entry to each ZFS vnode and vfs operation.
 + * ZFS_ENTER_NOERROR() is called when we can't return EIO.
   * ZFS_EXIT() must be called before exitting the vop.
   * ZFS_VERIFY_ZP() verifies the znode is valid.
   */
 @@ -267,6 +268,9 @@ VTOZ(vnode_t *vp)
  		} \
  	}
  
 +#define	ZFS_ENTER_NOERROR(zfsvfs) \
 +	rrw_enter(&(zfsvfs)->z_teardown_lock, RW_READER, FTAG)
 +
  #define	ZFS_EXIT(zfsvfs) rrw_exit(&(zfsvfs)->z_teardown_lock, FTAG)
  
  #define	ZFS_VERIFY_ZP(zp) \
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -19,7 +19,7 @@
   * CDDL HEADER END
   */
  /*
 - * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   * Use is subject to license terms.
   */
  
 @@ -56,10 +56,16 @@ typedef struct zil_header {
  	uint64_t zh_replay_seq;	/* highest replayed sequence number */
  	blkptr_t zh_log;	/* log chain */
  	uint64_t zh_claim_seq;	/* highest claimed sequence number */
 -	uint64_t zh_pad[5];
 +	uint64_t zh_flags;	/* header flags */
 +	uint64_t zh_pad[4];
  } zil_header_t;
  
  /*
 + * zh_flags bit settings
 + */
 +#define	ZIL_REPLAY_NEEDED 0x1	/* replay needed - internal only */
 +
 +/*
   * Log block trailer - structure at the end of the header and each log block
   *
   * The zit_bt contains a zbt_cksum which for the intent log is
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -252,7 +252,7 @@ static int
  zfsctl_common_access(ap)
  	struct vop_access_args /* {
  		struct vnode *a_vp;
 -		int  a_accmode;
 +		int  a_mode;
  		struct ucred *a_cred;
  		struct thread *a_td;
  	} */ *ap;
 @@ -817,7 +817,11 @@ zfsctl_snapdir_lookup(ap)
  	if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) != NULL) {
  		*vpp = sep->se_root;
  		VN_HOLD(*vpp);
 -		if ((*vpp)->v_mountedhere == NULL) {
 +		err = traverse(vpp, LK_EXCLUSIVE | LK_RETRY);
 +		if (err) {
 +			VN_RELE(*vpp);
 +			*vpp = NULL;
 +		} else if (*vpp == sep->se_root) {
  			/*
  			 * The snapshot was unmounted behind our backs,
  			 * try to remount it.
 @@ -831,10 +835,9 @@ zfsctl_snapdir_lookup(ap)
  			 */
  			(*vpp)->v_flag &= ~VROOT;
  		}
 -		vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curthread);
  		mutex_exit(&sdp->sd_lock);
  		ZFS_EXIT(zfsvfs);
 -		return (0);
 +		return (err);
  	}
  
  	/*
 @@ -1001,15 +1004,24 @@ zfsctl_snapdir_inactive(ap)
  {
  	vnode_t *vp = ap->a_vp;
  	zfsctl_snapdir_t *sdp = vp->v_data;
 -	void *private;
 +	zfs_snapentry_t *sep;
  
 -	private = gfs_dir_inactive(vp);
 -	if (private != NULL) {
 -		ASSERT(avl_numnodes(&sdp->sd_snaps) == 0);
 -		mutex_destroy(&sdp->sd_lock);
 -		avl_destroy(&sdp->sd_snaps);
 -		kmem_free(private, sizeof (zfsctl_snapdir_t));
 +	/*
 +	 * On forced unmount we have to free snapshots from here.
 +	 */
 +	mutex_enter(&sdp->sd_lock);
 +	while ((sep = avl_first(&sdp->sd_snaps)) != NULL) {
 +		avl_remove(&sdp->sd_snaps, sep);
 +		kmem_free(sep->se_name, strlen(sep->se_name) + 1);
 +		kmem_free(sep, sizeof (zfs_snapentry_t));
  	}
 +	mutex_exit(&sdp->sd_lock);
 +	gfs_dir_inactive(vp);
 +	ASSERT(avl_numnodes(&sdp->sd_snaps) == 0);
 +	mutex_destroy(&sdp->sd_lock);
 +	avl_destroy(&sdp->sd_snaps);
 +	kmem_free(sdp, sizeof (zfsctl_snapdir_t));
 +
  	return (0);
  }
  
 @@ -1066,6 +1078,9 @@ zfsctl_snapshot_inactive(ap)
  	int locked;
  	vnode_t *dvp;
  
 +	if (vp->v_count > 0)
 +		goto end;
 +
  	VERIFY(gfs_dir_lookup(vp, "..", &dvp, cr, 0, NULL, NULL) == 0);
  	sdp = dvp->v_data;
  	VOP_UNLOCK(dvp, 0, curthread);
 @@ -1073,11 +1088,6 @@ zfsctl_snapshot_inactive(ap)
  	if (!(locked = MUTEX_HELD(&sdp->sd_lock)))
  		mutex_enter(&sdp->sd_lock);
  
 -	if (vp->v_count > 1) {
 -		if (!locked)
 -			mutex_exit(&sdp->sd_lock);
 -		return (0);
 -	}
  	ASSERT(!vn_ismntpt(vp));
  
  	sep = avl_first(&sdp->sd_snaps);
 @@ -1097,6 +1107,7 @@ zfsctl_snapshot_inactive(ap)
  	if (!locked)
  		mutex_exit(&sdp->sd_lock);
  	VN_RELE(dvp);
 +end:
  	VFS_RELE(vp->v_vfsp);
  
  	/*
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -872,7 +872,7 @@ zfs_root(vfs_t *vfsp, int flags, vnode_t
  	znode_t *rootzp;
  	int error;
  
 -	ZFS_ENTER(zfsvfs);
 +	ZFS_ENTER_NOERROR(zfsvfs);
  
  	error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp);
  	if (error == 0) {
 @@ -1045,6 +1045,17 @@ zfs_umount(vfs_t *vfsp, int fflag, kthre
  		ASSERT(zfsvfs->z_ctldir == NULL);
  	}
  
 +	if (fflag & MS_FORCE) {
 +		/*
 +		 * Mark file system as unmounted before calling
 +		 * vflush(FORCECLOSE). This way we ensure no future vnops
 +		 * will be called and risk operating on DOOMED vnodes.
 +		 */
 +		rrw_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG);
 +		zfsvfs->z_unmounted = B_TRUE;
 +		rrw_exit(&zfsvfs->z_teardown_lock, FTAG);
 +	}
 +
  	/*
  	 * Flush all the files.
  	 */
 @@ -1111,10 +1122,7 @@ zfs_umount(vfs_t *vfsp, int fflag, kthre
  	if (zfsvfs->z_issnap) {
  		vnode_t *svp = vfsp->mnt_vnodecovered;
  
 -		/*
 -		 * We don't need an extra vn_rele if this is a manual snapshot mount
 -		 */
 -		if (svp->v_count == 2)
 +		if (svp->v_count >= 2)
  			VN_RELE(svp);
  	}
  	zfs_freevfs(vfsp);
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -3964,26 +3964,38 @@ static int
  zfs_freebsd_access(ap)
  	struct vop_access_args /* {
  		struct vnode *a_vp;
 -		accmode_t a_accmode;
 +		accmode_t a_mode;
  		struct ucred *a_cred;
  		struct thread *a_td;
  	} */ *ap;
  {
 +	accmode_t accmode;
 +	int error = 0;
  
  	/*
 -	 * ZFS itself only knowns about VREAD, VWRITE and VEXEC, the rest
 -	 * we have to handle by calling vaccess().
 +	 * ZFS itself only knowns about VREAD, VWRITE, VEXEC and VAPPEND,
  	 */
 -	if ((ap->a_mode & ~(VREAD|VWRITE|VEXEC)) != 0) {
 -		vnode_t *vp = ap->a_vp;
 -		znode_t *zp = VTOZ(vp);
 -		znode_phys_t *zphys = zp->z_phys;
 +	accmode = ap->a_mode & (VREAD|VWRITE|VEXEC|VAPPEND);
 +	if (accmode != 0)
 +		error = zfs_access(ap->a_vp, accmode, 0, ap->a_cred, NULL);
  
 -		return (vaccess(vp->v_type, zphys->zp_mode, zphys->zp_uid,
 -		    zphys->zp_gid, ap->a_mode, ap->a_cred, NULL));
 +	/*
 +	 * VADMIN has to be handled by vaccess().
 +	 */
 +	if (error == 0) {
 +		accmode = ap->a_mode & ~(VREAD|VWRITE|VEXEC|VAPPEND);
 +		if (accmode != 0) {
 +			vnode_t *vp = ap->a_vp;
 +			znode_t *zp = VTOZ(vp);
 +			znode_phys_t *zphys = zp->z_phys;
 +
 +			error = vaccess(vp->v_type, zphys->zp_mode,
 +			    zphys->zp_uid, zphys->zp_gid, accmode, ap->a_cred,
 +			    NULL);
 +		}
  	}
  
 -	return (zfs_access(ap->a_vp, ap->a_mode, 0, ap->a_cred, NULL));
 +	return (error);
  }
  
  static int
 @@ -4176,8 +4188,12 @@ zfs_freebsd_setattr(ap)
  	zflags = VTOZ(vp)->z_phys->zp_flags;
  
  	if (vap->va_flags != VNOVAL) {
 +		zfsvfs_t *zfsvfs = VTOZ(vp)->z_zfsvfs;
  		int error;
  
 +		if (zfsvfs->z_use_fuids == B_FALSE)
 +			return (EOPNOTSUPP);
 +
  		fflags = vap->va_flags;
  		if ((fflags & ~(SF_IMMUTABLE|SF_APPEND|SF_NOUNLINK|UF_NODUMP)) != 0)
  			return (EOPNOTSUPP);
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -143,16 +143,19 @@ zfs_znode_cache_constructor(void *buf, v
  
  	POINTER_INVALIDATE(&zp->z_zfsvfs);
  	ASSERT(!POINTER_IS_VALID(zp->z_zfsvfs));
 -	ASSERT(vfsp != NULL);
  
 -	error = getnewvnode("zfs", vfsp, &zfs_vnodeops, &vp);
 -	if (error != 0 && (kmflags & KM_NOSLEEP))
 -		return (-1);
 -	ASSERT(error == 0);
 -	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
 -	zp->z_vnode = vp;
 -	vp->v_data = (caddr_t)zp;
 -	VN_LOCK_AREC(vp);
 +	if (vfsp != NULL) {
 +		error = getnewvnode("zfs", vfsp, &zfs_vnodeops, &vp);
 +		if (error != 0 && (kmflags & KM_NOSLEEP))
 +			return (-1);
 +		ASSERT(error == 0);
 +		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
 +		zp->z_vnode = vp;
 +		vp->v_data = (caddr_t)zp;
 +		VN_LOCK_AREC(vp);
 +	} else {
 +		zp->z_vnode = NULL;
 +	}
  
  	list_link_init(&zp->z_link_node);
  
 @@ -1441,7 +1444,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, 
  	nvpair_t	*elem;
  	int		error;
  	znode_t		*rootzp = NULL;
 -	vnode_t		*vp;
 +	vnode_t		vnode;
  	vattr_t		vattr;
  	znode_t		*zp;
  
 @@ -1510,13 +1513,13 @@ zfs_create_fs(objset_t *os, cred_t *cr, 
  	vattr.va_gid = crgetgid(cr);
  
  	rootzp = kmem_cache_alloc(znode_cache, KM_SLEEP);
 -	zfs_znode_cache_constructor(rootzp, &zfsvfs, 0);
 +	zfs_znode_cache_constructor(rootzp, NULL, 0);
  	rootzp->z_unlinked = 0;
  	rootzp->z_atime_dirty = 0;
  
 -	vp = ZTOV(rootzp);
 -	vp->v_type = VDIR;
 -	VN_LOCK_ASHARE(vp);
 +	vnode.v_type = VDIR;
 +	vnode.v_data = rootzp;
 +	rootzp->z_vnode = &vnode;
  
  	bzero(&zfsvfs, sizeof (zfsvfs_t));
  
 @@ -1545,16 +1548,10 @@ zfs_create_fs(objset_t *os, cred_t *cr, 
  	ASSERT(error == 0);
  	POINTER_INVALIDATE(&rootzp->z_zfsvfs);
  
 -	VI_LOCK(vp);
 -	ZTOV(rootzp)->v_data = NULL;
 -	ZTOV(rootzp)->v_count = 0;
 -	ZTOV(rootzp)->v_holdcnt = 0;
 -	rootzp->z_vnode = NULL;
 -	VOP_UNLOCK(vp, 0, curthread);
 -	vdestroy(vp);
  	dmu_buf_rele(rootzp->z_dbuf, NULL);
  	rootzp->z_dbuf = NULL;
  	mutex_destroy(&zfsvfs.z_znodes_lock);
 +	rootzp->z_vnode = NULL;
  	kmem_cache_free(znode_cache, rootzp);
  }
  
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -506,6 +506,25 @@ zil_rollback_destroy(zilog_t *zilog, dmu
  	    tx, zh->zh_claim_txg);
  }
  
 +/*
 + * return true if the initial log block is not valid
 + */
 +static boolean_t
 +zil_empty(zilog_t *zilog)
 +{
 +	const zil_header_t *zh = zilog->zl_header;
 +	arc_buf_t *abuf = NULL;
 +
 +	if (BP_IS_HOLE(&zh->zh_log))
 +		return (B_TRUE);
 +
 +	if (zil_read_log_block(zilog, &zh->zh_log, &abuf) != 0)
 +		return (B_TRUE);
 +
 +	VERIFY(arc_buf_remove_ref(abuf, &abuf) == 1);
 +	return (B_FALSE);
 +}
 +
  int
  zil_claim(char *osname, void *txarg)
  {
 @@ -526,6 +545,21 @@ zil_claim(char *osname, void *txarg)
  	zh = zil_header_in_syncing_context(zilog);
  
  	/*
 +	 * Record here whether the zil has any records to replay.
 +	 * If the header block pointer is null or the block points
 +	 * to the stubby then we know there are no valid log records.
 +	 * We use the header to store this state as the the zilog gets
 +	 * freed later in dmu_objset_close().
 +	 * The flags (and the rest of the header fields) are cleared in
 +	 * zil_sync() as a result of a zil_destroy(), after replaying the log.
 +	 *
 +	 * Note, the intent log can be empty but still need the
 +	 * stubby to be claimed.
 +	 */
 +	if (!zil_empty(zilog))
 +		zh->zh_flags |= ZIL_REPLAY_NEEDED;
 +
 +	/*
  	 * Claim all log blocks if we haven't already done so, and remember
  	 * the highest claimed sequence number.  This ensures that if we can
  	 * read only part of the log now (e.g. due to a missing device),
 @@ -1349,25 +1383,6 @@ zil_free(zilog_t *zilog)
  }
  
  /*
 - * return true if the initial log block is not valid
 - */
 -static boolean_t
 -zil_empty(zilog_t *zilog)
 -{
 -	const zil_header_t *zh = zilog->zl_header;
 -	arc_buf_t *abuf = NULL;
 -
 -	if (BP_IS_HOLE(&zh->zh_log))
 -		return (B_TRUE);
 -
 -	if (zil_read_log_block(zilog, &zh->zh_log, &abuf) != 0)
 -		return (B_TRUE);
 -
 -	VERIFY(arc_buf_remove_ref(abuf, &abuf) == 1);
 -	return (B_FALSE);
 -}
 -
 -/*
   * Open an intent log.
   */
  zilog_t *
 @@ -1422,7 +1437,7 @@ zil_suspend(zilog_t *zilog)
  	const zil_header_t *zh = zilog->zl_header;
  
  	mutex_enter(&zilog->zl_lock);
 -	if (zh->zh_claim_txg != 0) {		/* unplayed log */
 +	if (zh->zh_flags & ZIL_REPLAY_NEEDED) {		/* unplayed log */
  		mutex_exit(&zilog->zl_lock);
  		return (EBUSY);
  	}
 @@ -1649,7 +1664,7 @@ zil_replay(objset_t *os, void *arg, uint
  	const zil_header_t *zh = zilog->zl_header;
  	zil_replay_arg_t zr;
  
 -	if (zil_empty(zilog)) {
 +	if ((zh->zh_flags & ZIL_REPLAY_NEEDED) == 0) {
  		zil_destroy(zilog, B_TRUE);
  		return;
  	}
 
 Modified: stable/7/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
 ==============================================================================
 --- stable/7/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h	Thu Jan  7 09:28:17 2010	(r201722)
 +++ stable/7/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h	Thu Jan  7 09:37:59 2010	(r201723)
 @@ -304,7 +304,6 @@ typedef struct xvattr {
   * VOP_ACCESS flags
   */
  #define	V_ACE_MASK	0x1	/* mask represents  NFSv4 ACE permissions */
 -#define	V_APPEND	0x2	/* want to do append only check */
  
  /*
   * Flags for vnode operations.
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
