FreeBSD/sys/fs/nfsclient/nfs_clvnops.c
/*
 * nfs file remove call
 * To try and make nfs semantics closer to ufs semantics, a file that has
 * other processes using the vnode is renamed instead of removed and then
 * removed later on the last close.
 * - If v_usecount > 1
 *	  If a rename is not already in the works
 *	     call nfs_sillyrename() to set it up
 *     else
 *	  do the remove rpc
 */
nfs file remove call
To try and make nfs semantics closer to ufs semantics, a file that has
other processes using the vnode is renamed instead of removed and then
removed later on the last close.
- If v_usecount > 1
If a rename is not already in the works
call nfs_sillyrename() to set it up
else
do the remove rpc
nfs file remove call To try and make nfs semantics closer to ufs semantics a file that has other processes using the vnode is renamed instead of removed and then removed later on the last close . - If v_usecount > 1 If a rename is not already in the works call nfs_sillyrename () to set it up else do the remove rpc
static int
nfs_remove(struct vop_remove_args *ap)
{
	struct vnode *vp = ap->a_vp;
	struct vnode *dvp = ap->a_dvp;
	struct componentname *cnp = ap->a_cnp;
	struct nfsnode *np = VTONFS(vp);
	int error = 0;
	struct vattr vattr;
	KASSERT((cnp->cn_flags & HASBUF) != 0, ("nfs_remove: no name"));
	KASSERT(vrefcnt(vp) > 0, ("nfs_remove: bad v_usecount"));
	if (vp->v_type == VDIR)
		error = EPERM;
	else if (vrefcnt(vp) == 1 || (np->n_sillyrename &&
	    VOP_GETATTR(vp, &vattr, cnp->cn_cred) == 0 &&
	    vattr.va_nlink > 1)) {
		cache_purge(vp);
		error = ncl_vinvalbuf(vp, 0, cnp->cn_thread, 1);
		if (error != EINTR && error != EIO)
			error = nfs_removerpc(dvp, vp, cnp->cn_nameptr,
			    cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread);
		if (error == ENOENT)
			error = 0;
	} else if (!np->n_sillyrename)
		error = nfs_sillyrename(dvp, vp, cnp);
	mtx_lock(&np->n_mtx);
	np->n_attrstamp = 0;
	mtx_unlock(&np->n_mtx);
	KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
	return (error);
}
static int nfs_remove ( struct vop_remove_args * ap ) { struct vnode * vp = ap -> a_vp ; struct vnode * dvp = ap -> a_dvp ; struct componentname * cnp = ap -> a_cnp ; struct nfsnode * np = VTONFS ( vp ) ; int error = 0 ; struct vattr vattr ; KASSERT ( ( cnp -> cn_flags & HASBUF ) != 0 , ( " " ) ) ; KASSERT ( vrefcnt ( vp ) > 0 , ( " " ) ) ; if ( vp -> v_type == VDIR ) error = EPERM ; else if ( vrefcnt ( vp ) == 1 || ( np -> n_sillyrename && VOP_GETATTR ( vp , & vattr , cnp -> cn_cred ) == 0 && vattr . va_nlink > 1 ) ) { cache_purge ( vp ) ; error = ncl_vinvalbuf ( vp , 0 , cnp -> cn_thread , 1 ) ; if ( error != EINTR && error != EIO ) error = nfs_removerpc ( dvp , vp , cnp -> cn_nameptr , cnp -> cn_namelen , cnp -> cn_cred , cnp -> cn_thread ) ; if ( error == ENOENT ) error = 0 ; } else if ( ! np -> n_sillyrename ) error = nfs_sillyrename ( dvp , vp , cnp ) ; mtx_lock ( & np -> n_mtx ) ; np -> n_attrstamp = 0 ; mtx_unlock ( & np -> n_mtx ) ; KDTRACE_NFS_ATTRCACHE_FLUSH_DONE ( vp ) ; return ( error ) ; }
nfs file remove call
 To try and make nfs semantics closer to ufs semantics, a file that has
 other processes using the vnode is renamed instead of removed and then
 removed later on the last close.
nfs file remove call To try and make nfs semantics closer to ufs semantics a file that has other processes using the vnode is renamed instead of removed and then removed later on the last close .
/*
		 * Purge the name cache so that the chance of a lookup for
		 * the name succeeding while the remove is in progress is
		 * minimized. Without node locking it can still happen, such
		 * that an I/O op returns ESTALE, but since you get this if
		 * another host removes the file..
		 */ /*
		 * throw away biocache buffers, mainly to avoid
		 * unnecessary delayed writes later.
		 */ /* Do the rpc */ /*
		 * Kludge City: If the first reply to the remove rpc is lost..
		 *   the reply to the retransmitted request will be ENOENT
		 *   since the file was in fact removed
		 *   Therefore, we cheat and return success.
		 */