diff options
Diffstat (limited to 'sys/nfsserver/nfs_serv.c')
-rw-r--r-- | sys/nfsserver/nfs_serv.c | 148 |
1 files changed, 80 insertions, 68 deletions
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c index 4a028fa7d265..38e74663b145 100644 --- a/sys/nfsserver/nfs_serv.c +++ b/sys/nfsserver/nfs_serv.c @@ -569,6 +569,10 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 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 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, } } - if (dirp) { - vrele(dirp); - dirp = NULL; - } - /* * Resources at this point: * ndp->ni_vp may not be NULL - * */ if (error) { @@ -621,15 +619,6 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, } /* - * 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 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 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 @@ nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 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 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 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 @@ nfsmout: 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 @@ nfsmout: } 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 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 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 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, * Iff doesn't exist, create it. */ if (nd.ni_vp) { + NFSD_UNLOCK(); + mtx_lock(&Giant); /* VFS */ error = EEXIST; goto out; } @@ -2146,6 +2149,10 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 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 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, */ 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 @@ out: 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 @@ nfsmout: 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 @@ nfsmout: } 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 @@ out: 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 @@ nfsmout: 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 @@ nfsmout: } 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 @@ nfsmout: 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 @@ nfsmout: 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 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 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 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 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 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 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 @@ nfsmout: 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 @@ nfsmout: else vrele(nd.ni_vp); } + if (dirp) + vrele(dirp); vn_finished_write(mp); mtx_unlock(&Giant); /* VFS */ NFSD_LOCK(); @@ -3255,8 +3267,6 @@ nfsmout: 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 @@ nfsmout: } if (nd.ni_vp) vput(nd.ni_vp); + if (dirp) + vrele(dirp); vn_finished_write(mp); mtx_unlock(&Giant); /* VFS */ |