Index: sys/nfsserver/nfs_serv.c =================================================================== RCS file: /home/ncvs/src/sys/nfsserver/nfs_serv.c,v retrieving revision 1.156 diff -u -r1.156 nfs_serv.c --- sys/nfsserver/nfs_serv.c 17 Apr 2005 16:25:36 -0000 1.156 +++ sys/nfsserver/nfs_serv.c 13 Feb 2007 20:43:09 -0000 @@ -569,6 +569,10 @@ error = lookup(&ind); ind.ni_dvp = NULL; + if (ind.ni_cnd.cn_flags & GIANTHELD) { + mtx_unlock(&Giant); + ind.ni_cnd.cn_flags &= ~GIANTHELD; + } if (error == 0) { /* @@ -599,15 +603,9 @@ } } - if (dirp) { - vrele(dirp); - dirp = NULL; - } - /* * Resources at this point: * ndp->ni_vp may not be NULL - * */ if (error) { @@ -621,15 +619,6 @@ } /* - * Clear out some resources prior to potentially blocking. This - * is not as critical as ni_dvp resources in other routines, but - * it helps. - */ - vrele(ndp->ni_startdir); - ndp->ni_startdir = NULL; - NDFREE(&nd, NDF_ONLY_PNBUF); - - /* * Get underlying attribute, then release remaining resources ( for * the same potential blocking reason ) and reply. */ @@ -641,8 +630,12 @@ error = VOP_GETATTR(vp, vap, cred, td); vput(vp); - mtx_unlock(&Giant); /* VFS */ + vrele(ndp->ni_startdir); + vrele(dirp); ndp->ni_vp = NULL; + ndp->ni_startdir = NULL; + dirp = NULL; + mtx_unlock(&Giant); /* VFS */ NFSD_LOCK(); nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3)); if (error) { @@ -662,17 +655,19 @@ nfsmout: NFSD_LOCK_ASSERT(); - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ - if (dirp) - vrele(dirp); + if (ndp->ni_vp || dirp || ndp->ni_startdir) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ + if (ndp->ni_vp) + vput(ndp->ni_vp); + if (dirp) + vrele(dirp); + if (ndp->ni_startdir) + vrele(ndp->ni_startdir); + mtx_unlock(&Giant); /* VFS */ + NFSD_LOCK(); + } NDFREE(&nd, NDF_ONLY_PNBUF); - if (ndp->ni_startdir) - vrele(ndp->ni_startdir); - if (ndp->ni_vp) - vput(ndp->ni_vp); - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); return (error); } @@ -1924,6 +1919,10 @@ error = lookup(&nd); nd.ni_dvp = NULL; + if (nd.ni_cnd.cn_flags & GIANTHELD) { + mtx_unlock(&Giant); + nd.ni_cnd.cn_flags &= ~GIANTHELD; + } if (error) goto ereply; @@ -2004,13 +2003,6 @@ NFSD_LOCK_ASSERT(); NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ - if (nd.ni_startdir) { - vrele(nd.ni_startdir); - nd.ni_startdir = NULL; - } - if (dirp) - vrele(dirp); - NDFREE(&nd, NDF_ONLY_PNBUF); if (nd.ni_dvp) { if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); @@ -2019,6 +2011,13 @@ } if (nd.ni_vp) vput(nd.ni_vp); + if (nd.ni_startdir) { + vrele(nd.ni_startdir); + nd.ni_startdir = NULL; + } + if (dirp) + vrele(dirp); + NDFREE(&nd, NDF_ONLY_PNBUF); vn_finished_write(mp); mtx_unlock(&Giant); /* VFS */ NFSD_LOCK(); @@ -2092,6 +2091,8 @@ tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED); vtyp = nfsv3tov_type(*tl); if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ error = NFSERR_BADTYPE; goto out; } @@ -2108,6 +2109,8 @@ * Iff doesn't exist, create it. */ if (nd.ni_vp) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ error = EEXIST; goto out; } @@ -2146,6 +2149,10 @@ error = lookup(&nd); nd.ni_dvp = NULL; + if (nd.ni_cnd.cn_flags & GIANTHELD) { + mtx_unlock(&Giant); + nd.ni_cnd.cn_flags &= ~GIANTHELD; + } if (error) goto out; @@ -2158,18 +2165,6 @@ */ out: NFSD_UNLOCK_ASSERT(); - if (nd.ni_startdir) { - vrele(nd.ni_startdir); - nd.ni_startdir = NULL; - } - NDFREE(&nd, NDF_ONLY_PNBUF); - if (nd.ni_dvp) { - if (nd.ni_dvp == nd.ni_vp) - vrele(nd.ni_dvp); - else - vput(nd.ni_dvp); - nd.ni_dvp = NULL; - } vp = nd.ni_vp; if (!error) { bzero((caddr_t)fhp, sizeof(nfh)); @@ -2178,11 +2173,23 @@ if (!error) error = VOP_GETATTR(vp, vap, cred, td); } + if (nd.ni_dvp) { + if (nd.ni_dvp == nd.ni_vp) + vrele(nd.ni_dvp); + else + vput(nd.ni_dvp); + nd.ni_dvp = NULL; + } if (vp) { vput(vp); vp = NULL; nd.ni_vp = NULL; } + if (nd.ni_startdir) { + vrele(nd.ni_startdir); + nd.ni_startdir = NULL; + } + NDFREE(&nd, NDF_ONLY_PNBUF); if (dirp) { vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td); diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td); @@ -2210,11 +2217,6 @@ NFSD_LOCK_ASSERT(); NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ - if (dirp) - vrele(dirp); - if (nd.ni_startdir) - vrele(nd.ni_startdir); - NDFREE(&nd, NDF_ONLY_PNBUF); if (nd.ni_dvp) { if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); @@ -2223,6 +2225,11 @@ } if (nd.ni_vp) vput(nd.ni_vp); + if (dirp) + vrele(dirp); + if (nd.ni_startdir) + vrele(nd.ni_startdir); + NDFREE(&nd, NDF_ONLY_PNBUF); vn_finished_write(mp); mtx_unlock(&Giant); /* VFS */ NFSD_LOCK(); @@ -2519,8 +2526,8 @@ tond.ni_dvp = NULL; tond.ni_vp = NULL; if (error) { - fromnd.ni_cnd.cn_flags &= ~HASBUF; - tond.ni_cnd.cn_flags &= ~HASBUF; + NDFREE(&fromnd, NDF_ONLY_PNBUF); + NDFREE(&tond, NDF_ONLY_PNBUF); } } else { if (error == -1) @@ -2573,11 +2580,6 @@ NFSD_LOCK_ASSERT(); NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ - if (tdirp) - vrele(tdirp); - if (tond.ni_startdir) - vrele(tond.ni_startdir); - NDFREE(&tond, NDF_ONLY_PNBUF); if (tond.ni_dvp) { if (tond.ni_dvp == tond.ni_vp) vrele(tond.ni_dvp); @@ -2586,7 +2588,11 @@ } if (tond.ni_vp) vput(tond.ni_vp); - + if (tdirp) + vrele(tdirp); + if (tond.ni_startdir) + vrele(tond.ni_startdir); + NDFREE(&tond, NDF_ONLY_PNBUF); /* * Clear out fromnd related fields */ @@ -2747,8 +2753,6 @@ NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ NDFREE(&nd, NDF_ONLY_PNBUF); - if (dirp) - vrele(dirp); if (vp) vput(vp); if (nd.ni_dvp) { @@ -2757,6 +2761,8 @@ else vput(nd.ni_dvp); } + if (dirp) + vrele(dirp); if (nd.ni_vp) vrele(nd.ni_vp); vn_finished_write(mp); @@ -2815,6 +2821,12 @@ nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART; error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos, &dirp, v3, &dirfor, &dirfor_ret, td, FALSE); + if (error == 0) { + VATTR_NULL(vap); + if (v3) + nfsm_srvsattr(vap); + nfsm_srvpathsiz(len2); + } NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ if (dirp && !v3) { @@ -2824,10 +2836,6 @@ if (error) goto out; - VATTR_NULL(vap); - if (v3) - nfsm_srvsattr(vap); - nfsm_srvpathsiz(len2); MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK); iv.iov_base = pathcp; iv.iov_len = len2; @@ -2884,6 +2892,10 @@ error = lookup(&nd); nd.ni_dvp = NULL; + if (nd.ni_cnd.cn_flags & GIANTHELD) { + mtx_unlock(&Giant); + nd.ni_cnd.cn_flags &= ~GIANTHELD; + } if (error == 0) { bzero((caddr_t)fhp, sizeof(nfh)); @@ -3113,8 +3125,6 @@ NFSD_LOCK_ASSERT(); NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ - if (dirp) - vrele(dirp); if (nd.ni_dvp) { NDFREE(&nd, NDF_ONLY_PNBUF); if (nd.ni_dvp == nd.ni_vp && vpexcl) @@ -3128,6 +3138,8 @@ else vrele(nd.ni_vp); } + if (dirp) + vrele(dirp); vn_finished_write(mp); mtx_unlock(&Giant); /* VFS */ NFSD_LOCK(); @@ -3255,8 +3267,6 @@ NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ NDFREE(&nd, NDF_ONLY_PNBUF); - if (dirp) - vrele(dirp); if (nd.ni_dvp) { if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); @@ -3265,6 +3275,8 @@ } if (nd.ni_vp) vput(nd.ni_vp); + if (dirp) + vrele(dirp); vn_finished_write(mp); mtx_unlock(&Giant); /* VFS */ Index: sys/nfsserver/nfs_srvsubs.c =================================================================== RCS file: /home/ncvs/src/sys/nfsserver/nfs_srvsubs.c,v retrieving revision 1.136 diff -u -r1.136 nfs_srvsubs.c --- sys/nfsserver/nfs_srvsubs.c 28 Mar 2005 18:51:58 -0000 1.136 +++ sys/nfsserver/nfs_srvsubs.c 13 Feb 2007 20:43:09 -0000 @@ -875,6 +875,10 @@ } if (!lockleaf) cnp->cn_flags &= ~LOCKLEAF; + if (cnp->cn_flags & GIANTHELD) { + mtx_unlock(&Giant); + cnp->cn_flags &= ~GIANTHELD; + } /* * nfs_namei() guarentees that fields will not contain garbage @@ -1331,6 +1335,24 @@ return 0; } +int +nfsm_srvnamesiz0_xx(int *s, int m, struct mbuf **md, caddr_t *dpos) +{ + u_int32_t *tl; + + NFSD_LOCK_DONTCARE(); + + tl = nfsm_dissect_xx_nonblock(NFSX_UNSIGNED, md, dpos); + if (tl == NULL) + return EBADRPC; + *s = fxdr_unsigned(int32_t, *tl); + if (*s > m) + return NFSERR_NAMETOL; + if (*s < 0) + return EBADRPC; + return 0; +} + void nfsm_clget_xx(u_int32_t **tl, struct mbuf *mb, struct mbuf **mp, char **bp, char **be, caddr_t bpos, int droplock) Index: sys/nfsserver/nfsm_subs.h =================================================================== RCS file: /home/ncvs/src/sys/nfsserver/nfsm_subs.h,v retrieving revision 1.37 diff -u -r1.37 nfsm_subs.h --- sys/nfsserver/nfsm_subs.h 7 Jan 2005 01:45:51 -0000 1.37 +++ sys/nfsserver/nfsm_subs.h 13 Feb 2007 20:43:09 -0000 @@ -74,6 +74,7 @@ int nfsm_srvstrsiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos); int nfsm_srvnamesiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos); +int nfsm_srvnamesiz0_xx(int *s, int m, struct mbuf **md, caddr_t *dpos); int nfsm_srvmtofh_xx(fhandle_t *f, struct nfsrv_descript *nfsd, struct mbuf **md, caddr_t *dpos); int nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos); @@ -101,7 +102,7 @@ #define nfsm_srvpathsiz(s) \ do { \ int t1; \ - t1 = nfsm_srvnamesiz_xx(&(s), NFS_MAXPATHLEN, &md, &dpos); \ + t1 = nfsm_srvnamesiz0_xx(&(s), NFS_MAXPATHLEN, &md, &dpos); \ if (t1) { \ error = t1; \ nfsm_reply(0); \