Index: sys/nfsserver/nfs_serv.c =================================================================== --- sys/nfsserver/nfs_serv.c (wersja 216626) +++ sys/nfsserver/nfs_serv.c (kopia robocza) @@ -213,8 +213,7 @@ fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED); - error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, nfsd, slp, - nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly); if (error) { nfsm_reply(NFSX_UNSIGNED); nfsm_srvpostop_attr(1, NULL); @@ -280,8 +279,7 @@ vfslocked = 0; fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); - error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, nfsd, slp, nam, - &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly); if (error) { nfsm_reply(0); error = 0; @@ -389,8 +387,7 @@ /* * Now that we have all the fields, lets do it. */ - error = nfsrv_fhtovp(fhp, 1, &vp, &tvfslocked, nfsd, slp, - nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 0, &vp, &tvfslocked, nfsd, slp, nam, &rdonly); vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked); if (error) { nfsm_reply(2 * NFSX_UNSIGNED); @@ -712,8 +709,7 @@ uiop->uio_rw = UIO_READ; uiop->uio_segflg = UIO_SYSSPACE; uiop->uio_td = NULL; - error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, nfsd, slp, - nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly); if (error) { nfsm_reply(2 * NFSX_UNSIGNED); if (v3) @@ -808,8 +804,7 @@ * as well. */ - error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, nfsd, slp, - nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly); if (error) { vp = NULL; nfsm_reply(2 * NFSX_UNSIGNED); @@ -1109,8 +1104,7 @@ error = 0; goto nfsmout; } - error = nfsrv_fhtovp(fhp, 1, &vp, &tvfslocked, nfsd, slp, - nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 0, &vp, &tvfslocked, nfsd, slp, nam, &rdonly); vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked); if (error) { vp = NULL; @@ -2102,8 +2096,7 @@ nfsm_srvmtofh(dfhp); nfsm_srvnamesiz(len); - error = nfsrv_fhtovp(fhp, TRUE, &vp, &tvfslocked, nfsd, slp, - nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 0, &vp, &tvfslocked, nfsd, slp, nam, &rdonly); vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked); if (error) { nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); @@ -2770,8 +2763,7 @@ if (siz > xfer) siz = xfer; fullsiz = siz; - error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, nfsd, slp, - nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly); if (!error && vp->v_type != VDIR) { error = ENOTDIR; vput(vp); @@ -3044,9 +3036,11 @@ int v3 = (nfsd->nd_flag & ND_NFSV3); int usevget = 1, vfslocked; struct componentname cn; + struct mount *mntp = NULL; nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); vfslocked = 0; + vp_locked = 0; if (!v3) panic("nfsrv_readdirplus: v3 proc called on a v2 connection"); fhp = &nfh.fh_generic; @@ -3066,14 +3060,17 @@ if (siz > xfer) siz = xfer; fullsiz = siz; - error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, nfsd, slp, - nam, &rdonly, TRUE); - vp_locked = 1; - if (!error && vp->v_type != VDIR) { - error = ENOTDIR; - vput(vp); - vp = NULL; - vp_locked = 0; + error = nfsrv_fhtovp(fhp, NFSRV_FLAG_BUSY, &vp, &vfslocked, nfsd, slp, + nam, &rdonly); + if (!error) { + vp_locked = 1; + mntp = vp->v_mount; + if (vp->v_type != VDIR) { + error = ENOTDIR; + vput(vp); + vp = NULL; + vp_locked = 0; + } } if (error) { nfsm_reply(NFSX_UNSIGNED); @@ -3215,8 +3212,8 @@ * For readdir_and_lookup get the vnode using * the file number. */ - error = VFS_VGET(vp->v_mount, dp->d_fileno, - LK_SHARED, &nvp); + error = VFS_VGET(mntp, dp->d_fileno, LK_SHARED, + &nvp); if (error != 0 && error != EOPNOTSUPP) { error = 0; goto invalid; @@ -3375,6 +3372,8 @@ nfsmout: if (vp) vrele(vp); + if (mntp) + vfs_unbusy(mntp); VFS_UNLOCK_GIANT(vfslocked); return(error); } @@ -3426,8 +3425,7 @@ off = fxdr_hyper(tl); tl += 2; cnt = fxdr_unsigned(int, *tl); - error = nfsrv_fhtovp(fhp, 1, &vp, &tvfslocked, nfsd, slp, - nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 0, &vp, &tvfslocked, nfsd, slp, nam, &rdonly); vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked); if (error) { nfsm_reply(2 * NFSX_UNSIGNED); @@ -3571,8 +3569,7 @@ vfslocked = 0; fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); - error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, nfsd, slp, - nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly); if (error) { nfsm_reply(NFSX_UNSIGNED); if (v3) @@ -3666,8 +3663,7 @@ fhp = &nfh.fh_generic; vfslocked = 0; nfsm_srvmtofh(fhp); - error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, nfsd, slp, - nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly); if (error) { nfsm_reply(NFSX_UNSIGNED); nfsm_srvpostop_attr(getret, &at); @@ -3741,8 +3737,7 @@ vfslocked = 0; fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); - error = nfsrv_fhtovp(fhp, 1, &vp, &vfslocked, nfsd, slp, - nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly); if (error) { nfsm_reply(NFSX_UNSIGNED); nfsm_srvpostop_attr(getret, &at); Index: sys/nfsserver/nfs.h =================================================================== --- sys/nfsserver/nfs.h (wersja 216626) +++ sys/nfsserver/nfs.h (kopia robocza) @@ -239,6 +239,12 @@ #endif +/* + * The following flags can be passed to nfsrv_fhtovp() function. + */ +/* Leave file system busy on success. */ +#define NFSRV_FLAG_BUSY 0x01 + struct mbuf *nfs_rephead(int, struct nfsrv_descript *, int, struct mbuf **, caddr_t *); void nfsm_srvfattr(struct nfsrv_descript *, struct vattr *, @@ -264,7 +270,7 @@ struct mbuf **mrq); int nfsrv_fhtovp(fhandle_t *, int, struct vnode **, int *, struct nfsrv_descript *, struct nfssvc_sock *, struct sockaddr *, - int *, int); + int *); int nfsrv_setpublicfs(struct mount *, struct netexport *, struct export_args *); int nfs_ispublicfh(fhandle_t *); Index: sys/nfsserver/nfs_srvsubs.c =================================================================== --- sys/nfsserver/nfs_srvsubs.c (wersja 216627) +++ sys/nfsserver/nfs_srvsubs.c (kopia robocza) @@ -639,16 +639,18 @@ goto out; } + if (!pubflag && nfs_ispublicfh(fhp)) + return (ESTALE); + /* * Extract and set starting directory. */ - error = nfsrv_fhtovp(fhp, FALSE, &dp, &dvfslocked, - nfsd, slp, nam, &rdonly, pubflag); + error = nfsrv_fhtovp(fhp, 0, &dp, &dvfslocked, nfsd, slp, nam, &rdonly); if (error) goto out; vfslocked = VFS_LOCK_GIANT(dp->v_mount); if (dp->v_type != VDIR) { - vrele(dp); + vput(dp); error = ENOTDIR; goto out; } @@ -662,12 +664,12 @@ */ *retdirp = dp; if (v3) { - vn_lock(dp, LK_EXCLUSIVE | LK_RETRY); *retdirattr_retp = VOP_GETATTR(dp, retdirattrp, ndp->ni_cnd.cn_cred); - VOP_UNLOCK(dp, 0); } + VOP_UNLOCK(dp, 0); + if (pubflag) { /* * Oh joy. For WebNFS, handle those pesky '%' escapes, @@ -1051,12 +1053,11 @@ * - look up fsid in mount list (if not found ret error) * - get vp and export rights by calling VFS_FHTOVP() * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon - * - if not lockflag unlock it with VOP_UNLOCK() */ int -nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, int *vfslockedp, +nfsrv_fhtovp(fhandle_t *fhp, int flags, struct vnode **vpp, int *vfslockedp, struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, - struct sockaddr *nam, int *rdonlyp, int pubflag) + struct sockaddr *nam, int *rdonlyp) { struct mount *mp; int i; @@ -1076,7 +1077,7 @@ *vpp = NULL; if (nfs_ispublicfh(fhp)) { - if (!pubflag || !nfs_pub.np_valid) + if (!nfs_pub.np_valid) return (ESTALE); fhp = &nfs_pub.np_handle; } @@ -1128,12 +1129,12 @@ } } error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp); - if (error != 0) + if (error) { /* Make sure the server replies ESTALE to the client. */ error = ESTALE; - vfs_unbusy(mp); - if (error) + vfs_unbusy(mp); goto out; + } #ifdef MNT_EXNORESPORT if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) { saddr = (struct sockaddr_in *)nam; @@ -1144,6 +1145,8 @@ vput(*vpp); *vpp = NULL; error = NFSERR_AUTHERR | AUTH_TOOWEAK; + vfs_unbusy(mp); + goto out; } } #endif @@ -1160,8 +1163,8 @@ else *rdonlyp = 0; - if (!lockflag) - VOP_UNLOCK(*vpp, 0); + if (!(flags & NFSRV_FLAG_BUSY)) + vfs_unbusy(mp); out: if (credanon != NULL) crfree(credanon);