X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/832eafe0c66b35d66bae59a86d7cc1da656b2d81..9910d07b2f8670a44edbe17863f961ffbc6ea537:/sys/vfs/nfs/nfs_syscalls.c diff --git a/sys/vfs/nfs/nfs_syscalls.c b/sys/vfs/nfs/nfs_syscalls.c index ef361d261c..2058282009 100644 --- a/sys/vfs/nfs/nfs_syscalls.c +++ b/sys/vfs/nfs/nfs_syscalls.c @@ -58,8 +58,11 @@ #include #include #include +#include #include +#include + #include #include #include "xdr_subs.h" @@ -76,28 +79,15 @@ static MALLOC_DEFINE(M_NFSSVC, "NFS srvsock", "Nfs server structure"); -/* Global defs. */ -extern int32_t (*nfsrv3_procs[NFS_NPROCS]) (struct nfsrv_descript *nd, - struct nfssvc_sock *slp, - struct thread *td, - struct mbuf **mreqp); -extern int nfs_numasync; -extern int nfsrtton; -extern struct nfsstats nfsstats; -extern int nfsrvw_procrastinate; -extern int nfsrvw_procrastinate_v3; static int nuidhash_max = NFS_MAXUIDHASH; #ifndef NFS_NOSERVER static void nfsrv_zapsock (struct nfssvc_sock *slp); #endif -static int nfssvc_iod (struct thread *); #define TRUE 1 #define FALSE 0 -static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON]; - SYSCTL_DECL(_vfs_nfs); #ifndef NFS_NOSERVER @@ -114,7 +104,7 @@ static int nfs_privport = 0; SYSCTL_INT(_vfs_nfs, NFS_NFSPRIVPORT, nfs_privport, CTLFLAG_RW, &nfs_privport, 0, ""); SYSCTL_INT(_vfs_nfs, OID_AUTO, gatherdelay, CTLFLAG_RW, &nfsrvw_procrastinate, 0, ""); SYSCTL_INT(_vfs_nfs, OID_AUTO, gatherdelay_v3, CTLFLAG_RW, &nfsrvw_procrastinate_v3, 0, ""); -static int nfs_soreserve = 65535; +int nfs_soreserve = NFS_MAXPACKET * NFS_MAXASYNCBIO; SYSCTL_INT(_vfs_nfs, OID_AUTO, soreserve, CTLFLAG_RW, &nfs_soreserve, 0, ""); /* @@ -130,6 +120,8 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, soreserve, CTLFLAG_RW, &nfs_soreserve, 0, ""); * - adds a socket to the selection list * - remains in the kernel as an nfsd * - remains in the kernel as an nfsiod + * + * MPALMOSTSAFE */ int sys_nfssvc(struct nfssvc_args *uap) @@ -154,15 +146,16 @@ sys_nfssvc(struct nfssvc_args *uap) * Must be super user */ error = priv_check(td, PRIV_ROOT); - if(error) + if (error) return (error); - KKASSERT(td->td_proc); /* for ucred and p_fd */ + + get_mplock(); while (nfssvc_sockhead_flag & SLP_INIT) { - nfssvc_sockhead_flag |= SLP_WANTINIT; - (void) tsleep((caddr_t)&nfssvc_sockhead, 0, "nfsd init", 0); + nfssvc_sockhead_flag |= SLP_WANTINIT; + tsleep((caddr_t)&nfssvc_sockhead, 0, "nfsd init", 0); } if (uap->flag & NFSSVC_BIOD) - error = nfssvc_iod(td); + error = ENXIO; /* no longer need nfsiod's */ #ifdef NFS_NOSERVER else error = ENXIO; @@ -170,7 +163,7 @@ sys_nfssvc(struct nfssvc_args *uap) else if (uap->flag & NFSSVC_MNTD) { error = copyin(uap->argp, (caddr_t)&ncd, sizeof (ncd)); if (error) - return (error); + goto done; vp = NULL; error = nlookup_init(&nd, ncd.ncd_dirp, UIO_USERSPACE, NLC_FOLLOW); @@ -180,38 +173,40 @@ sys_nfssvc(struct nfssvc_args *uap) error = cache_vget(&nd.nl_nch, nd.nl_cred, LK_EXCLUSIVE, &vp); nlookup_done(&nd); if (error) - return (error); + goto done; if ((vp->v_flag & VROOT) == 0) error = EINVAL; nmp = VFSTONFS(vp->v_mount); vput(vp); if (error) - return (error); + goto done; if ((nmp->nm_state & NFSSTA_MNTD) && - (uap->flag & NFSSVC_GOTAUTH) == 0) - return (0); + (uap->flag & NFSSVC_GOTAUTH) == 0) { + error = 0; + goto done; + } nmp->nm_state |= NFSSTA_MNTD; - error = nfs_clientd(nmp, td->td_proc->p_ucred, &ncd, uap->flag, + error = nfs_clientd(nmp, td->td_ucred, &ncd, uap->flag, uap->argp, td); } else if (uap->flag & NFSSVC_ADDSOCK) { error = copyin(uap->argp, (caddr_t)&nfsdarg, sizeof(nfsdarg)); if (error) - return (error); + goto done; error = holdsock(td->td_proc->p_fd, nfsdarg.sock, &fp); if (error) - return (error); + goto done; /* * Get the client address for connected sockets. */ if (nfsdarg.name == NULL || nfsdarg.namelen == 0) - nam = (struct sockaddr *)0; + nam = NULL; else { error = getsockaddr(&nam, nfsdarg.name, nfsdarg.namelen); if (error) { fdrop(fp); - return (error); + goto done; } } error = nfssvc_addsock(fp, nam, td); @@ -219,7 +214,7 @@ sys_nfssvc(struct nfssvc_args *uap) } else { error = copyin(uap->argp, (caddr_t)nsd, sizeof (*nsd)); if (error) - return (error); + goto done; if ((uap->flag & NFSSVC_AUTHIN) && ((nfsd = nsd->nsd_nfsd)) != NULL && (nfsd->nfsd_slp->ns_flag & SLP_VALID)) { @@ -250,12 +245,12 @@ sys_nfssvc(struct nfssvc_args *uap) kmalloc(sizeof (struct nfsuid), M_NFSUID, M_WAITOK); } else - nuidp = (struct nfsuid *)0; + nuidp = NULL; if ((slp->ns_flag & SLP_VALID) == 0) { if (nuidp) kfree((caddr_t)nuidp, M_NFSUID); } else { - if (nuidp == (struct nfsuid *)0) { + if (nuidp == NULL) { nuidp = TAILQ_FIRST(&slp->ns_uidlruhead); LIST_REMOVE(nuidp, nu_hash); TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, @@ -311,6 +306,8 @@ sys_nfssvc(struct nfssvc_args *uap) #endif /* NFS_NOSERVER */ if (error == EINTR || error == ERESTART) error = 0; +done: + rel_mplock(); return (error); } @@ -328,7 +325,7 @@ nfssvc_addsock(struct file *fp, struct sockaddr *mynam, struct thread *td) so = (struct socket *)fp->f_data; #if 0 - tslp = (struct nfssvc_sock *)0; + tslp = NULL; /* * Add it to the list, as required. */ @@ -345,6 +342,9 @@ nfssvc_addsock(struct file *fp, struct sockaddr *mynam, struct thread *td) * Reserve buffer space in the socket. Note that due to bugs in * Linux's delayed-ack code, serious performance degredation may * occur with linux hosts if the minimum is used. + * + * NFS sockets are not limited to the standard sb_max or by + * resource limits. */ if (so->so_type == SOCK_STREAM) siz = NFS_MAXPACKET + sizeof (u_long); @@ -352,14 +352,8 @@ nfssvc_addsock(struct file *fp, struct sockaddr *mynam, struct thread *td) siz = NFS_MAXPACKET; if (siz < nfs_soreserve) siz = nfs_soreserve; - if (siz > sb_max_adj) { - kprintf("Warning: vfs.nfs.soreserve (%d) " - "limited to adjusted sb_max (%ld)\n", - nfs_soreserve, sb_max_adj); - siz = sb_max_adj; - } - error = soreserve(so, siz, siz, &td->td_proc->p_rlimit[RLIMIT_SBSIZE]); + error = soreserve(so, siz, siz, NULL); if (error) { if (mynam != NULL) FREE(mynam, M_SONAME); @@ -403,6 +397,7 @@ nfssvc_addsock(struct file *fp, struct sockaddr *mynam, struct thread *td) slp = (struct nfssvc_sock *)kmalloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO); + mtx_init(&slp->ns_solock); STAILQ_INIT(&slp->ns_rec); TAILQ_INIT(&slp->ns_uidlruhead); TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain); @@ -441,7 +436,7 @@ nfssvc_nfsd(struct nfsd_srvargs *nsd, caddr_t argp, struct thread *td) cacherep = RC_DOIT; writes_todo = 0; #endif - if (nfsd == (struct nfsd *)0) { + if (nfsd == NULL) { nsd->nsd_nfsd = nfsd = (struct nfsd *) kmalloc(sizeof (struct nfsd), M_NFSD, M_WAITOK|M_ZERO); crit_enter(); @@ -479,7 +474,7 @@ nfssvc_nfsd(struct nfsd_srvargs *nsd, caddr_t argp, struct thread *td) if (slp == 0) nfsd_head_flag &= ~NFSD_CHECKSLP; } - if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0) + if ((slp = nfsd->nfsd_slp) == NULL) continue; if (slp->ns_flag & SLP_VALID) { if (slp->ns_flag & SLP_DISCONN) @@ -511,7 +506,7 @@ nfssvc_nfsd(struct nfsd_srvargs *nsd, caddr_t argp, struct thread *td) kfree((caddr_t)nd, M_NFSRVDESC); nd = NULL; } - nfsd->nfsd_slp = (struct nfssvc_sock *)0; + nfsd->nfsd_slp = NULL; nfsd->nfsd_flag &= ~NFSD_REQINPROG; nfsrv_slpderef(slp); continue; @@ -603,7 +598,7 @@ nfssvc_nfsd(struct nfsd_srvargs *nsd, caddr_t argp, struct thread *td) } nfsstats.srvrpccnt[nd->nd_procnum]++; nfsrv_updatecache(nd, TRUE, mreq); - nd->nd_mrep = (struct mbuf *)0; + nd->nd_mrep = NULL; case RC_REPLY: m = mreq; siz = 0; @@ -617,7 +612,7 @@ nfssvc_nfsd(struct nfsd_srvargs *nsd, caddr_t argp, struct thread *td) } m = mreq; m->m_pkthdr.len = siz; - m->m_pkthdr.rcvif = (struct ifnet *)0; + m->m_pkthdr.rcvif = NULL; /* * For stream protocols, prepend a Sun RPC * Record Mark. @@ -691,7 +686,7 @@ done: TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain); crit_exit(); kfree((caddr_t)nfsd, M_NFSD); - nsd->nsd_nfsd = (struct nfsd *)0; + nsd->nsd_nfsd = NULL; if (--nfs_numnfsd == 0) nfsrv_init(TRUE); /* Reinitialize everything */ return (error); @@ -716,7 +711,7 @@ nfsrv_zapsock(struct nfssvc_sock *slp) slp->ns_flag &= ~SLP_ALLFLAGS; fp = slp->ns_fp; if (fp) { - slp->ns_fp = (struct file *)0; + slp->ns_fp = NULL; so = slp->ns_so; so->so_rcv.ssb_flags &= ~SSB_UPCALL; so->so_upcall = NULL; @@ -768,20 +763,22 @@ nfsrv_slpderef(struct nfssvc_sock *slp) /* * Lock a socket against others. + * + * Returns 0 on failure, 1 on success. */ int nfs_slplock(struct nfssvc_sock *slp, int wait) { - int *statep = &slp->ns_solock; + mtx_t mtx = &slp->ns_solock; - if (!wait && (*statep & NFSSTA_SNDLOCK)) - return(0); /* already locked, fail */ - while (*statep & NFSSTA_SNDLOCK) { - *statep |= NFSSTA_WANTSND; - (void) tsleep((caddr_t)statep, 0, "nfsslplck", 0); + if (wait) { + mtx_lock_ex(mtx, "nfsslplck", 0, 0); + return(1); + } else if (mtx_lock_ex_try(mtx) == 0) { + return(1); + } else { + return(0); } - *statep |= NFSSTA_SNDLOCK; - return (1); } /* @@ -790,15 +787,9 @@ nfs_slplock(struct nfssvc_sock *slp, int wait) void nfs_slpunlock(struct nfssvc_sock *slp) { - int *statep = &slp->ns_solock; - - if ((*statep & NFSSTA_SNDLOCK) == 0) - panic("nfs slpunlock"); - *statep &= ~NFSSTA_SNDLOCK; - if (*statep & NFSSTA_WANTSND) { - *statep &= ~NFSSTA_WANTSND; - wakeup((caddr_t)statep); - } + mtx_t mtx = &slp->ns_solock; + + mtx_unlock(mtx); } /* @@ -838,12 +829,14 @@ nfsrv_init(int terminating) #if 0 nfs_udpsock = (struct nfssvc_sock *) kmalloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO); + mtx_init(&nfs_udpsock->ns_solock); STAILQ_INIT(&nfs_udpsock->ns_rec); TAILQ_INIT(&nfs_udpsock->ns_uidlruhead); TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain); nfs_cltpsock = (struct nfssvc_sock *) kmalloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO); + mtx_init(&nfs_cltpsock->ns_solock); STAILQ_INIT(&nfs_cltpsock->ns_rec); TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead); TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain); @@ -883,84 +876,6 @@ nfsd_rt(int sotype, struct nfsrv_descript *nd, int cacherep) static int nfs_defect = 0; SYSCTL_INT(_vfs_nfs, OID_AUTO, defect, CTLFLAG_RW, &nfs_defect, 0, ""); -/* - * Asynchronous I/O daemons for client nfs. - * They do read-ahead and write-behind operations on the block I/O cache. - * Never returns unless it fails or gets killed. - */ -static int -nfssvc_iod(struct thread *td) -{ - struct bio *bio; - int i, myiod; - struct nfsmount *nmp; - int error = 0; - - /* - * Assign my position or return error if too many already running - */ - myiod = -1; - for (i = 0; i < NFS_MAXASYNCDAEMON; i++) - if (nfs_asyncdaemon[i] == 0) { - nfs_asyncdaemon[i]++; - myiod = i; - break; - } - if (myiod == -1) - return (EBUSY); - nfs_numasync++; - /* - * Just loop around doin our stuff until SIGKILL - */ - for (;;) { - while (((nmp = nfs_iodmount[myiod]) == NULL - || TAILQ_EMPTY(&nmp->nm_bioq)) - && error == 0) { - if (nmp) - nmp->nm_bioqiods--; - nfs_iodwant[myiod] = td; - nfs_iodmount[myiod] = NULL; - error = tsleep((caddr_t)&nfs_iodwant[myiod], - PCATCH, "nfsidl", 0); - } - if (error) { - nfs_asyncdaemon[myiod] = 0; - if (nmp) - nmp->nm_bioqiods--; - nfs_iodwant[myiod] = NULL; - nfs_iodmount[myiod] = NULL; - nfs_numasync--; - return (error); - } - while ((bio = TAILQ_FIRST(&nmp->nm_bioq)) != NULL) { - /* - * Take one off the front of the list. The BIO's - * block number is normalized for DEV_BSIZE. - */ - TAILQ_REMOVE(&nmp->nm_bioq, bio, bio_act); - nmp->nm_bioqlen--; - if (nmp->nm_bioqwant && nmp->nm_bioqlen <= nfs_numasync) { - nmp->nm_bioqwant = FALSE; - wakeup(&nmp->nm_bioq); - } - nfs_doio((struct vnode *)bio->bio_driver_info, bio, NULL); - /* - * If there are more than one iod on this mount, then defect - * so that the iods can be shared out fairly between the mounts - */ - if (nfs_defect && nmp->nm_bioqiods > 1) { - NFS_DPF(ASYNCIO, - ("nfssvc_iod: iod %d defecting from mount %p\n", - myiod, nmp)); - nfs_iodmount[myiod] = NULL; - nmp->nm_bioqiods--; - break; - } - } - } -} - - /* * Get an authorization string for the uid by having the mount_nfs sitting * on this mount point porpous out of the kernel and do it. @@ -1073,6 +988,9 @@ nfs_getnickauth(struct nfsmount *nmp, struct ucred *cred, char **auth_str, */ #ifdef NFSKERB XXX +#else + ktvout.tv_sec = 0; + ktvout.tv_usec = 0; #endif *verfp++ = ktvout.tv_sec; @@ -1091,15 +1009,17 @@ nfs_savenickauth(struct nfsmount *nmp, struct ucred *cred, int len, { struct nfsuid *nuidp; u_int32_t *tl; - int32_t t1; - struct mbuf *md = *mdp; struct timeval ktvin, ktvout; u_int32_t nick; - char *dpos = *dposp, *cp2; int deltasec, error = 0; + struct nfsm_info info; + + info.md = *mdp; + info.dpos = *dposp; + info.mrep = mrep; if (len == (3 * NFSX_UNSIGNED)) { - nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); + NULLOUT(tl = nfsm_dissect(&info, 3 * NFSX_UNSIGNED)); ktvin.tv_sec = *tl++; ktvin.tv_usec = *tl++; nick = fxdr_unsigned(u_int32_t, *tl); @@ -1109,6 +1029,9 @@ nfs_savenickauth(struct nfsmount *nmp, struct ucred *cred, int len, */ #ifdef NFSKERB XXX +#else + ktvout.tv_sec = 0; + ktvout.tv_usec = 0; #endif ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec); ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec); @@ -1141,10 +1064,11 @@ nfs_savenickauth(struct nfsmount *nmp, struct ucred *cred, int len, LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid), nuidp, nu_hash); } - } else - nfsm_adv(nfsm_rndup(len)); + } else { + ERROROUT(nfsm_adv(&info, nfsm_rndup(len))); + } nfsmout: - *mdp = md; - *dposp = dpos; + *mdp = info.md; + *dposp = info.dpos; return (error); }