Use vfs_hash_ref(9) to eliminate LK_EXCLOTHER kludge. As a

consequence, the nfs client override of VOP_LOCK1() is no longer
needed.

Reviewed and tested by:	rmacklem
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2016-05-11 06:35:46 +00:00
parent 54a33d2f97
commit b6a60ae74a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=299413
2 changed files with 13 additions and 43 deletions

View File

@ -293,7 +293,7 @@ nfscl_nget(struct mount *mntp, struct vnode *dvp, struct nfsfh *nfhp,
}
/*
* Anothe variant of nfs_nget(). This one is only used by reopen. It
* Another variant of nfs_nget(). This one is only used by reopen. It
* takes almost the same args as nfs_nget(), but only succeeds if an entry
* exists in the cache. (Since files should already be "open" with a
* vnode ref cnt on the node when reopen calls this, it should always
@ -332,21 +332,24 @@ nfscl_ngetreopen(struct mount *mntp, u_int8_t *fhp, int fhsize,
NFSVOPUNLOCK(nvp, 0);
} else if (error == EBUSY) {
/*
* The LK_EXCLOTHER lock type tells nfs_lock1() to not try
* and lock the vnode, but just get a v_usecount on it.
* LK_NOWAIT is set so that when vget() returns ENOENT,
* vfs_hash_get() fails instead of looping.
* If this succeeds, it is safe so long as a vflush() with
* It is safe so long as a vflush() with
* FORCECLOSE has not been done. Since the Renew thread is
* stopped and the MNTK_UNMOUNTF flag is set before doing
* a vflush() with FORCECLOSE, we should be ok here.
*/
if ((mntp->mnt_kern_flag & MNTK_UNMOUNTF))
error = EINTR;
else
error = vfs_hash_get(mntp, hash,
(LK_EXCLOTHER | LK_NOWAIT), td, &nvp,
newnfs_vncmpf, nfhp);
else {
vfs_hash_ref(mntp, hash, td, &nvp, newnfs_vncmpf, nfhp);
if (nvp == NULL) {
error = ENOENT;
} else if ((nvp->v_iflag & VI_DOOMED) != 0) {
error = ENOENT;
vrele(nvp);
} else {
error = 0;
}
}
}
FREE(nfhp, M_NFSFH);
if (error)

View File

@ -138,7 +138,6 @@ static vop_rmdir_t nfs_rmdir;
static vop_symlink_t nfs_symlink;
static vop_readdir_t nfs_readdir;
static vop_strategy_t nfs_strategy;
static vop_lock1_t nfs_lock1;
static int nfs_lookitup(struct vnode *, char *, int,
struct ucred *, struct thread *, struct nfsnode **);
static int nfs_sillyrename(struct vnode *, struct vnode *,
@ -167,7 +166,6 @@ struct vop_vector newnfs_vnodeops = {
.vop_putpages = ncl_putpages,
.vop_inactive = ncl_inactive,
.vop_link = nfs_link,
.vop_lock1 = nfs_lock1,
.vop_lookup = nfs_lookup,
.vop_mkdir = nfs_mkdir,
.vop_mknod = nfs_mknod,
@ -3349,37 +3347,6 @@ struct buf_ops buf_ops_newnfs = {
.bop_bdflush = bufbdflush,
};
/*
* Cloned from vop_stdlock(), and then the ugly hack added.
*/
static int
nfs_lock1(struct vop_lock1_args *ap)
{
struct vnode *vp = ap->a_vp;
int error = 0;
/*
* Since vfs_hash_get() calls vget() and it will no longer work
* for FreeBSD8 with flags == 0, I can only think of this horrible
* hack to work around it. I call vfs_hash_get() with LK_EXCLOTHER
* and then handle it here. All I want for this case is a v_usecount
* on the vnode to use for recovery, while another thread might
* hold a lock on the vnode. I have the other threads blocked, so
* there isn't any race problem.
*/
if ((ap->a_flags & LK_TYPE_MASK) == LK_EXCLOTHER) {
if ((ap->a_flags & LK_INTERLOCK) == 0)
panic("ncllock1");
if ((vp->v_iflag & VI_DOOMED))
error = ENOENT;
VI_UNLOCK(vp);
return (error);
}
return (_lockmgr_args(vp->v_vnlock, ap->a_flags, VI_MTX(vp),
LK_WMESG_DEFAULT, LK_PRIO_DEFAULT, LK_TIMO_DEFAULT, ap->a_file,
ap->a_line));
}
static int
nfs_getacl(struct vop_getacl_args *ap)
{