Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 16 Aug 2000 12:40:03 -0700 (PDT)
From:      Tor.Egge@fast.no
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/20632: stacking mount_null causes an error: mount_null: Resource deadlock avoided 
Message-ID:  <200008161940.MAA01501@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/20632; it has been noted by GNATS.

From: Tor.Egge@fast.no
To: sheldonh@uunet.co.za
Cc: akr@m17n.org, semen@iclub.nsu.ru
Subject: Re: kern/20632: stacking mount_null causes an error: mount_null: Resource deadlock avoided 
Date: Wed, 16 Aug 2000 20:52:29 +0200

 >  > Unfortunately the patch doesn't fix the problem.
 >  
 >  I've asked Ustimenko Semen <semen@iclub.nsu.ru>, the author of the
 >  patch, to take a look at your PR.
 
 Here is yet another nullfs patch for -current.  It lacks some
 of the features in Ustimenko's patch (e.g. support for nfs exporting
 nfs mounted file systems), but it avoids the aliasing problem.
 
 
 Index: sbin/mount_null/mount_null.c
 ===================================================================
 RCS file: /home/ncvs/src/sbin/mount_null/mount_null.c,v
 retrieving revision 1.14
 diff -u -r1.14 mount_null.c
 --- sbin/mount_null/mount_null.c	2000/07/28 11:54:08	1.14
 +++ sbin/mount_null/mount_null.c	2000/08/06 19:16:28
 @@ -101,9 +101,11 @@
  	(void)checkpath(argv[0], target);
  	(void)checkpath(argv[1], source);
  
 +#if 0
  	if (subdir(target, source) || subdir(source, target))
  		errx(EX_USAGE, "%s (%s) and %s are not distinct paths",
  		    argv[0], target, argv[1]);
 +#endif
  
  	args.target = target;
  
 Index: sys/kern/vfs_subr.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/kern/vfs_subr.c,v
 retrieving revision 1.267
 diff -u -r1.267 vfs_subr.c
 --- sys/kern/vfs_subr.c	2000/07/24 05:28:29	1.267
 +++ sys/kern/vfs_subr.c	2000/08/06 19:16:46
 @@ -711,7 +711,7 @@
  	 */
  	simple_lock(&vp->v_interlock);
  	object = vp->v_object;
 -	if (object != NULL) {
 +	if (object != NULL && (void *) vp == object->handle) {
  		vm_object_page_remove(object, 0, 0,
  			(flags & V_SAVE) ? TRUE : FALSE);
  	}
 @@ -841,6 +841,8 @@
  	int s;
  
  	KASSERT(bp->b_vp == NULL, ("bgetvp: not free"));
 +	if (vp->v_tag == VT_NULL)
 +		panic("bgetvp: null node");
  
  	vhold(vp);
  	bp->b_vp = vp;
 @@ -1190,6 +1192,8 @@
  			}
  			vn_syncer_add_to_worklist(newvp, delay);
  		}
 +		if (newvp->v_tag == VT_NULL)
 +			panic("reassignbuf: null node dirty list");
  		bp->b_xflags |= BX_VNDIRTY;
  		tbp = TAILQ_FIRST(listheadp);
  		if (tbp == NULL ||
 @@ -1243,6 +1247,8 @@
  			TAILQ_INSERT_AFTER(listheadp, tbp, bp, b_vnbufs);
  		}
  	} else {
 +		if (newvp->v_tag == VT_NULL)
 +			panic("reassignbuf: null node clean list");
  		bp->b_xflags |= BX_VNCLEAN;
  		TAILQ_INSERT_TAIL(&newvp->v_cleanblkhd, bp, b_vnbufs);
  		if ((newvp->v_flag & VONWORKLST) &&
 @@ -1683,7 +1689,7 @@
  			vinvalbuf(vp, 0, NOCRED, p, 0, 0);
  	}
  
 -	if ((obj = vp->v_object) != NULL) {
 +	if ((obj = vp->v_object) != NULL && (void *) vp == obj->handle) {
  		if (obj->ref_count == 0) {
  			/*
  			 * vclean() may be called twice. The first time
 @@ -2529,7 +2535,8 @@
  
  		simple_lock(&vp->v_interlock);
  		if (vp->v_object &&
 -		   (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
 +		    (void *) vp == vp->v_object->handle &&
 +		    (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
  			if (!vget(vp,
  				LK_INTERLOCK | LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ, curproc)) {
  				if (vp->v_object) {
 @@ -2613,6 +2620,21 @@
  
  	s = splbio();
  	simple_lock(&vnode_free_list_slock);
 +	if ((vp->v_flag & VFREE) != 0)
 +		panic("vfree called on doomed node");
 +	if ((vp->v_flag & VFREE) != 0)
 +		panic("vfree called on free node");
 +	if (vp->v_holdcnt != 0)
 +		panic("vfree called with holdcnt=%d (>0)", vp->v_holdcnt);
 +	if (vp->v_usecount != 0)
 +		panic("vfree called with usecnt=%d (>0)", vp->v_usecount);
 +	if (vp->v_object != NULL &&
 +	    vp->v_object->handle == (void *) vp &&
 +	    (vp->v_object->resident_page_count != 0 ||
 +	     vp->v_object->ref_count != 0))
 +	    panic("vfree called with object RPC: %d, RC: %d",
 +		  vp->v_object->resident_page_count,
 +		  vp->v_object->ref_count);
  	KASSERT((vp->v_flag & VFREE) == 0, ("vnode already free"));
  	if (vp->v_flag & VAGE) {
  		TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
 Index: sys/miscfs/nullfs/null.h
 ===================================================================
 RCS file: /home/ncvs/src/sys/miscfs/nullfs/null.h,v
 retrieving revision 1.13
 diff -u -r1.13 null.h
 --- sys/miscfs/nullfs/null.h	2000/05/26 02:04:58	1.13
 +++ sys/miscfs/nullfs/null.h	2000/08/06 19:16:47
 @@ -55,7 +55,15 @@
  	LIST_ENTRY(null_node)	null_hash;	/* Hash list */
  	struct vnode	        *null_lowervp;	/* VREFed once */
  	struct vnode		*null_vnode;	/* Back pointer */
 +	int flags;				/* flags (see below) */
 +	pid_t lockholder;			/* owner of exclusive lock */
  };
 +
 +/* Null node flags */
 +
 +#define NN_LOCK		0x01
 +#define NN_WANT		0x02
 +#define NN_FSYNC_SKIPPED 0x04
  
  extern int nullfs_init __P((struct vfsconf *vfsp));
  extern int null_node_create __P((struct mount *mp, struct vnode *target, struct vnode **vpp));
 Index: sys/miscfs/nullfs/null_subr.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/miscfs/nullfs/null_subr.c,v
 retrieving revision 1.23
 diff -u -r1.23 null_subr.c
 --- sys/miscfs/nullfs/null_subr.c	2000/05/26 02:04:59	1.23
 +++ sys/miscfs/nullfs/null_subr.c	2000/08/06 19:16:47
 @@ -45,6 +45,8 @@
  #include <sys/mount.h>
  #include <sys/malloc.h>
  #include <miscfs/nullfs/null.h>
 +#include <vm/vm.h>
 +#include <vm/vm_object.h>
  
  #define LOG2_SIZEVNODE 7		/* log2(sizeof struct vnode) */
  #define	NNULLNODECACHE 16
 @@ -94,6 +96,7 @@
  	struct null_node_hashhead *hd;
  	struct null_node *a;
  	struct vnode *vp;
 +	int retry;
  
  	/*
  	 * Find hash base, and then search the (two-way) linked
 @@ -102,6 +105,7 @@
  	 * reference count (but NOT the lower vnode's VREF counter).
  	 */
  	hd = NULL_NHASH(lowervp);
 +	retry = 0;
  loop:
  	for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
  		if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
 @@ -112,6 +116,9 @@
  			 * the lower node.
  			 */
  			if (vget(vp, 0, p)) {
 +				retry++;
 +				if (retry < 2)
 +					goto loop;
  				printf ("null_node_find: vget failed.\n");
  				goto loop;
  			};
 @@ -138,6 +145,7 @@
  	struct null_node *xp;
  	struct vnode *othervp, *vp;
  	int error;
 +	int waslocked;
  
  	/*
  	 * Do the MALLOC before the getnewvnode since doing so afterward
 @@ -157,6 +165,8 @@
  	xp->null_vnode = vp;
  	vp->v_data = xp;
  	xp->null_lowervp = lowervp;
 +	xp->flags = 0;
 +	xp->lockholder = 0;
  	/*
  	 * Before we insert our new node onto the hash chains,
  	 * check to see if someone else has beaten us to it.
 @@ -167,12 +177,41 @@
  		FREE(xp, M_TEMP);
  		vp->v_type = VBAD;	/* node is discarded */
  		vp->v_usecount = 0;	/* XXX */
 +		if (VSHOULDFREE(vp))
 +			vfree(vp);
  		*vpp = othervp;
  		return 0;
  	};
  	VREF(lowervp);   /* Extra VREF will be vrele'd in null_node_create */
  	hd = NULL_NHASH(lowervp);
  	LIST_INSERT_HEAD(hd, xp, null_hash);
 +	/*
 +	 * Create the lower VM object, if needed
 +	 */
 +	if ((lowervp->v_type == VREG) &&
 +	    ((lowervp->v_object == NULL) ||
 +	     (lowervp->v_object->flags & OBJ_DEAD))) {
 +		waslocked = VOP_ISLOCKED(lowervp, NULL); /* XXX: Wrong */
 +		if (!waslocked) {
 +			simple_lock(&lowervp->v_interlock);
 +			vn_lock(lowervp,
 +				LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY,
 +				curproc);
 +		}
 +		vfs_object_create(lowervp, curproc, curproc->p_ucred);
 +		if (!waslocked) {
 +			simple_lock(&lowervp->v_interlock);
 +			VOP_UNLOCK(lowervp, LK_INTERLOCK, curproc);
 +		}
 +
 +	}
 +	vp->v_object = lowervp->v_object;	/* XXX: share object */
 +	if (vp->v_object != NULL) {
 +		if ((lowervp->v_flag & VOBJBUF) != 0)
 +			vp->v_flag |= VOBJBUF;
 +		if ((lowervp->v_flag & VTEXT) != 0)
 +			vp->v_flag |= VTEXT;
 +	}
  	return 0;
  }
  
 Index: sys/miscfs/nullfs/null_vfsops.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/miscfs/nullfs/null_vfsops.c,v
 retrieving revision 1.37
 diff -u -r1.37 null_vfsops.c
 --- sys/miscfs/nullfs/null_vfsops.c	2000/07/28 11:54:09	1.37
 +++ sys/miscfs/nullfs/null_vfsops.c	2000/08/06 19:16:47
 @@ -93,7 +93,6 @@
  	struct vnode *nullm_rootvp;
  	struct null_mount *xmp;
  	u_int size;
 -	int isvnunlocked = 0;
  
  #ifdef DEBUG
  	printf("nullfs_mount(mp = %p)\n", (void *)mp);
 @@ -115,46 +114,23 @@
  		return (error);
  
  	/*
 -	 * Unlock lower node to avoid deadlock.
 -	 * (XXX) VOP_ISLOCKED is needed?
 -	 */
 -	if ((mp->mnt_vnodecovered->v_op == null_vnodeop_p) &&
 -		VOP_ISLOCKED(mp->mnt_vnodecovered, NULL)) {
 -		VOP_UNLOCK(mp->mnt_vnodecovered, 0, p);
 -		isvnunlocked = 1;
 -	}
 -	/*
  	 * Find lower node
  	 */
 -	NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
 -		UIO_USERSPACE, args.target, p);
 +	NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF,
 +	       UIO_USERSPACE, args.target, p);
  	error = namei(ndp);
 -	/*
 -	 * Re-lock vnode.
 -	 */
 -	if (isvnunlocked && !VOP_ISLOCKED(mp->mnt_vnodecovered, NULL))
 -		vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY, p);
 -
  	if (error)
  		return (error);
  	NDFREE(ndp, NDF_ONLY_PNBUF);
  
 -	/*
 -	 * Sanity check on lower vnode
 -	 */
  	lowerrootvp = ndp->ni_vp;
  
 -	vrele(ndp->ni_dvp);
 -	ndp->ni_dvp = NULLVP;
 -
  	/*
 -	 * Check multi null mount to avoid `lock against myself' panic.
 +	 * Sanity check on lower vnode
  	 */
 -	if (lowerrootvp == VTONULL(mp->mnt_vnodecovered)->null_lowervp) {
 -#ifdef DEBUG
 -		printf("nullfs_mount: multi null mount?\n");
 -#endif
 -		return (EDEADLK);
 +	if (VOP_ISLOCKED(mp->mnt_vnodecovered, NULL)) {
 +		vput(lowerrootvp);
 +		return EBUSY;
  	}
  
  	xmp = (struct null_mount *) malloc(sizeof(struct null_mount),
 @@ -171,19 +147,18 @@
  	 */
  	error = null_node_create(mp, lowerrootvp, &vp);
  	/*
 -	 * Unlock the node (either the lower or the alias)
 -	 */
 -	VOP_UNLOCK(vp, 0, p);
 -	/*
  	 * Make sure the node alias worked
  	 */
  	if (error) {
 -		vrele(lowerrootvp);
 +		vput(lowerrootvp);
  		free(xmp, M_NULLFSMNT);	/* XXX */
  		return (error);
  	}
 -
  	/*
 +	 * Unlock the node (either the lower or the alias)
 +	 */
 +	VOP_UNLOCK(vp, 0, p);
 +	/*
  	 * Keep a held reference to the root vnode.
  	 * It is vrele'd in nullfs_unmount.
  	 */
 @@ -269,7 +244,8 @@
  	/*
  	 * And blow it away for future re-use
  	 */
 -	vgone(nullm_rootvp);
 +	if (nullm_rootvp->v_mount == mp)
 +		vgone(nullm_rootvp);
  	/*
  	 * Finally, throw away the null_mount structure
  	 */
 @@ -297,18 +273,7 @@
  	 */
  	vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
  	VREF(vp);
 -	if (VOP_ISLOCKED(vp, NULL)) {
 -		/*
 -		 * XXX
 -		 * Should we check type of node?
 -		 */
 -#ifdef DEBUG
 -		printf("nullfs_root: multi null mount?\n");
 -#endif
 -		vrele(vp);
 -		return (EDEADLK);
 -	} else
 -		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 +	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
  	*vpp = vp;
  	return 0;
  }
 Index: sys/miscfs/nullfs/null_vnops.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/miscfs/nullfs/null_vnops.c,v
 retrieving revision 1.39
 diff -u -r1.39 null_vnops.c
 --- sys/miscfs/nullfs/null_vnops.c	2000/04/18 15:15:23	1.39
 +++ sys/miscfs/nullfs/null_vnops.c	2000/08/06 19:16:51
 @@ -182,7 +182,12 @@
  #include <sys/mount.h>
  #include <sys/namei.h>
  #include <sys/malloc.h>
 +#include <sys/bio.h>
 +#include <sys/buf.h>
 +#include <sys/proc.h>
  #include <miscfs/nullfs/null.h>
 +#include <vm/vm.h>
 +#include <vm/vm_object.h>
  
  static int null_bug_bypass = 0;   /* for debugging: enables bypass printf'ing */
  SYSCTL_INT(_debug, OID_AUTO, nullfs_bug_bypass, CTLFLAG_RW, 
 @@ -191,12 +196,15 @@
  static int	null_access __P((struct vop_access_args *ap));
  static int	null_getattr __P((struct vop_getattr_args *ap));
  static int	null_inactive __P((struct vop_inactive_args *ap));
 +static int	null_islocked __P((struct vop_islocked_args *ap));
  static int	null_lock __P((struct vop_lock_args *ap));
  static int	null_lookup __P((struct vop_lookup_args *ap));
  static int	null_print __P((struct vop_print_args *ap));
  static int	null_reclaim __P((struct vop_reclaim_args *ap));
  static int	null_setattr __P((struct vop_setattr_args *ap));
  static int	null_unlock __P((struct vop_unlock_args *ap));
 +static int	null_fsync __P((struct vop_fsync_args *ap));
 +static int	null_getwritemount __P((struct vop_getwritemount_args *ap));
  
  /*
   * This is the 10-Apr-92 bypass routine.
 @@ -236,6 +244,7 @@
  	struct vnode ***vppp;
  	struct vnodeop_desc *descp = ap->a_desc;
  	int reles, i;
 +	struct mount *old_mount;
  
  	if (null_bug_bypass)
  		printf ("null_bypass: %s\n", descp->vdesc_name);
 @@ -288,6 +297,11 @@
  	 */
  	error = VCALL(*(vps_p[0]), descp->vdesc_offset, ap);
  
 +	if (descp->vdesc_vp_offsets[0] != VDESC_NO_OFFSET &&
 +	    old_vps[0] != NULLVP)
 +	  old_mount = old_vps[0]->v_mount;
 +	else
 +	  old_mount = NULL;
  	/*
  	 * Maintain the illusion of call-by-value
  	 * by restoring vnodes in the argument structure
 @@ -323,7 +337,7 @@
  		vppp = VOPARG_OFFSETTO(struct vnode***,
  				 descp->vdesc_vpp_offset,ap);
  		if (*vppp)
 -			error = null_node_create(old_vps[0]->v_mount, **vppp, *vppp);
 +			error = null_node_create(old_mount, **vppp, *vppp);
  	}
  
   out:
 @@ -496,10 +510,31 @@
  		struct proc *a_p;
  	} */ *ap;
  {
 +	struct null_node *xp;
 +	pid_t pid;
  
 +	xp = VTONULL(ap->a_vp);
 +	if ((xp->flags & NN_LOCK) != 0) {
 +		pid = (ap->a_p == NULL) ? LK_KERNPROC : ap->a_p->p_pid;
 +		if (xp->lockholder == pid) {
 +			panic("null_lock: recursive lock");
 +		} else {
 +			if ((ap->a_flags & LK_NOWAIT) != 0)
 +				return EBUSY;
 +			while ((xp->flags & NN_LOCK) != 0) {
 +				xp->flags |= NN_WANT;
 +				tsleep(xp, PINOD, "nnlock", 0);
 +			}
 +		}
 +	}
 +
  	vop_nolock(ap);
 -	if ((ap->a_flags & LK_TYPE_MASK) == LK_DRAIN)
 -		return (0);
 +	if ((ap->a_flags & LK_TYPE_MASK) == LK_DRAIN) {
 +		pid = (ap->a_p == NULL) ? LK_KERNPROC : ap->a_p->p_pid;
 +		xp->flags |= NN_LOCK;
 +		xp->lockholder = pid;
 +		return 0;
 +	}
  	ap->a_flags &= ~LK_INTERLOCK;
  	return (null_bypass((struct vop_generic_args *)ap));
  }
 @@ -517,28 +552,58 @@
  		struct proc *a_p;
  	} */ *ap;
  {
 +	struct vnode *vp = ap->a_vp;
 +	struct null_node *xp;
 +	pid_t pid;
 +
 +	xp = VTONULL(vp);
 +	if ((xp->flags & NN_LOCK) != 0) {
 +		pid = (ap->a_p == NULL) ? LK_KERNPROC : ap->a_p->p_pid;
 +		if (xp->lockholder == pid) {
 +			xp->flags &= ~ (NN_LOCK | NN_FSYNC_SKIPPED);
 +			xp->lockholder = 0;
 +			if ((xp->flags & NN_WANT) != 0) {
 +				xp->flags &= ~NN_WANT;
 +				wakeup(xp);
 +			}
 +			return 0;
 +		}
 +	}
 +
  	vop_nounlock(ap);
  	ap->a_flags &= ~LK_INTERLOCK;
  	return (null_bypass((struct vop_generic_args *)ap));
  }
  
  static int
 +null_islocked(ap)
 +	struct vop_islocked_args /* {
 +		struct vnode *a_vp;
 +	} */ *ap;
 +{
 +	struct vnode *vp;
 +	struct null_node *xp;
 +
 +	vp = ap->a_vp;
 +	xp = VTONULL(vp);
 +	if (xp == NULL || (xp->flags & NN_LOCK) != 0)
 +		return LK_EXCLUSIVE;
 +	
 +	return (null_bypass((struct vop_generic_args *)ap));
 +}
 +
 +static int
  null_inactive(ap)
  	struct vop_inactive_args /* {
  		struct vnode *a_vp;
  		struct proc *a_p;
  	} */ *ap;
  {
 -	struct vnode *vp = ap->a_vp;
 -	struct null_node *xp = VTONULL(vp);
 -	struct vnode *lowervp = xp->null_lowervp;
  	/*
  	 * Do nothing (and _don't_ bypass).
  	 * Wait to vrele lowervp until reclaim,
  	 * so that until then our null_node is in the
  	 * cache and reusable.
 -	 * We still have to tell the lower layer the vnode
 -	 * is now inactive though.
  	 *
  	 * NEEDSWORK: Someday, consider inactive'ing
  	 * the lowervp and then trying to reactivate it
 @@ -546,8 +611,8 @@
  	 * like they do in the name lookup cache code.
  	 * That's too much work for now.
  	 */
 -	VOP_INACTIVE(lowervp, ap->a_p);
  	VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
 +	vrecycle(ap->a_vp, (struct simplelock *) 0, ap->a_p);
  	return (0);
  }
  
 @@ -561,21 +626,85 @@
  	struct vnode *vp = ap->a_vp;
  	struct null_node *xp = VTONULL(vp);
  	struct vnode *lowervp = xp->null_lowervp;
 +	vm_object_t object;
  
  	/*
  	 * Note: in vop_reclaim, vp->v_op == dead_vnodeop_p,
  	 * so we can't call VOPs on ourself.
  	 */
 +
 +	object = vp->v_object;
 +	if (object != lowervp->v_object)
 +		panic("null_reclaim: wrong object");
 +	if (object != NULL) {
 +		if ((void *) lowervp != object->handle)
 +			panic("null_reclaim: wrong object handle");
 +		vp->v_object = NULL;
 +		vp->v_flag &= ~(VTEXT|VOBJBUF);
 +		if (lowervp->v_usecount < 1 + object->ref_count)
 +			panic("null_reclaim: lowervp->v_usecount too low");
 +	}
  	/* After this assignment, this node will not be re-used. */
  	xp->null_lowervp = NULLVP;
  	LIST_REMOVE(xp, null_hash);
  	FREE(vp->v_data, M_TEMP);
  	vp->v_data = NULL;
 +	if (lowervp->v_usecount < 1)
 +		panic("null_reclaim: lowervp->v_usecount < 1");
  	vrele (lowervp);
  	return (0);
  }
  
  static int
 +null_fsync(ap)
 +	struct vop_fsync_args /* {
 +		struct vnodeop_desc *a_desc;
 +		struct vnode *a_vp;
 +		struct ucred *a_cred;
 +		int a_waitfor;
 +		struct proc *a_p;
 +	} */ *ap;
 +{
 +	struct vnode *vp;
 +	struct null_node *xp;
 +	pid_t pid; 
 +
 +	vp = ap->a_vp;
 +	xp = VTONULL(vp);
 +
 +	if (!TAILQ_EMPTY(&vp->v_dirtyblkhd))
 +		panic("dirty buffers on null vnode");
 +	if (!TAILQ_EMPTY(&vp->v_cleanblkhd))
 +		panic("clean buffers on null vnode");
 +	
 +	if ((xp->flags & NN_LOCK) != 0) {
 +		pid = (ap->a_p == NULL) ? LK_KERNPROC : ap->a_p->p_pid;
 +		if (xp->lockholder == pid)
 +			if (/*  vp->v_object != NULL &&
 +			    vp->v_object->handle != (void *) vp && */
 +			    (xp->flags & NN_FSYNC_SKIPPED) == 0) { 
 +				xp->flags |= NN_FSYNC_SKIPPED;
 +				return 0;
 +			}
 +	}
 +	return (null_bypass((struct vop_generic_args *)ap));
 +}
 +
 +int
 +null_getwritemount(ap)
 +	struct vop_getwritemount_args /* {
 +		struct vnode *a_vp;
 +		struct mount **a_mpp;
 +	} */ *ap;
 +{
 +  if (VTONULL(ap->a_vp) == NULL) {
 +    return VOP_GETWRITEMOUNT(ap->a_vp->v_mount->mnt_vnodecovered, ap->a_mpp);
 +  } else
 +    return (null_bypass((struct vop_generic_args *) ap));
 +}
 +
 +
 +static int
  null_print(ap)
  	struct vop_print_args /* {
  		struct vnode *a_vp;
 @@ -595,12 +724,15 @@
  	{ &vop_access_desc,		(vop_t *) null_access },
  	{ &vop_getattr_desc,		(vop_t *) null_getattr },
  	{ &vop_inactive_desc,		(vop_t *) null_inactive },
 +	{ &vop_islocked_desc,		(vop_t *) null_islocked },
  	{ &vop_lock_desc,		(vop_t *) null_lock },
  	{ &vop_lookup_desc,		(vop_t *) null_lookup },
  	{ &vop_print_desc,		(vop_t *) null_print },
  	{ &vop_reclaim_desc,		(vop_t *) null_reclaim },
  	{ &vop_setattr_desc,		(vop_t *) null_setattr },
  	{ &vop_unlock_desc,		(vop_t *) null_unlock },
 +	{ &vop_fsync_desc,		(vop_t *) null_fsync },
 +	{ &vop_getwritemount_desc,	(vop_t *) null_getwritemount },
  	{ NULL, NULL }
  };
  static struct vnodeopv_desc null_vnodeop_opv_desc =
 Index: sys/vm/vnode_pager.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/vm/vnode_pager.c,v
 retrieving revision 1.124
 diff -u -r1.124 vnode_pager.c
 --- sys/vm/vnode_pager.c	2000/07/11 22:07:57	1.124
 +++ sys/vm/vnode_pager.c	2000/08/06 19:17:02
 @@ -154,7 +154,7 @@
  		vp->v_usecount++;
  	} else {
  		object->ref_count++;
 -		vp->v_usecount++;
 +		((struct vnode *) object->handle)->v_usecount++;
  	}
  
  	vp->v_flag &= ~VOLOCK;
 
 
 - Tor Egge
 
 


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200008161940.MAA01501>