Index: nfs.h =================================================================== RCS file: /home/ncvs/src/sys/nfsserver/nfs.h,v retrieving revision 1.78 retrieving revision 1.81 diff -u -p -r1.78 -r1.81 --- nfs.h 17 Apr 2005 16:25:36 -0000 1.78 +++ nfs.h 24 Nov 2006 11:53:16 -0000 1.81 @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)nfs.h 8.4 (Berkeley) 5/1/95 - * $FreeBSD: src/sys/nfsserver/nfs.h,v 1.78 2005/04/17 16:25:36 rwatson Exp $ + * $FreeBSD: src/sys/nfsserver/nfs.h,v 1.81 2006/11/24 11:53:16 rwatson Exp $ */ #ifndef _NFSSERVER_NFS_H_ @@ -258,7 +258,7 @@ struct nfsrv_descript { u_int32_t nd_retxid; /* Reply xid */ struct timeval nd_starttime; /* Time RPC initiated */ fhandle_t nd_fh; /* File handle */ - struct ucred nd_cr; /* Credentials */ + struct ucred *nd_cr; /* Credentials */ }; /* Bits for "nd_flag" */ @@ -337,6 +337,7 @@ int nfs_namei(struct nameidata *, fhandl void nfsm_adj(struct mbuf *, int, int); int nfsm_mbuftouio(struct mbuf **, struct uio *, int, caddr_t *); void nfsrv_initcache(void); +void nfsrv_destroycache(void); void nfsrv_timer(void *); int nfsrv_dorec(struct nfssvc_sock *, struct nfsd *, struct nfsrv_descript **); @@ -359,6 +360,9 @@ int nfsrv_create(struct nfsrv_descript * struct thread *td, struct mbuf **mrq); int nfsrv_fhtovp(fhandle_t *, int, struct vnode **, struct ucred *, struct nfssvc_sock *, struct sockaddr *, int *, int); +int nfsrv_fhtovp_locked(fhandle_t *, int, struct vnode **, + struct ucred *, struct nfssvc_sock *, struct sockaddr *, int *, + int); int nfsrv_setpublicfs(struct mount *, struct netexport *, struct export_args *); int nfs_ispublicfh(fhandle_t *); Index: nfs_serv.c =================================================================== RCS file: /home/ncvs/src/sys/nfsserver/nfs_serv.c,v retrieving revision 1.156.2.2 retrieving revision 1.168 diff -u -p -r1.156.2.2 -r1.168 --- nfs_serv.c 13 Mar 2006 03:06:49 -0000 1.156.2.2 +++ nfs_serv.c 24 Nov 2006 11:53:16 -0000 1.168 @@ -33,7 +33,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/nfsserver/nfs_serv.c,v 1.156.2.2 2006/03/13 03:06:49 jeff Exp $"); +__FBSDID("$FreeBSD: src/sys/nfsserver/nfs_serv.c,v 1.168 2006/11/24 11:53:16 rwatson Exp $"); /* * nfs version 2 and 3 server calls to vnode ops @@ -137,11 +137,8 @@ struct nfsrvstats nfsrvstats; SYSCTL_STRUCT(_vfs_nfsrv, NFS_NFSRVSTATS, nfsrvstats, CTLFLAG_RD, &nfsrvstats, nfsrvstats, "S,nfsrvstats"); -static int nfsrv_access_withgiant(struct vnode *vp, int flags, - struct ucred *cred, int rdonly, struct thread *td, - int override); -static int nfsrv_access(struct vnode *, int, struct ucred *, int, - struct thread *, int); +static int nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, + int rdonly, struct thread *td, int override); static void nfsrvw_coalesce(struct nfsrv_descript *, struct nfsrv_descript *); @@ -170,7 +167,7 @@ nfsrv3_access(struct nfsrv_descript *nfs struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct vnode *vp = NULL; nfsfh_t nfh; fhandle_t *fhp; @@ -181,6 +178,7 @@ nfsrv3_access(struct nfsrv_descript *nfs struct vattr vattr, *vap = &vattr; u_long testmode, nfsmode; int v3 = (nfsd->nd_flag & ND_NFSV3); + int vfslocked; NFSD_LOCK_ASSERT(); @@ -190,18 +188,20 @@ nfsrv3_access(struct nfsrv_descript *nfs fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED); - error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); + NFSD_UNLOCK(); + error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, + TRUE); if (error) { + NFSD_LOCK(); nfsm_reply(NFSX_UNSIGNED); nfsm_srvpostop_attr(1, NULL); error = 0; goto nfsmout; } nfsmode = fxdr_unsigned(u_int32_t, *tl); - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); if ((nfsmode & NFSV3ACCESS_READ) && - nfsrv_access_withgiant(vp, VREAD, cred, rdonly, td, 0)) + nfsrv_access(vp, VREAD, cred, rdonly, td, 0)) nfsmode &= ~NFSV3ACCESS_READ; if (vp->v_type == VDIR) testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND | @@ -209,18 +209,18 @@ nfsrv3_access(struct nfsrv_descript *nfs else testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND); if ((nfsmode & testmode) && - nfsrv_access_withgiant(vp, VWRITE, cred, rdonly, td, 0)) + nfsrv_access(vp, VWRITE, cred, rdonly, td, 0)) nfsmode &= ~testmode; if (vp->v_type == VDIR) testmode = NFSV3ACCESS_LOOKUP; else testmode = NFSV3ACCESS_EXECUTE; if ((nfsmode & testmode) && - nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0)) + nfsrv_access(vp, VEXEC, cred, rdonly, td, 0)) nfsmode &= ~testmode; getret = VOP_GETATTR(vp, vap, cred, td); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED); @@ -231,9 +231,9 @@ nfsmout: NFSD_LOCK_ASSERT(); if (vp) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); } return(error); @@ -249,7 +249,7 @@ nfsrv_getattr(struct nfsrv_descript *nfs struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct nfs_fattr *fp; struct vattr va; struct vattr *vap = &va; @@ -259,23 +259,25 @@ nfsrv_getattr(struct nfsrv_descript *nfs caddr_t bpos; int error = 0, rdonly; struct mbuf *mb, *mreq; + int vfslocked; NFSD_LOCK_ASSERT(); nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); + NFSD_UNLOCK(); error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); if (error) { + NFSD_LOCK(); nfsm_reply(0); error = 0; goto nfsmout; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); error = VOP_GETATTR(vp, vap, cred, td); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; NFSD_LOCK(); nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3)); @@ -292,9 +294,9 @@ nfsmout: NFSD_LOCK_ASSERT(); if (vp) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); } return(error); @@ -310,7 +312,7 @@ nfsrv_setattr(struct nfsrv_descript *nfs struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct vattr va, preat; struct vattr *vap = &va; struct nfsv2_sattr *sp; @@ -325,22 +327,24 @@ nfsrv_setattr(struct nfsrv_descript *nfs struct mbuf *mb, *mreq; struct timespec guard; struct mount *mp = NULL; + int vfslocked; NFSD_LOCK_ASSERT(); nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); + NFSD_UNLOCK(); if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) { error = ESTALE; goto out; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); (void) vn_start_write(NULL, &mp, V_WAIT); - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + vfs_rel(mp); /* The write holds a ref. */ + VFS_UNLOCK_GIANT(vfslocked); VATTR_NULL(vap); + NFSD_LOCK(); if (v3) { nfsm_srvsattr(vap); tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED); @@ -379,12 +383,14 @@ nfsrv_setattr(struct nfsrv_descript *nfs fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime); } + NFSD_UNLOCK(); /* * Now that we have all the fields, lets do it. */ error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); if (error) { + NFSD_LOCK(); nfsm_reply(2 * NFSX_UNSIGNED); if (v3) nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap); @@ -396,8 +402,7 @@ nfsrv_setattr(struct nfsrv_descript *nfs * vp now an active resource, pay careful attention to cleanup */ if (v3) { - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); error = preat_ret = VOP_GETATTR(vp, &preat, cred, td); if (!error && gcheck && (preat.va_ctime.tv_sec != guard.tv_sec || @@ -405,7 +410,7 @@ nfsrv_setattr(struct nfsrv_descript *nfs error = NFSERR_NOT_SYNC; if (error) { vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; NFSD_LOCK(); nfsm_reply(NFSX_WCCDATA(v3)); @@ -414,10 +419,8 @@ nfsrv_setattr(struct nfsrv_descript *nfs error = 0; goto nfsmout; } - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + VFS_UNLOCK_GIANT(vfslocked); } - NFSD_LOCK_ASSERT(); /* * If the size is being changed write acces is required, otherwise @@ -433,28 +436,25 @@ nfsrv_setattr(struct nfsrv_descript *nfs error = EISDIR; goto out; } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly, - td, 0)) != 0) + td, 0)) != 0) goto out; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); error = VOP_SETATTR(vp, vap, cred, td); postat_ret = VOP_GETATTR(vp, vap, cred, td); - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + VFS_UNLOCK_GIANT(vfslocked); if (!error) error = postat_ret; out: - NFSD_LOCK_ASSERT(); + NFSD_UNLOCK_ASSERT(); if (vp != NULL) { - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vput(vp); - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + VFS_UNLOCK_GIANT(vfslocked); } vp = NULL; + NFSD_LOCK(); nfsm_reply(NFSX_WCCORFATTR(v3)); if (v3) { nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap); @@ -469,11 +469,11 @@ out: nfsmout: NFSD_LOCK_ASSERT(); NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); if (vp) vput(vp); vn_finished_write(mp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); return(error); } @@ -488,7 +488,7 @@ nfsrv_lookup(struct nfsrv_descript *nfsd struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct nfs_fattr *fp; struct nameidata nd, ind, *ndp = &nd; struct vnode *vp, *dirp = NULL; @@ -516,13 +516,16 @@ nfsrv_lookup(struct nfsrv_descript *nfsd nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART; error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos, &dirp, v3, &dirattr, &dirattr_ret, td, pubflag); + NFSD_UNLOCK(); /* * namei failure, only dirp to cleanup. Clear out garbarge from * structure in case macros jump to nfsmout. + * + * XXXRW: For now, use Giant unconditionally during name lookup, + * rather than deal with complexity of conditional Giant acqusition + * as moving across the name space. */ - - NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ if (error) { if (dirp) { @@ -569,6 +572,10 @@ nfsrv_lookup(struct nfsrv_descript *nfsd 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) { /* @@ -677,7 +684,7 @@ nfsrv_readlink(struct nfsrv_descript *nf struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN]; struct iovec *ivp = iv; struct mbuf *mp; @@ -691,6 +698,7 @@ nfsrv_readlink(struct nfsrv_descript *nf nfsfh_t nfh; fhandle_t *fhp; struct uio io, *uiop = &io; + int vfslocked; NFSD_LOCK_ASSERT(); @@ -701,9 +709,9 @@ nfsrv_readlink(struct nfsrv_descript *nf mp3 = NULL; fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); + NFSD_UNLOCK(); len = 0; i = 0; - NFSD_UNLOCK(); while (len < NFS_MAXPATHLEN) { MGET(nmp, M_TRYWAIT, MT_DATA); MCLGET(nmp, M_TRYWAIT); @@ -731,17 +739,16 @@ nfsrv_readlink(struct nfsrv_descript *nf uiop->uio_rw = UIO_READ; uiop->uio_segflg = UIO_SYSSPACE; uiop->uio_td = NULL; - NFSD_LOCK(); error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); if (error) { + NFSD_LOCK(); nfsm_reply(2 * NFSX_UNSIGNED); if (v3) nfsm_srvpostop_attr(1, NULL); error = 0; goto nfsmout; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); if (vp->v_type != VLNK) { if (v3) error = EINVAL; @@ -751,7 +758,7 @@ nfsrv_readlink(struct nfsrv_descript *nf error = VOP_READLINK(vp, uiop, cred); getret = VOP_GETATTR(vp, &attr, cred, td); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED); @@ -776,9 +783,9 @@ nfsmout: m_freem(mp3); if (vp) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); } return(error); @@ -794,7 +801,7 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct iovec *iv; struct iovec *iv2; struct mbuf *m; @@ -814,6 +821,7 @@ nfsrv_read(struct nfsrv_descript *nfsd, struct nfsheur *nh; off_t off; int ioflag = 0; + int vfslocked; NFSD_LOCK_ASSERT(); @@ -828,16 +836,18 @@ nfsrv_read(struct nfsrv_descript *nfsd, off = (off_t)fxdr_unsigned(u_int32_t, *tl); } nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd)); + NFSD_UNLOCK(); /* * Reference vp. If an error occurs, vp will be invalid, but we * have to NULL it just in case. The macros might goto nfsmout * as well. */ - - error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, + TRUE); if (error) { vp = NULL; + NFSD_LOCK(); nfsm_reply(2 * NFSX_UNSIGNED); if (v3) nfsm_srvpostop_attr(1, NULL); @@ -851,20 +861,18 @@ nfsrv_read(struct nfsrv_descript *nfsd, else error = (vp->v_type == VDIR) ? EISDIR : EACCES; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); if (!error) { - if ((error = nfsrv_access_withgiant(vp, VREAD, cred, rdonly, - td, 1)) != 0) - error = nfsrv_access_withgiant(vp, VEXEC, cred, - rdonly, td, 1); + if ((error = nfsrv_access(vp, VREAD, cred, rdonly, td, 1)) + != 0) + error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 1); } getret = VOP_GETATTR(vp, vap, cred, td); if (!error) error = getret; if (error) { vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(v3)); @@ -873,8 +881,7 @@ nfsrv_read(struct nfsrv_descript *nfsd, error = 0; goto nfsmout; } - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + VFS_UNLOCK_GIANT(vfslocked); /* * Calculate byte count to read @@ -887,6 +894,7 @@ nfsrv_read(struct nfsrv_descript *nfsd, else cnt = reqlen; + NFSD_LOCK(); /* * Calculate seqcount for heuristic */ @@ -953,8 +961,8 @@ nfsrv_read(struct nfsrv_descript *nfsd, fp = (struct nfs_fattr *)tl; tl += (NFSX_V2FATTR / sizeof (u_int32_t)); } - len = left = nfsm_rndup(cnt); NFSD_UNLOCK(); + len = left = nfsm_rndup(cnt); if (cnt > 0) { /* * Generate the mbuf list with the uio_iov ref. to it. @@ -1000,7 +1008,7 @@ nfsrv_read(struct nfsrv_descript *nfsd, uiop->uio_resid = len; uiop->uio_rw = UIO_READ; uiop->uio_segflg = UIO_SYSSPACE; - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred); off = uiop->uio_offset; nh->nh_nextr = off; @@ -1010,7 +1018,7 @@ nfsrv_read(struct nfsrv_descript *nfsd, error = getret; m_freem(mreq); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); vp = NULL; nfsm_reply(NFSX_POSTOPATTR(v3)); @@ -1021,11 +1029,11 @@ nfsrv_read(struct nfsrv_descript *nfsd, } } else { uiop->uio_resid = 0; - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); } - mtx_assert(&Giant, MA_OWNED); /* VFS */ + VFS_ASSERT_GIANT(vp->v_mount); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; NFSD_LOCK(); nfsm_srvfillattr(vap, fp); @@ -1046,9 +1054,9 @@ nfsmout: NFSD_LOCK_ASSERT(); if (vp) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); } return(error); @@ -1064,7 +1072,7 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct iovec *ivp; int i, cnt; struct mbuf *mp; @@ -1085,6 +1093,7 @@ nfsrv_write(struct nfsrv_descript *nfsd, struct uio io, *uiop = &io; off_t off; struct mount *mntp = NULL; + int vfslocked; NFSD_LOCK_ASSERT(); @@ -1096,22 +1105,27 @@ nfsrv_write(struct nfsrv_descript *nfsd, } fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); + NFSD_UNLOCK(); if ((mntp = vfs_getvfs(&fhp->fh_fsid)) == NULL) { error = ESTALE; + NFSD_LOCK(); goto ereply; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mntp); (void) vn_start_write(NULL, &mntp, V_WAIT); - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + vfs_rel(mntp); /* The write holds a ref. */ + VFS_UNLOCK_GIANT(vfslocked); if (v3) { + NFSD_LOCK(); tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED); + NFSD_UNLOCK(); off = fxdr_hyper(tl); tl += 3; stable = fxdr_unsigned(int, *tl++); } else { + NFSD_LOCK(); tl = nfsm_dissect_nonblock(u_int32_t *, 4 * NFSX_UNSIGNED); + NFSD_UNLOCK(); off = (off_t)fxdr_unsigned(u_int32_t, *++tl); tl += 2; if (nfs_async) @@ -1152,15 +1166,18 @@ nfsrv_write(struct nfsrv_descript *nfsd, } if (len > NFS_MAXDATA || len < 0 || i < len) { error = EIO; + NFSD_LOCK(); nfsm_reply(2 * NFSX_UNSIGNED); if (v3) nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap); error = 0; goto nfsmout; } - error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); + error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, + TRUE); if (error) { vp = NULL; + NFSD_LOCK(); nfsm_reply(2 * NFSX_UNSIGNED); if (v3) nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap); @@ -1168,11 +1185,9 @@ nfsrv_write(struct nfsrv_descript *nfsd, goto nfsmout; } if (v3) { - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); forat_ret = VOP_GETATTR(vp, &forat, cred, td); - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + VFS_UNLOCK_GIANT(vfslocked); } if (vp->v_type != VREG) { if (v3) @@ -1180,15 +1195,17 @@ nfsrv_write(struct nfsrv_descript *nfsd, else error = (vp->v_type == VDIR) ? EISDIR : EACCES; } - if (!error) + if (!error) { + vfslocked = VFS_LOCK_GIANT(vp->v_mount); error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1); + VFS_UNLOCK_GIANT(vfslocked); + } if (error) { - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vput(vp); - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; + NFSD_LOCK(); nfsm_reply(NFSX_WCCDATA(v3)); if (v3) nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap); @@ -1196,7 +1213,6 @@ nfsrv_write(struct nfsrv_descript *nfsd, goto nfsmout; } - NFSD_UNLOCK(); if (len > 0) { MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP, M_WAITOK); @@ -1230,21 +1246,21 @@ nfsrv_write(struct nfsrv_descript *nfsd, uiop->uio_segflg = UIO_SYSSPACE; uiop->uio_td = NULL; uiop->uio_offset = off; - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); error = VOP_WRITE(vp, uiop, ioflags, cred); /* XXXRW: unlocked write. */ nfsrvstats.srvvop_writes++; FREE((caddr_t)iv, M_TEMP); } else - mtx_lock(&Giant); /* VFS */ - mtx_assert(&Giant, MA_OWNED); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); + VFS_ASSERT_GIANT(vp->v_mount); aftat_ret = VOP_GETATTR(vp, vap, cred, td); vput(vp); - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; if (!error) error = aftat_ret; + NFSD_LOCK(); ereply: NFSD_LOCK_ASSERT(); nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) + @@ -1282,11 +1298,11 @@ ereply: nfsmout: NFSD_LOCK_ASSERT(); NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mntp); if (vp) vput(vp); vn_finished_write(mntp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); return(error); } @@ -1302,6 +1318,8 @@ nfsrv_samecred(struct ucred *cr1, struct { int i; + NFSD_LOCK_DONTCARE(); + if (cr1->cr_uid != cr2->cr_uid) return (0); if (cr1->cr_ngroups != cr2->cr_ngroups) @@ -1342,6 +1360,7 @@ nfsrv_writegather(struct nfsrv_descript struct uio io, *uiop = &io; u_quad_t cur_usec; struct mount *mntp = NULL; + int vfslocked; NFSD_LOCK_ASSERT(); @@ -1357,7 +1376,7 @@ nfsrv_writegather(struct nfsrv_descript mrep = nfsd->nd_mrep; md = nfsd->nd_md; dpos = nfsd->nd_dpos; - cred = &nfsd->nd_cr; + cred = nfsd->nd_cr; v3 = (nfsd->nd_flag & ND_NFSV3); LIST_INIT(&nfsd->nd_coalesce); nfsd->nd_mreq = NULL; @@ -1464,7 +1483,7 @@ nfsmout: */ for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) { wp = LIST_NEXT(nfsd, nd_hash); - if (nfsrv_samecred(&owp->nd_cr, &nfsd->nd_cr)) + if (nfsrv_samecred(owp->nd_cr, nfsd->nd_cr)) nfsrvw_coalesce(owp, nfsd); } } else { @@ -1493,18 +1512,17 @@ loop1: splx(s); mrep = nfsd->nd_mrep; nfsd->nd_mrep = NULL; - cred = &nfsd->nd_cr; + cred = nfsd->nd_cr; v3 = (nfsd->nd_flag & ND_NFSV3); + NFSD_UNLOCK(); forat_ret = aftat_ret = 1; error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp, nfsd->nd_nam, &rdonly, TRUE); if (!error) { if (v3) { - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); forat_ret = VOP_GETATTR(vp, &forat, cred, td); - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + VFS_UNLOCK_GIANT(vfslocked); } if (vp->v_type != VREG) { if (v3) @@ -1515,11 +1533,9 @@ loop1: } else { vp = NULL; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); if (!error) - error = nfsrv_access_withgiant(vp, VWRITE, cred, rdonly, - td, 1); + error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1); if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE) ioflags = IO_NODELOCKED; else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC) @@ -1573,13 +1589,13 @@ loop1: vput(vp); vp = NULL; } - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + VFS_UNLOCK_GIANT(vfslocked); /* * Loop around generating replies for all write rpcs that have * now been completed. */ + NFSD_LOCK(); swp = nfsd; do { NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff)); @@ -1642,6 +1658,7 @@ loop1: * Search for a reply to return. */ s = splsoftclock(); + NFSD_LOCK_ASSERT(); LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq) if (nfsd->nd_mreq) { NFS_DPF(WG, ("X%03x", nfsd->nd_retxid & 0xfff)); @@ -1718,7 +1735,7 @@ nfsrv_create(struct nfsrv_descript *nfsd struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct nfs_fattr *fp; struct vattr va, dirfor, diraft; struct vattr *vap = &va; @@ -1736,6 +1753,7 @@ nfsrv_create(struct nfsrv_descript *nfsd u_quad_t tempsize; u_char cverf[NFSX_V3CREATEVERF]; struct mount *mp = NULL; + int vfslocked; NFSD_LOCK_ASSERT(); @@ -1747,14 +1765,16 @@ nfsrv_create(struct nfsrv_descript *nfsd fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); + NFSD_UNLOCK(); if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) { error = ESTALE; + NFSD_LOCK(); goto ereply_locked; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); (void) vn_start_write(NULL, &mp, V_WAIT); - mtx_unlock(&Giant); /* VFS */ + vfs_rel(mp); /* The write holds a ref. */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); nfsm_srvnamesiz(len); @@ -1775,9 +1795,9 @@ nfsrv_create(struct nfsrv_descript *nfsd &dirp, v3, &dirfor, &dirfor_ret, td, FALSE); if (dirp && !v3) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(dirp->v_mount); vrele(dirp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); dirp = NULL; } @@ -1822,10 +1842,12 @@ nfsrv_create(struct nfsrv_descript *nfsd exclusive_flag = 1; break; }; + NFSD_UNLOCK(); vap->va_type = VREG; } else { sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR); vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode)); + NFSD_UNLOCK(); if (vap->va_type == VNON) vap->va_type = VREG; vap->va_mode = nfstov_mode(sp->sa_mode); @@ -1852,8 +1874,11 @@ nfsrv_create(struct nfsrv_descript *nfsd * * The only possible error we can have at this point is EEXIST. * nd.ni_vp will also be non-NULL in that case. + * + * XXXRW: For now acquire Giant unconditionally during create to + * avoid interactions between Giant for ndvp and Giant for vp if it + * already exists. */ - NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ if (nd.ni_vp == NULL) { if (vap->va_mode == (mode_t)VNOVAL) @@ -1915,6 +1940,10 @@ nfsrv_create(struct nfsrv_descript *nfsd 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; @@ -1927,8 +1956,8 @@ nfsrv_create(struct nfsrv_descript *nfsd } } else { if (vap->va_size != -1) { - error = nfsrv_access_withgiant(nd.ni_vp, VWRITE, - cred, (nd.ni_cnd.cn_flags & RDONLY), td, 0); + error = nfsrv_access(nd.ni_vp, VWRITE, cred, + (nd.ni_cnd.cn_flags & RDONLY), td, 0); if (!error) { tempsize = vap->va_size; VATTR_NULL(vap); @@ -2026,7 +2055,7 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct vattr va, dirfor, diraft; struct vattr *vap = &va; u_int32_t *tl; @@ -2041,6 +2070,7 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, fhandle_t *fhp; struct mount *mp = NULL; int v3 = (nfsd->nd_flag & ND_NFSV3); + int vfslocked; NFSD_LOCK_ASSERT(); @@ -2051,14 +2081,16 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); + NFSD_UNLOCK(); if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) { error = ESTALE; + NFSD_LOCK(); goto ereply; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); (void) vn_start_write(NULL, &mp, V_WAIT); - mtx_unlock(&Giant); /* VFS */ + vfs_rel(mp); /* The write holds a ref. */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); nfsm_srvnamesiz(len); @@ -2080,12 +2112,17 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, error = 0; goto nfsmout; } + + /* + * XXXRW: For now, acquire Giant unconditionally to avoid complexity + * of dealing with Giant separately for dvp and vp. + */ 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; + mtx_lock(&Giant); /* VFS */ goto out; } VATTR_NULL(vap); @@ -2102,8 +2139,8 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, */ if (nd.ni_vp) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ error = EEXIST; + mtx_lock(&Giant); /* VFS */ goto out; } vap->va_type = vtyp; @@ -2141,6 +2178,10 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, 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; @@ -2152,6 +2193,7 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, * send response, cleanup, return. */ out: + GIANT_REQUIRED; NFSD_UNLOCK_ASSERT(); vp = nd.ni_vp; if (!error) { @@ -2196,9 +2238,9 @@ ereply: nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); } NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); vn_finished_write(mp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); return (0); nfsmout: @@ -2234,7 +2276,7 @@ nfsrv_remove(struct nfsrv_descript *nfsd struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct nameidata nd; caddr_t bpos; int error = 0, len, dirfor_ret = 1, diraft_ret = 1; @@ -2245,6 +2287,7 @@ nfsrv_remove(struct nfsrv_descript *nfsd nfsfh_t nfh; fhandle_t *fhp; struct mount *mp = NULL; + int vfslocked; NFSD_LOCK_ASSERT(); @@ -2253,14 +2296,16 @@ nfsrv_remove(struct nfsrv_descript *nfsd fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); + NFSD_UNLOCK(); if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) { error = ESTALE; + NFSD_LOCK(); goto ereply; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); (void) vn_start_write(NULL, &mp, V_WAIT); - mtx_unlock(&Giant); /* VFS */ + vfs_rel(mp); /* The write holds a ref. */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); nfsm_srvnamesiz(len); @@ -2355,7 +2400,7 @@ nfsrv_rename(struct nfsrv_descript *nfsd struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; caddr_t bpos; int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1; int tdirfor_ret = 1, tdiraft_ret = 1; @@ -2369,6 +2414,7 @@ nfsrv_rename(struct nfsrv_descript *nfsd fhandle_t *ffhp, *tfhp; uid_t saved_uid; struct mount *mp = NULL; + int vfslocked; NFSD_LOCK_ASSERT(); @@ -2387,14 +2433,16 @@ nfsrv_rename(struct nfsrv_descript *nfsd ndclear(&tond); nfsm_srvmtofh(ffhp); + NFSD_UNLOCK(); if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL) { error = ESTALE; + NFSD_LOCK(); goto out1; } - NFSD_UNLOCK(); - mtx_lock(&Giant); + vfslocked = VFS_LOCK_GIANT(mp); (void) vn_start_write(NULL, &mp, V_WAIT); - mtx_unlock(&Giant); + vfs_rel(mp); /* The write holds a ref. */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); nfsm_srvnamesiz(len); /* @@ -2409,9 +2457,9 @@ nfsrv_rename(struct nfsrv_descript *nfsd &dpos, &fdirp, v3, &fdirfor, &fdirfor_ret, td, FALSE); if (fdirp && !v3) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(fdirp->v_mount); vrele(fdirp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); fdirp = NULL; } @@ -2500,6 +2548,7 @@ nfsrv_rename(struct nfsrv_descript *nfsd fromnd.ni_cnd.cn_namelen)) error = -1; out: + GIANT_REQUIRED; NFSD_UNLOCK_ASSERT(); if (!error) { /* @@ -2514,8 +2563,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) @@ -2610,7 +2659,7 @@ nfsrv_link(struct nfsrv_descript *nfsd, struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct nameidata nd; caddr_t bpos; int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1; @@ -2621,6 +2670,7 @@ nfsrv_link(struct nfsrv_descript *nfsd, nfsfh_t nfh, dnfh; fhandle_t *fhp, *dfhp; struct mount *mp = NULL; + int vfslocked; NFSD_LOCK_ASSERT(); @@ -2635,14 +2685,16 @@ nfsrv_link(struct nfsrv_descript *nfsd, goto ereply; } NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); (void) vn_start_write(NULL, &mp, V_WAIT); - mtx_unlock(&Giant); /* VFS */ + vfs_rel(mp); /* The write holds a ref. */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); nfsm_srvmtofh(dfhp); nfsm_srvnamesiz(len); - error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, slp, nam, &rdonly, TRUE); + error = nfsrv_fhtovp_locked(fhp, TRUE, &vp, cred, slp, nam, &rdonly, + TRUE); if (error) { nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); if (v3) { @@ -2769,7 +2821,7 @@ nfsrv_symlink(struct nfsrv_descript *nfs struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct vattr va, dirfor, diraft; struct nameidata nd; struct vattr *vap = &va; @@ -2784,12 +2836,18 @@ nfsrv_symlink(struct nfsrv_descript *nfs nfsfh_t nfh; fhandle_t *fhp; struct mount *mp = NULL; + int vfslocked; NFSD_LOCK_ASSERT(); nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); ndclear(&nd); + /* + * XXXRW: For now, unconditionally acquire Giant in several places to + * avoid complexity of unwinding separately when several vnodes are + * in flight. + */ fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) { @@ -2799,9 +2857,10 @@ nfsrv_symlink(struct nfsrv_descript *nfs goto out; } NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); (void) vn_start_write(NULL, &mp, V_WAIT); - mtx_unlock(&Giant); /* VFS */ + vfs_rel(mp); /* The write holds a ref. */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); nfsm_srvnamesiz(len); nd.ni_cnd.cn_cred = cred; @@ -2809,6 +2868,12 @@ nfsrv_symlink(struct nfsrv_descript *nfs 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) { @@ -2817,11 +2882,6 @@ nfsrv_symlink(struct nfsrv_descript *nfs } 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; @@ -2878,6 +2938,10 @@ nfsrv_symlink(struct nfsrv_descript *nfs 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)); @@ -2959,7 +3023,7 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct vattr va, dirfor, diraft; struct vattr *vap = &va; struct nfs_fattr *fp; @@ -2974,12 +3038,17 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, nfsfh_t nfh; fhandle_t *fhp; struct mount *mp = NULL; + int vfslocked; NFSD_LOCK_ASSERT(); nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); ndclear(&nd); + /* + * XXXRW: For now, unconditionally acquire Giant so as to avoid the + * complexity of tracking it for several in-flight vnodes. + */ fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) { @@ -2989,9 +3058,10 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, goto out; } NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); (void) vn_start_write(NULL, &mp, V_WAIT); - mtx_unlock(&Giant); /* VFS */ + vfs_rel(mp); /* The write holds a ref. */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); nfsm_srvnamesiz(len); nd.ni_cnd.cn_cred = cred; @@ -3002,9 +3072,9 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, &dirp, v3, &dirfor, &dirfor_ret, td, FALSE); if (dirp && !v3) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(dirp->v_mount); vrele(dirp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); dirp = NULL; } @@ -3138,7 +3208,7 @@ nfsrv_rmdir(struct nfsrv_descript *nfsd, struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; caddr_t bpos; int error = 0, len, dirfor_ret = 1, diraft_ret = 1; int v3 = (nfsd->nd_flag & ND_NFSV3); @@ -3149,6 +3219,7 @@ nfsrv_rmdir(struct nfsrv_descript *nfsd, fhandle_t *fhp; struct nameidata nd; struct mount *mp = NULL; + int vfslocked; NFSD_LOCK_ASSERT(); @@ -3162,9 +3233,10 @@ nfsrv_rmdir(struct nfsrv_descript *nfsd, goto out; } NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); (void) vn_start_write(NULL, &mp, V_WAIT); - mtx_unlock(&Giant); /* VFS */ + vfs_rel(mp); /* The write holds a ref. */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); nfsm_srvnamesiz(len); nd.ni_cnd.cn_cred = cred; @@ -3174,9 +3246,9 @@ nfsrv_rmdir(struct nfsrv_descript *nfsd, &dirp, v3, &dirfor, &dirfor_ret, td, FALSE); if (dirp && !v3) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(dirp->v_mount); vrele(dirp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); dirp = NULL; } @@ -3208,6 +3280,9 @@ out: /* * Issue or abort op. Since SAVESTART is not set, path name * component is freed by the VOP after either. + * + * XXXRW: For now, acquire Giant unconditionally to avoid the + * complexity of unwinding Giant for several vnodes in flight. */ NFSD_LOCK_ASSERT(); NFSD_UNLOCK(); @@ -3311,7 +3386,7 @@ nfsrv_readdir(struct nfsrv_descript *nfs struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; char *bp, *be; struct mbuf *mp; struct dirent *dp; @@ -3331,6 +3406,7 @@ nfsrv_readdir(struct nfsrv_descript *nfs int v3 = (nfsd->nd_flag & ND_NFSV3); u_quad_t off, toff, verf; u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ + int vfslocked; NFSD_LOCK_ASSERT(); @@ -3348,6 +3424,7 @@ nfsrv_readdir(struct nfsrv_descript *nfs toff = fxdr_unsigned(u_quad_t, *tl++); verf = 0; /* shut up gcc */ } + NFSD_UNLOCK(); off = toff; cnt = fxdr_unsigned(int, *tl); siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); @@ -3360,14 +3437,13 @@ nfsrv_readdir(struct nfsrv_descript *nfs error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); if (!error && vp->v_type != VDIR) { error = ENOTDIR; - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vput(vp); - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; } if (error) { + NFSD_LOCK(); nfsm_reply(NFSX_UNSIGNED); if (v3) nfsm_srvpostop_attr(getret, &at); @@ -3378,8 +3454,7 @@ nfsrv_readdir(struct nfsrv_descript *nfs /* * Obtain lock on vnode for this section of the code */ - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); if (v3) { error = getret = VOP_GETATTR(vp, &at, cred, td); #if 0 @@ -3391,10 +3466,10 @@ nfsrv_readdir(struct nfsrv_descript *nfs #endif } if (!error) - error = nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0); + error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0); if (error) { vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); vp = NULL; nfsm_reply(NFSX_POSTOPATTR(v3)); @@ -3438,7 +3513,7 @@ again: VOP_UNLOCK(vp, 0, td); if (error) { vrele(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; free((caddr_t)rbuf, M_TEMP); if (cookies) @@ -3459,7 +3534,7 @@ again: */ if (siz == 0) { vrele(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + @@ -3509,7 +3584,7 @@ again: goto again; } - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */ nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz); @@ -3588,9 +3663,9 @@ again: ncookies--; } NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vrele(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); vp = NULL; nfsm_clget; @@ -3614,9 +3689,9 @@ nfsmout: NFSD_LOCK_ASSERT(); if (vp) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vrele(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); } return(error); @@ -3629,7 +3704,7 @@ nfsrv_readdirplus(struct nfsrv_descript struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; char *bp, *be; struct mbuf *mp; struct dirent *dp; @@ -3651,6 +3726,7 @@ nfsrv_readdirplus(struct nfsrv_descript u_quad_t off, toff, verf; u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ int v3 = (nfsd->nd_flag & ND_NFSV3); + int vfslocked; NFSD_LOCK_ASSERT(); @@ -3669,6 +3745,7 @@ nfsrv_readdirplus(struct nfsrv_descript off = toff; siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); xfer = NFS_SRVMAXDATA(nfsd); + NFSD_UNLOCK(); if (cnt > xfer) cnt = xfer; if (siz > xfer) @@ -3677,21 +3754,19 @@ nfsrv_readdirplus(struct nfsrv_descript error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); if (!error && vp->v_type != VDIR) { error = ENOTDIR; - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; - NFSD_LOCK(); } if (error) { + NFSD_LOCK(); nfsm_reply(NFSX_UNSIGNED); nfsm_srvpostop_attr(getret, &at); error = 0; goto nfsmout; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); error = getret = VOP_GETATTR(vp, &at, cred, td); #if 0 /* @@ -3701,10 +3776,10 @@ nfsrv_readdirplus(struct nfsrv_descript error = NFSERR_BAD_COOKIE; #endif if (!error) - error = nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0); + error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0); if (error) { vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); vp = NULL; nfsm_reply(NFSX_V3POSTOPATTR); @@ -3741,7 +3816,7 @@ again: error = getret; if (error) { vrele(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; if (cookies) free((caddr_t)cookies, M_TEMP); @@ -3761,7 +3836,7 @@ again: */ if (siz == 0) { vrele(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); vp = NULL; nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + @@ -3816,7 +3891,7 @@ again: EOPNOTSUPP) { error = NFSERR_NOTSUPP; vrele(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; free((caddr_t)cookies, M_TEMP); free((caddr_t)rbuf, M_TEMP); @@ -3827,7 +3902,7 @@ again: goto nfsmout; } vput(nvp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); nvp = NULL; dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + @@ -3842,7 +3917,7 @@ again: be = bp + M_TRAILINGSPACE(mp); NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + VFS_LOCK_GIANT(vp->v_mount); /* Loop through the records and build reply */ while (cpos < cend && ncookies > 0) { if (dp->d_fileno != 0 && dp->d_type != DT_WHT) { @@ -3859,6 +3934,13 @@ again: bzero((caddr_t)nfhp, NFSX_V3FH); nfhp->fh_fsid = nvp->v_mount->mnt_stat.f_fsid; + /* + * XXXRW: Assert the mountpoints are the same so that + * we know that acquiring Giant based on the + * directory is the right thing for the child. + */ + KASSERT(nvp->v_mount == vp->v_mount, + ("nfsrv_readdirplus: nvp mount != vp mount")); if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) { vput(nvp); nvp = NULL; @@ -3956,7 +4038,7 @@ invalid: ncookies--; } vrele(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; nfsm_clget_nolock; *tl = nfsrv_nfs_false; @@ -3979,9 +4061,9 @@ nfsmout: NFSD_LOCK_ASSERT(); if (vp) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vrele(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); } return(error); @@ -3997,7 +4079,7 @@ nfsrv_commit(struct nfsrv_descript *nfsd struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct vattr bfor, aft; struct vnode *vp = NULL; nfsfh_t nfh; @@ -4009,6 +4091,7 @@ nfsrv_commit(struct nfsrv_descript *nfsd u_quad_t off; struct mount *mp = NULL; int v3 = (nfsd->nd_flag & ND_NFSV3); + int vfslocked; NFSD_LOCK_ASSERT(); @@ -4022,10 +4105,10 @@ nfsrv_commit(struct nfsrv_descript *nfsd goto ereply; } NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); (void) vn_start_write(NULL, &mp, V_WAIT); - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + vfs_rel(mp); /* The write holds a ref. */ + VFS_UNLOCK_GIANT(vfslocked); tl = nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED); /* @@ -4037,13 +4120,13 @@ nfsrv_commit(struct nfsrv_descript *nfsd cnt = fxdr_unsigned(int, *tl); error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); if (error) { + NFSD_LOCK(); nfsm_reply(2 * NFSX_UNSIGNED); nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); error = 0; goto nfsmout; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); for_ret = VOP_GETATTR(vp, &bfor, cred, td); if (cnt > MAX_COMMIT_COUNT) { @@ -4131,7 +4214,7 @@ nfsrv_commit(struct nfsrv_descript *nfsd aft_ret = VOP_GETATTR(vp, &aft, cred, td); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; NFSD_LOCK(); ereply: @@ -4150,11 +4233,11 @@ ereply: nfsmout: NFSD_LOCK_ASSERT(); NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); if (vp) vput(vp); vn_finished_write(mp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); return(error); } @@ -4169,7 +4252,7 @@ nfsrv_statfs(struct nfsrv_descript *nfsd struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct statfs *sf; struct nfs_statfs *sfp; caddr_t bpos; @@ -4182,14 +4265,17 @@ nfsrv_statfs(struct nfsrv_descript *nfsd fhandle_t *fhp; struct statfs statfs; u_quad_t tval; + int vfslocked; NFSD_LOCK_ASSERT(); + NFSD_UNLOCK(); nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); if (error) { + NFSD_LOCK(); nfsm_reply(NFSX_UNSIGNED); if (v3) nfsm_srvpostop_attr(getret, &at); @@ -4197,12 +4283,11 @@ nfsrv_statfs(struct nfsrv_descript *nfsd goto nfsmout; } sf = &statfs; - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); error = VFS_STATFS(vp->v_mount, sf, td); getret = VOP_GETATTR(vp, &at, cred, td); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; NFSD_LOCK(); nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3)); @@ -4253,9 +4338,9 @@ nfsmout: NFSD_LOCK_ASSERT(); if (vp) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); } return(error); @@ -4271,7 +4356,7 @@ nfsrv_fsinfo(struct nfsrv_descript *nfsd struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct nfsv3_fsinfo *sip; caddr_t bpos; int error = 0, rdonly, getret = 1, pref; @@ -4283,8 +4368,10 @@ nfsrv_fsinfo(struct nfsrv_descript *nfsd u_quad_t maxfsize; struct statfs sb; int v3 = (nfsd->nd_flag & ND_NFSV3); + int vfslocked; NFSD_LOCK_ASSERT(); + NFSD_UNLOCK(); nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); if (!v3) @@ -4293,21 +4380,21 @@ nfsrv_fsinfo(struct nfsrv_descript *nfsd nfsm_srvmtofh(fhp); error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); if (error) { + NFSD_LOCK(); nfsm_reply(NFSX_UNSIGNED); nfsm_srvpostop_attr(getret, &at); error = 0; goto nfsmout; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); /* XXX Try to make a guess on the max file size. */ VFS_STATFS(vp->v_mount, &sb, td); maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1; getret = VOP_GETATTR(vp, &at, cred, td); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; NFSD_LOCK(); nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO); @@ -4340,9 +4427,9 @@ nfsmout: NFSD_LOCK_ASSERT(); if (vp) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); } return(error); @@ -4358,7 +4445,7 @@ nfsrv_pathconf(struct nfsrv_descript *nf struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; struct sockaddr *nam = nfsd->nd_nam; caddr_t dpos = nfsd->nd_dpos; - struct ucred *cred = &nfsd->nd_cr; + struct ucred *cred = nfsd->nd_cr; struct nfsv3_pathconf *pc; caddr_t bpos; int error = 0, rdonly, getret = 1; @@ -4369,8 +4456,10 @@ nfsrv_pathconf(struct nfsrv_descript *nf nfsfh_t nfh; fhandle_t *fhp; int v3 = (nfsd->nd_flag & ND_NFSV3); + int vfslocked; NFSD_LOCK_ASSERT(); + NFSD_UNLOCK(); nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); if (!v3) @@ -4379,13 +4468,13 @@ nfsrv_pathconf(struct nfsrv_descript *nf nfsm_srvmtofh(fhp); error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE); if (error) { + NFSD_LOCK(); nfsm_reply(NFSX_UNSIGNED); nfsm_srvpostop_attr(getret, &at); error = 0; goto nfsmout; } - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax); if (!error) error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax); @@ -4395,7 +4484,7 @@ nfsrv_pathconf(struct nfsrv_descript *nf error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc); getret = VOP_GETATTR(vp, &at, cred, td); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); vp = NULL; NFSD_LOCK(); nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF); @@ -4422,9 +4511,9 @@ nfsmout: NFSD_LOCK_ASSERT(); if (vp) { NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(vp->v_mount); vput(vp); - mtx_unlock(&Giant); /* VFS */ + VFS_UNLOCK_GIANT(vfslocked); NFSD_LOCK(); } return(error); @@ -4494,19 +4583,24 @@ nfsmout: * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS() * will return EPERM instead of EACCESS. EPERM is always an error. * - * There are two versions: one to be called while holding Giant (which is - * needed due to use of VFS), and the other called with the NFS server lock - * (which will be dropped and reacquired). This is necessary because - * nfsrv_access checks are required from both classes of contexts. + * There are two versions: one called while holding the NFS server lock, + * which will be dropped and re-acquired, and one called without it. + * + * nfsrv_access() assumes that the NFS server lock is not held, but that if + * Giant is required for the vnode it will already be acquired. + * + * nfsrv_access_locked() assumes that the NFS server lock is held, but that + * it will need to acquire Giant for the vnode. */ static int -nfsrv_access_withgiant(struct vnode *vp, int flags, struct ucred *cred, +nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly, struct thread *td, int override) { struct vattr vattr; int error; - GIANT_REQUIRED; + NFSD_UNLOCK_ASSERT(); + VFS_ASSERT_GIANT(vp->v_mount); nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); @@ -4547,19 +4641,3 @@ nfsrv_access_withgiant(struct vnode *vp, error = 0; return (error); } - -static int -nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly, - struct thread *td, int override) -{ - int error; - - NFSD_LOCK_ASSERT(); - - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ - error = nfsrv_access_withgiant(vp, flags, cred, rdonly, td, override); - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); - return (error); -} Index: nfs_srvcache.c =================================================================== RCS file: /home/ncvs/src/sys/nfsserver/nfs_srvcache.c,v retrieving revision 1.40 retrieving revision 1.43 diff -u -p -r1.40 -r1.43 --- nfs_srvcache.c 7 Jan 2005 01:45:51 -0000 1.40 +++ nfs_srvcache.c 1 Aug 2006 16:27:14 -0000 1.43 @@ -33,7 +33,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/nfsserver/nfs_srvcache.c,v 1.40 2005/01/07 01:45:51 imp Exp $"); +__FBSDID("$FreeBSD: src/sys/nfsserver/nfs_srvcache.c,v 1.43 2006/08/01 16:27:14 jhb Exp $"); /* * Reference: Chet Juszczak, "Improving the Performance and Correctness @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD: src/sys/nfsserver/nf #include #include #include /* for sodupsockaddr */ +#include #include #include @@ -57,13 +58,14 @@ __FBSDID("$FreeBSD: src/sys/nfsserver/nf #include static long numnfsrvcache; -static long desirednfsrvcache = NFSRVCACHESIZ; +static long desirednfsrvcache; #define NFSRCHASH(xid) \ (&nfsrvhashtbl[((xid) + ((xid) >> 24)) & nfsrvhash]) static LIST_HEAD(nfsrvhash, nfsrvcache) *nfsrvhashtbl; static TAILQ_HEAD(nfsrvlru, nfsrvcache) nfsrvlruhead; static u_long nfsrvhash; +static eventhandler_tag nfsrv_nmbclusters_tag; #define TRUE 1 #define FALSE 0 @@ -122,15 +124,43 @@ static const int nfsv2_repstat[NFS_NPROC FALSE, }; +/* + * Size the NFS server's duplicate request cache at 1/2 the nmbclsters, floating + * within a (64, 2048) range. This is to prevent all mbuf clusters being tied up + * in the NFS dupreq cache for small values of nmbclusters. + */ +static void +nfsrvcache_size_change(void *tag) +{ + desirednfsrvcache = nmbclusters /2; + if (desirednfsrvcache > NFSRVCACHE_MAX_SIZE) + desirednfsrvcache = NFSRVCACHE_MAX_SIZE; + if (desirednfsrvcache < NFSRVCACHE_MIN_SIZE) + desirednfsrvcache = NFSRVCACHE_MIN_SIZE; +} + /* * Initialize the server request cache list */ void nfsrv_initcache(void) { - + nfsrvcache_size_change(NULL); nfsrvhashtbl = hashinit(desirednfsrvcache, M_NFSD, &nfsrvhash); TAILQ_INIT(&nfsrvlruhead); + nfsrv_nmbclusters_tag = EVENTHANDLER_REGISTER(nmbclusters_change, + nfsrvcache_size_change, NULL, EVENTHANDLER_PRI_FIRST); +} + +/* + * Teardown the server request cache list + */ +void +nfsrv_destroycache(void) +{ + KASSERT(TAILQ_EMPTY(&nfsrvlruhead), ("%s: pending requests", __func__)); + EVENTHANDLER_DEREGISTER(nmbclusters_change, nfsrv_nmbclusters_tag); + hashdestroy(nfsrvhashtbl, M_NFSD, nfsrvhash); } /* @@ -342,8 +372,7 @@ nfsrv_cleancache(void) NFSD_LOCK_ASSERT(); - for (rp = TAILQ_FIRST(&nfsrvlruhead); rp != 0; rp = nextrp) { - nextrp = TAILQ_NEXT(rp, rc_lru); + TAILQ_FOREACH_SAFE(rp, &nfsrvlruhead, rc_lru, nextrp) { LIST_REMOVE(rp, rc_hash); TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru); if (rp->rc_flag & RC_REPMBUF) Index: nfs_srvsock.c =================================================================== RCS file: /home/ncvs/src/sys/nfsserver/nfs_srvsock.c,v retrieving revision 1.94.2.1 retrieving revision 1.101 diff -u -p -r1.94.2.1 -r1.101 --- nfs_srvsock.c 1 Mar 2006 14:18:10 -0000 1.94.2.1 +++ nfs_srvsock.c 22 Oct 2006 11:52:17 -0000 1.101 @@ -33,12 +33,14 @@ */ #include -__FBSDID("$FreeBSD: src/sys/nfsserver/nfs_srvsock.c,v 1.94.2.1 2006/03/01 14:18:10 simon Exp $"); +__FBSDID("$FreeBSD: src/sys/nfsserver/nfs_srvsock.c,v 1.101 2006/10/22 11:52:17 rwatson Exp $"); /* * Socket operations for use by nfs */ +#include "opt_mac.h" + #include #include #include @@ -49,6 +51,7 @@ __FBSDID("$FreeBSD: src/sys/nfsserver/nf #include #include #include +#include #include #include #include @@ -65,6 +68,8 @@ __FBSDID("$FreeBSD: src/sys/nfsserver/nf #include #include +#include + #define TRUE 1 #define FALSE 0 @@ -361,17 +366,13 @@ nfs_getreq(struct nfsrv_descript *nd, st } nfsm_adv(nfsm_rndup(len)); tl = nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED); - /* - * XXX: This credential should be managed using crget(9) - * and related calls. Right now, this tramples on any - * extensible data in the ucred, fails to initialize the - * mutex, and worse. This must be fixed before FreeBSD - * 5.3-RELEASE. - */ - bzero((caddr_t)&nd->nd_cr, sizeof (struct ucred)); - nd->nd_cr.cr_ref = 1; - nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++); - nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++); + nd->nd_cr->cr_uid = nd->nd_cr->cr_ruid = + nd->nd_cr->cr_svuid = fxdr_unsigned(uid_t, *tl++); + nd->nd_cr->cr_groups[0] = nd->nd_cr->cr_rgid = + nd->nd_cr->cr_svgid = fxdr_unsigned(gid_t, *tl++); +#ifdef MAC + mac_associate_nfsd_label(nd->nd_cr); +#endif len = fxdr_unsigned(int, *tl); if (len < 0 || len > RPCAUTH_UNIXGIDS) { m_freem(mrep); @@ -380,12 +381,12 @@ nfs_getreq(struct nfsrv_descript *nd, st tl = nfsm_dissect_nonblock(u_int32_t *, (len + 2) * NFSX_UNSIGNED); for (i = 1; i <= len; i++) if (i < NGROUPS) - nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++); + nd->nd_cr->cr_groups[i] = fxdr_unsigned(gid_t, *tl++); else tl++; - nd->nd_cr.cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1); - if (nd->nd_cr.cr_ngroups > 1) - nfsrvw_sort(nd->nd_cr.cr_groups, nd->nd_cr.cr_ngroups); + nd->nd_cr->cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1); + if (nd->nd_cr->cr_ngroups > 1) + nfsrvw_sort(nd->nd_cr->cr_groups, nd->nd_cr->cr_ngroups); len = fxdr_unsigned(int, *++tl); if (len < 0 || len > RPCAUTH_MAXSIZ) { m_freem(mrep); @@ -466,8 +467,7 @@ nfsrv_rcv(struct socket *so, void *arg, auio.uio_resid = 1000000000; flags = MSG_DONTWAIT; NFSD_UNLOCK(); - error = so->so_proto->pr_usrreqs->pru_soreceive - (so, &nam, &auio, &mp, NULL, &flags); + error = soreceive(so, &nam, &auio, &mp, NULL, &flags); NFSD_LOCK(); if (error || mp == NULL) { if (error == EWOULDBLOCK) @@ -503,8 +503,7 @@ nfsrv_rcv(struct socket *so, void *arg, auio.uio_resid = 1000000000; flags = MSG_DONTWAIT; NFSD_UNLOCK(); - error = so->so_proto->pr_usrreqs->pru_soreceive - (so, &nam, &auio, &mp, NULL, &flags); + error = soreceive(so, &nam, &auio, &mp, NULL, &flags); if (mp) { struct nfsrv_rec *rec; rec = malloc(sizeof(struct nfsrv_rec), @@ -702,6 +701,7 @@ nfsrv_dorec(struct nfssvc_sock *slp, str STAILQ_FIRST(&slp->ns_rec) == NULL) return (ENOBUFS); rec = STAILQ_FIRST(&slp->ns_rec); + KASSERT(rec->nr_packet != NULL, ("nfsrv_dorec: missing mbuf")); STAILQ_REMOVE_HEAD(&slp->ns_rec, nr_link); nam = rec->nr_address; m = rec->nr_packet; @@ -709,6 +709,7 @@ nfsrv_dorec(struct nfssvc_sock *slp, str NFSD_UNLOCK(); MALLOC(nd, struct nfsrv_descript *, sizeof (struct nfsrv_descript), M_NFSRVDESC, M_WAITOK); + nd->nd_cr = crget(); NFSD_LOCK(); nd->nd_md = nd->nd_mrep = m; nd->nd_nam2 = nam; @@ -718,6 +719,8 @@ nfsrv_dorec(struct nfssvc_sock *slp, str if (nam) { FREE(nam, M_SONAME); } + if (nd->nd_cr != NULL) + crfree(nd->nd_cr); free((caddr_t)nd, M_NFSRVDESC); return (error); } @@ -781,8 +784,7 @@ nfsrv_send(struct socket *so, struct soc else flags = 0; - error = so->so_proto->pr_usrreqs->pru_sosend(so, sendnam, 0, top, 0, - flags, curthread/*XXX*/); + error = sosend(so, sendnam, 0, top, 0, flags, curthread/*XXX*/); if (error == ENOBUFS && so->so_type == SOCK_DGRAM) error = 0; Index: nfs_srvsubs.c =================================================================== RCS file: /home/ncvs/src/sys/nfsserver/nfs_srvsubs.c,v retrieving revision 1.136.2.2 retrieving revision 1.145 diff -u -p -r1.136.2.2 -r1.145 --- nfs_srvsubs.c 4 Apr 2006 15:29:51 -0000 1.136.2.2 +++ nfs_srvsubs.c 2 Jan 2007 20:42:08 -0000 1.145 @@ -33,7 +33,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/nfsserver/nfs_srvsubs.c,v 1.136.2.2 2006/04/04 15:29:51 cel Exp $"); +__FBSDID("$FreeBSD: src/sys/nfsserver/nfs_srvsubs.c,v 1.145 2007/01/02 20:42:08 hrs Exp $"); /* * These functions support the macros and help fiddle mbuf chains for @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD: src/sys/nfsserver/nf #include #include #include +#include #include #include #include @@ -553,8 +554,9 @@ nfsrv_modevent(module_t mod, int type, v NFSD_UNLOCK(); nfsrv_timer(0); + /* XXX: Should use SYSCALL_MODULE() */ nfs_prev_nfssvc_sy_narg = sysent[SYS_nfssvc].sy_narg; - sysent[SYS_nfssvc].sy_narg = 2 | SYF_MPSAFE; + sysent[SYS_nfssvc].sy_narg = 2; nfs_prev_nfssvc_sy_call = sysent[SYS_nfssvc].sy_call; sysent[SYS_nfssvc].sy_call = (sy_call_t *)nfssvc; break; @@ -565,9 +567,10 @@ nfsrv_modevent(module_t mod, int type, v break; } - callout_stop(&nfsrv_callout); + callout_drain(&nfsrv_callout); sysent[SYS_nfssvc].sy_narg = nfs_prev_nfssvc_sy_narg; sysent[SYS_nfssvc].sy_call = nfs_prev_nfssvc_sy_call; + nfsrv_destroycache(); /* Free the server request cache */ mtx_destroy(&nfsd_mtx); break; default: @@ -621,7 +624,6 @@ nfs_namei(struct nameidata *ndp, fhandle NFSD_LOCK_ASSERT(); NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ *retdirp = NULL; cnp->cn_flags |= NOMACCHECK; @@ -640,14 +642,14 @@ nfs_namei(struct nameidata *ndp, fhandle md = md->m_next; if (md == NULL) { error = EBADRPC; - goto out; + goto out_nogiant; } fromcp = mtod(md, caddr_t); rem = md->m_len; } if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) { error = EACCES; - goto out; + goto out_nogiant; } *tocp++ = *fromcp++; rem--; @@ -660,17 +662,17 @@ nfs_namei(struct nameidata *ndp, fhandle if (rem >= len) *dposp += len; else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0) - goto out; + goto out_nogiant; } /* * Extract and set starting directory. + * + * XXXRW: For now, acquire Giant unconditionally to avoid tracking it + * on multiple vnodes. */ - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp, nam, &rdonly, pubflag); - NFSD_UNLOCK(); mtx_lock(&Giant); /* VFS */ if (error) goto out; @@ -875,6 +877,10 @@ nfs_namei(struct nameidata *ndp, fhandle } 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 @@ -882,6 +888,8 @@ nfs_namei(struct nameidata *ndp, fhandle * cleanup state trivially. */ out: + mtx_unlock(&Giant); /* VFS */ +out_nogiant: if (error) { uma_zfree(namei_zone, cnp->cn_pnbuf); ndp->ni_vp = NULL; @@ -891,7 +899,6 @@ out: } else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) { ndp->ni_dvp = NULL; } - mtx_unlock(&Giant); /* VFS */ NFSD_LOCK(); return (error); } @@ -1057,6 +1064,10 @@ nfsm_srvfattr(struct nfsrv_descript *nfs * - 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() + * + * As this routine may acquire Giant and may sleep, it can't be called with + * nfsd_mtx. Caller should invoke nfsrv_fhtovp_locked() if the lock is held + * so that it can be automatically dropped and re-acquired. */ int nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, @@ -1068,11 +1079,12 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockfla int i; struct ucred *credanon; int error, exflags; + int vfslocked; #ifdef MNT_EXNORESPORT /* XXX needs mountd and /etc/exports help yet */ struct sockaddr_int *saddr; #endif - NFSD_LOCK_ASSERT(); + NFSD_UNLOCK_ASSERT(); *vpp = NULL; @@ -1085,8 +1097,7 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockfla mp = vfs_getvfs(&fhp->fh_fsid); if (!mp) return (ESTALE); - NFSD_UNLOCK(); - mtx_lock(&Giant); /* VFS */ + vfslocked = VFS_LOCK_GIANT(mp); error = VFS_CHECKEXP(mp, nam, &exflags, &credanon); if (error) goto out; @@ -1123,11 +1134,29 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockfla if (!lockflag) VOP_UNLOCK(*vpp, 0, td); out: - mtx_unlock(&Giant); /* VFS */ - NFSD_LOCK(); + vfs_rel(mp); + VFS_UNLOCK_GIANT(vfslocked); return (error); } +/* + * Version of nfsrv_fhtovp() that can be called holding nfsd_mtx: it will + * drop and re-acquire the lock for the caller. + */ +int +nfsrv_fhtovp_locked(fhandle_t *fhp, int lockflag, struct vnode **vpp, + struct ucred *cred, struct nfssvc_sock *slp, struct sockaddr *nam, + int *rdonlyp, int pubflag) +{ + int error; + + NFSD_LOCK_ASSERT(); + NFSD_UNLOCK(); + error = nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, + pubflag); + NFSD_LOCK(); + return (error); +} /* * WebNFS: check if a filehandle is a public filehandle. For v3, this @@ -1257,7 +1286,7 @@ nfsrv_setcred(struct ucred *incred, stru NFSD_LOCK_DONTCARE(); bzero((caddr_t)outcred, sizeof (struct ucred)); - outcred->cr_ref = 1; + refcount_init(&outcred->cr_ref, 1); outcred->cr_uid = incred->cr_uid; outcred->cr_ngroups = incred->cr_ngroups; for (i = 0; i < incred->cr_ngroups; i++) @@ -1331,6 +1360,24 @@ nfsm_srvnamesiz_xx(int *s, int m, struct 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: nfs_syscalls.c =================================================================== RCS file: /home/ncvs/src/sys/nfsserver/nfs_syscalls.c,v retrieving revision 1.103 retrieving revision 1.109 diff -u -p -r1.103 -r1.109 --- nfs_syscalls.c 26 Mar 2005 11:29:02 -0000 1.103 +++ nfs_syscalls.c 12 Dec 2006 12:17:58 -0000 1.109 @@ -33,7 +33,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/nfsserver/nfs_syscalls.c,v 1.103 2005/03/26 11:29:02 delphij Exp $"); +__FBSDID("$FreeBSD: src/sys/nfsserver/nfs_syscalls.c,v 1.109 2006/12/12 12:17:58 bz Exp $"); #include "opt_inet6.h" #include "opt_mac.h" @@ -46,9 +46,9 @@ __FBSDID("$FreeBSD: src/sys/nfsserver/nf #include #include #include -#include #include #include +#include #include #include #include @@ -74,10 +74,12 @@ __FBSDID("$FreeBSD: src/sys/nfsserver/nf #include #include -static MALLOC_DEFINE(M_NFSSVC, "NFS srvsock", "Nfs server structure"); +#include -MALLOC_DEFINE(M_NFSRVDESC, "NFSV3 srvdesc", "NFS server socket descriptor"); -MALLOC_DEFINE(M_NFSD, "NFS daemon", "Nfs server daemon structure"); +static MALLOC_DEFINE(M_NFSSVC, "nfsserver_srvsock", "Nfs server structure"); + +MALLOC_DEFINE(M_NFSRVDESC, "nfsserver_srvdesc", "NFS server socket descriptor"); +MALLOC_DEFINE(M_NFSD, "nfsserver_daemon", "Nfs server daemon structure"); #define TRUE 1 @@ -141,7 +143,7 @@ nfssvc(struct thread *td, struct nfssvc_ if (error) return (error); #endif - error = suser(td); + error = priv_check(td, PRIV_NFSD); if (error) return (error); NET_LOCK_GIANT(); @@ -390,6 +392,8 @@ nfssvc_nfsd(struct thread *td) } if (error || (slp->ns_flag & SLP_VALID) == 0) { if (nd) { + if (nd->nd_cr != NULL) + crfree(nd->nd_cr); free((caddr_t)nd, M_NFSRVDESC); nd = NULL; } @@ -426,27 +430,31 @@ nfssvc_nfsd(struct thread *td) port = ntohs(sin->sin_port); if (port >= IPPORT_RESERVED && nd->nd_procnum != NFSPROC_NULL) { -#if defined(INET6) && defined(KLD_MODULE) - /* do not use ip6_sprintf: the nfs module should work without INET6 */ - char b6[INET6_ADDRSTRLEN]; -#define ip6_sprintf(a) \ - (sprintf(b6, "%x:%x:%x:%x:%x:%x:%x:%x", \ +#ifdef INET6 + char b6[INET6_ADDRSTRLEN]; +#if defined(KLD_MODULE) + /* Do not use ip6_sprintf: the nfs module should work without INET6. */ +#define ip6_sprintf(buf, a) \ + (sprintf((buf), "%x:%x:%x:%x:%x:%x:%x:%x", \ (a)->s6_addr16[0], (a)->s6_addr16[1], \ (a)->s6_addr16[2], (a)->s6_addr16[3], \ (a)->s6_addr16[4], (a)->s6_addr16[5], \ (a)->s6_addr16[6], (a)->s6_addr16[7]), \ - b6) + (buf)) +#endif #endif nd->nd_procnum = NFSPROC_NOOP; nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK); cacherep = RC_DOIT; printf("NFS request from unprivileged port (%s:%d)\n", #ifdef INET6 - sin->sin_family == AF_INET6 ? - ip6_sprintf(&satosin6(sin)->sin6_addr) : + sin->sin_family == AF_INET6 ? + ip6_sprintf(b6, &satosin6(sin)->sin6_addr) : +#if defined(KLD_MODULE) #undef ip6_sprintf #endif - inet_ntoa(sin->sin_addr), port); +#endif + inet_ntoa(sin->sin_addr), port); } } @@ -522,6 +530,8 @@ nfssvc_nfsd(struct thread *td) if (slp->ns_so->so_proto->pr_flags & PR_CONNREQUIRED) nfs_slpunlock(slp); if (error == EINTR || error == ERESTART) { + if (nd->nd_cr != NULL) + crfree(nd->nd_cr); free((caddr_t)nd, M_NFSRVDESC); nfsrv_slpderef(slp); s = splnet(); @@ -535,6 +545,8 @@ nfssvc_nfsd(struct thread *td) break; }; if (nd) { + if (nd->nd_cr != NULL) + crfree(nd->nd_cr); FREE((caddr_t)nd, M_NFSRVDESC); nd = NULL; } @@ -630,6 +642,8 @@ nfsrv_zapsock(struct nfssvc_sock *slp) for (nwp = LIST_FIRST(&slp->ns_tq); nwp; nwp = nnwp) { nnwp = LIST_NEXT(nwp, nd_tq); LIST_REMOVE(nwp, nd_tq); + if (nwp->nd_cr != NULL) + crfree(nwp->nd_cr); free((caddr_t)nwp, M_NFSRVDESC); } LIST_INIT(&slp->ns_tq); @@ -712,9 +726,7 @@ nfsrv_init(int terminating) panic("nfsd init"); nfssvc_sockhead_flag |= SLP_INIT; if (terminating) { - for (slp = TAILQ_FIRST(&nfssvc_sockhead); slp != NULL; - slp = nslp) { - nslp = TAILQ_NEXT(slp, ns_chain); + TAILQ_FOREACH_SAFE(slp, &nfssvc_sockhead, ns_chain, nslp) { if (slp->ns_flag & SLP_VALID) nfsrv_zapsock(slp); TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain); Index: nfsm_subs.h =================================================================== RCS file: /home/ncvs/src/sys/nfsserver/nfsm_subs.h,v retrieving revision 1.37 retrieving revision 1.38 diff -u -p -r1.37 -r1.38 --- nfsm_subs.h 7 Jan 2005 01:45:51 -0000 1.37 +++ nfsm_subs.h 2 Jan 2007 20:42:08 -0000 1.38 @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)nfsm_subs.h 8.2 (Berkeley) 3/30/95 - * $FreeBSD: src/sys/nfsserver/nfsm_subs.h,v 1.37 2005/01/07 01:45:51 imp Exp $ + * $FreeBSD: src/sys/nfsserver/nfsm_subs.h,v 1.38 2007/01/02 20:42:08 hrs Exp $ */ #ifndef _NFSSERVER_NFSM_SUBS_H_ @@ -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 @@ do { \ #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); \ Index: nfsrvcache.h =================================================================== RCS file: /home/ncvs/src/sys/nfsserver/nfsrvcache.h,v retrieving revision 1.17.6.1 retrieving revision 1.19 diff -u -p -r1.17.6.1 -r1.19 --- nfsrvcache.h 30 Apr 2006 03:56:12 -0000 1.17.6.1 +++ nfsrvcache.h 23 Jun 2006 00:42:26 -0000 1.19 @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * @(#)nfsrvcache.h 8.3 (Berkeley) 3/30/95 - * $FreeBSD: src/sys/nfsserver/nfsrvcache.h,v 1.17.6.1 2006/04/30 03:56:12 kris Exp $ + * $FreeBSD: src/sys/nfsserver/nfsrvcache.h,v 1.19 2006/06/23 00:42:26 mohans Exp $ */ #ifndef _NFSSERVER_NFSRVCACHE_H_ @@ -41,8 +41,8 @@ /* * Definitions for the server recent request cache */ - -#define NFSRVCACHESIZ 2048 +#define NFSRVCACHE_MAX_SIZE 2048 +#define NFSRVCACHE_MIN_SIZE 64 struct nfsrvcache { TAILQ_ENTRY(nfsrvcache) rc_lru; /* LRU chain */