VOP_ISLOCKED() should not be used to determine if the vnode is locked.

Explicitely track the locked status of the vnode.

Reviewed by:	pjd
Tested by:	avg
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2010-12-15 12:46:53 +00:00
parent 03ee10d8e4
commit 607ccc8676
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=216454

View File

@ -3037,6 +3037,7 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct vattr va, at, *vap = &va; struct vattr va, at, *vap = &va;
struct nfs_fattr *fp; struct nfs_fattr *fp;
int len, nlen, rem, xfer, tsiz, i, error = 0, error1, getret = 1; int len, nlen, rem, xfer, tsiz, i, error = 0, error1, getret = 1;
int vp_locked;
int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies; int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
u_quad_t off, toff, verf; u_quad_t off, toff, verf;
u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
@ -3067,10 +3068,12 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
fullsiz = siz; fullsiz = siz;
error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, nfsd, slp, error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, nfsd, slp,
nam, &rdonly, TRUE); nam, &rdonly, TRUE);
vp_locked = 1;
if (!error && vp->v_type != VDIR) { if (!error && vp->v_type != VDIR) {
error = ENOTDIR; error = ENOTDIR;
vput(vp); vput(vp);
vp = NULL; vp = NULL;
vp_locked = 0;
} }
if (error) { if (error) {
nfsm_reply(NFSX_UNSIGNED); nfsm_reply(NFSX_UNSIGNED);
@ -3090,6 +3093,7 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
error = nfsrv_access(vp, VEXEC, cred, rdonly, 0); error = nfsrv_access(vp, VEXEC, cred, rdonly, 0);
if (error) { if (error) {
vput(vp); vput(vp);
vp_locked = 0;
vp = NULL; vp = NULL;
nfsm_reply(NFSX_V3POSTOPATTR); nfsm_reply(NFSX_V3POSTOPATTR);
nfsm_srvpostop_attr(getret, &at); nfsm_srvpostop_attr(getret, &at);
@ -3097,6 +3101,7 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
goto nfsmout; goto nfsmout;
} }
VOP_UNLOCK(vp, 0); VOP_UNLOCK(vp, 0);
vp_locked = 0;
rbuf = malloc(siz, M_TEMP, M_WAITOK); rbuf = malloc(siz, M_TEMP, M_WAITOK);
again: again:
iv.iov_base = rbuf; iv.iov_base = rbuf;
@ -3110,6 +3115,7 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
io.uio_td = NULL; io.uio_td = NULL;
eofflag = 0; eofflag = 0;
vn_lock(vp, LK_SHARED | LK_RETRY); vn_lock(vp, LK_SHARED | LK_RETRY);
vp_locked = 1;
if (cookies) { if (cookies) {
free((caddr_t)cookies, M_TEMP); free((caddr_t)cookies, M_TEMP);
cookies = NULL; cookies = NULL;
@ -3118,6 +3124,7 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
off = (u_quad_t)io.uio_offset; off = (u_quad_t)io.uio_offset;
getret = VOP_GETATTR(vp, &at, cred); getret = VOP_GETATTR(vp, &at, cred);
VOP_UNLOCK(vp, 0); VOP_UNLOCK(vp, 0);
vp_locked = 0;
if (!cookies && !error) if (!cookies && !error)
error = NFSERR_PERM; error = NFSERR_PERM;
if (!error) if (!error)
@ -3238,8 +3245,10 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
} else { } else {
cn.cn_flags &= ~ISDOTDOT; cn.cn_flags &= ~ISDOTDOT;
} }
if (!VOP_ISLOCKED(vp)) if (!vp_locked) {
vn_lock(vp, LK_SHARED | LK_RETRY); vn_lock(vp, LK_SHARED | LK_RETRY);
vp_locked = 1;
}
if ((vp->v_vflag & VV_ROOT) != 0 && if ((vp->v_vflag & VV_ROOT) != 0 &&
(cn.cn_flags & ISDOTDOT) != 0) { (cn.cn_flags & ISDOTDOT) != 0) {
vref(vp); vref(vp);
@ -3342,7 +3351,7 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
cookiep++; cookiep++;
ncookies--; ncookies--;
} }
if (!usevget && VOP_ISLOCKED(vp)) if (!usevget && vp_locked)
vput(vp); vput(vp);
else else
vrele(vp); vrele(vp);