⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nfs_syscalls.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1989, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Rick Macklem at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)nfs_syscalls.c	8.3 (Berkeley) 1/4/94 */#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/file.h>#include <sys/stat.h>#include <sys/vnode.h>#include <sys/mount.h>#include <sys/proc.h>#include <sys/uio.h>#include <sys/malloc.h>#include <sys/buf.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/domain.h>#include <sys/protosw.h>#include <sys/namei.h>#include <sys/syslog.h>#include <netinet/in.h>#include <netinet/tcp.h>#ifdef ISO#include <netiso/iso.h>#endif#include <nfs/rpcv2.h>#include <nfs/nfsv2.h>#include <nfs/nfs.h>#include <nfs/nfsrvcache.h>#include <nfs/nfsmount.h>#include <nfs/nfsnode.h>#include <nfs/nqnfs.h>#include <nfs/nfsrtt.h>/* Global defs. */extern u_long nfs_prog, nfs_vers;extern int (*nfsrv_procs[NFS_NPROCS])();extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];extern int nfs_numasync;extern time_t nqnfsstarttime;extern struct nfsrv_req nsrvq_head;extern struct nfsd nfsd_head;extern int nqsrv_writeslack;extern int nfsrtton;struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock;int nuidhash_max = NFS_MAXUIDHASH;static int nfs_numnfsd = 0;int nfsd_waiting = 0;static int notstarted = 1;static int modify_flag = 0;static struct nfsdrt nfsdrt;void nfsrv_cleancache(), nfsrv_rcv(), nfsrv_wakenfsd(), nfs_sndunlock();static void nfsd_rt();void nfsrv_slpderef(), nfsrv_init();#define	TRUE	1#define	FALSE	0static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON];/* * NFS server system calls * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c *//* * Get file handle system call */struct getfh_args {	char	*fname;	fhandle_t *fhp;};getfh(p, uap, retval)	struct proc *p;	register struct getfh_args *uap;	int *retval;{	register struct vnode *vp;	fhandle_t fh;	int error;	struct nameidata nd;	/*	 * Must be super user	 */	if (error = suser(p->p_ucred, &p->p_acflag))		return (error);	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p);	if (error = namei(&nd))		return (error);	vp = nd.ni_vp;	bzero((caddr_t)&fh, sizeof(fh));	fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;	error = VFS_VPTOFH(vp, &fh.fh_fid);	vput(vp);	if (error)		return (error);	error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh));	return (error);}static struct nfssvc_sock nfssvc_sockhead;/* * Nfs server psuedo system call for the nfsd's * Based on the flag value it either: * - adds a socket to the selection list * - remains in the kernel as an nfsd * - remains in the kernel as an nfsiod */struct nfssvc_args {	int flag;	caddr_t argp;};nfssvc(p, uap, retval)	struct proc *p;	register struct nfssvc_args *uap;	int *retval;{	struct nameidata nd;	struct file *fp;	struct mbuf *nam;	struct nfsd_args nfsdarg;	struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs;	struct nfsd_cargs ncd;	struct nfsd *nfsd;	struct nfssvc_sock *slp;	struct nfsuid *nuidp, **nuh;	struct nfsmount *nmp;	int error;	/*	 * Must be super user	 */	if (error = suser(p->p_ucred, &p->p_acflag))		return (error);	while (nfssvc_sockhead.ns_flag & SLP_INIT) {		nfssvc_sockhead.ns_flag |= SLP_WANTINIT;		(void) tsleep((caddr_t)&nfssvc_sockhead, PSOCK, "nfsd init", 0);	}	if (uap->flag & NFSSVC_BIOD)		error = nfssvc_iod(p);	else if (uap->flag & NFSSVC_MNTD) {		if (error = copyin(uap->argp, (caddr_t)&ncd, sizeof (ncd)))			return (error);		NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,			ncd.ncd_dirp, p);		if (error = namei(&nd))			return (error);		if ((nd.ni_vp->v_flag & VROOT) == 0)			error = EINVAL;		nmp = VFSTONFS(nd.ni_vp->v_mount);		vput(nd.ni_vp);		if (error)			return (error);		if ((nmp->nm_flag & NFSMNT_MNTD) &&			(uap->flag & NFSSVC_GOTAUTH) == 0)			return (0);		nmp->nm_flag |= NFSMNT_MNTD;		error = nqnfs_clientd(nmp, p->p_ucred, &ncd, uap->flag,			uap->argp, p);	} else if (uap->flag & NFSSVC_ADDSOCK) {		if (error = copyin(uap->argp, (caddr_t)&nfsdarg,		    sizeof(nfsdarg)))			return (error);		if (error = getsock(p->p_fd, nfsdarg.sock, &fp))			return (error);		/*		 * Get the client address for connected sockets.		 */		if (nfsdarg.name == NULL || nfsdarg.namelen == 0)			nam = (struct mbuf *)0;		else if (error = sockargs(&nam, nfsdarg.name, nfsdarg.namelen,			MT_SONAME))			return (error);		error = nfssvc_addsock(fp, nam);	} else {		if (error = copyin(uap->argp, (caddr_t)nsd, sizeof (*nsd)))			return (error);		if ((uap->flag & NFSSVC_AUTHIN) && (nfsd = nsd->nsd_nfsd) &&			(nfsd->nd_slp->ns_flag & SLP_VALID)) {			slp = nfsd->nd_slp;			/*			 * First check to see if another nfsd has already			 * added this credential.			 */			nuidp = slp->ns_uidh[NUIDHASH(nsd->nsd_uid)];			while (nuidp) {				if (nuidp->nu_uid == nsd->nsd_uid)					break;				nuidp = nuidp->nu_hnext;			}			if (!nuidp) {			    /*			     * Nope, so we will.			     */			    if (slp->ns_numuids < nuidhash_max) {				slp->ns_numuids++;				nuidp = (struct nfsuid *)				   malloc(sizeof (struct nfsuid), M_NFSUID,					M_WAITOK);			    } else				nuidp = (struct nfsuid *)0;			    if ((slp->ns_flag & SLP_VALID) == 0) {				if (nuidp)				    free((caddr_t)nuidp, M_NFSUID);			    } else {				if (nuidp == (struct nfsuid *)0) {				    nuidp = slp->ns_lruprev;				    remque(nuidp);				    if (nuidp->nu_hprev)					nuidp->nu_hprev->nu_hnext =					    nuidp->nu_hnext;				    if (nuidp->nu_hnext)					nuidp->nu_hnext->nu_hprev =					    nuidp->nu_hprev;			        }				nuidp->nu_cr = nsd->nsd_cr;				if (nuidp->nu_cr.cr_ngroups > NGROUPS)					nuidp->nu_cr.cr_ngroups = NGROUPS;				nuidp->nu_cr.cr_ref = 1;				nuidp->nu_uid = nsd->nsd_uid;				insque(nuidp, (struct nfsuid *)slp);				nuh = &slp->ns_uidh[NUIDHASH(nsd->nsd_uid)];				if (nuidp->nu_hnext = *nuh)				    nuidp->nu_hnext->nu_hprev = nuidp;				nuidp->nu_hprev = (struct nfsuid *)0;				*nuh = nuidp;			    }			}		}		if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd))			nfsd->nd_flag |= NFSD_AUTHFAIL;		error = nfssvc_nfsd(nsd, uap->argp, p);	}	if (error == EINTR || error == ERESTART)		error = 0;	return (error);}/* * Adds a socket to the list for servicing by nfsds. */nfssvc_addsock(fp, mynam)	struct file *fp;	struct mbuf *mynam;{	register struct mbuf *m;	register int siz;	register struct nfssvc_sock *slp;	register struct socket *so;	struct nfssvc_sock *tslp;	int error, s;	so = (struct socket *)fp->f_data;	tslp = (struct nfssvc_sock *)0;	/*	 * Add it to the list, as required.	 */	if (so->so_proto->pr_protocol == IPPROTO_UDP) {		tslp = nfs_udpsock;		if (tslp->ns_flag & SLP_VALID) {			m_freem(mynam);			return (EPERM);		}#ifdef ISO	} else if (so->so_proto->pr_protocol == ISOPROTO_CLTP) {		tslp = nfs_cltpsock;		if (tslp->ns_flag & SLP_VALID) {			m_freem(mynam);			return (EPERM);		}#endif /* ISO */	}	if (so->so_type == SOCK_STREAM)		siz = NFS_MAXPACKET + sizeof (u_long);	else		siz = NFS_MAXPACKET;	if (error = soreserve(so, siz, siz)) {		m_freem(mynam);		return (error);	}	/*	 * Set protocol specific options { for now TCP only } and	 * reserve some space. For datagram sockets, this can get called	 * repeatedly for the same socket, but that isn't harmful.	 */	if (so->so_type == SOCK_STREAM) {		MGET(m, M_WAIT, MT_SOOPTS);		*mtod(m, int *) = 1;		m->m_len = sizeof(int);		sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m);	}	if (so->so_proto->pr_domain->dom_family == AF_INET &&	    so->so_proto->pr_protocol == IPPROTO_TCP) {		MGET(m, M_WAIT, MT_SOOPTS);		*mtod(m, int *) = 1;		m->m_len = sizeof(int);		sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m);	}	so->so_rcv.sb_flags &= ~SB_NOINTR;	so->so_rcv.sb_timeo = 0;	so->so_snd.sb_flags &= ~SB_NOINTR;	so->so_snd.sb_timeo = 0;	if (tslp)		slp = tslp;	else {		slp = (struct nfssvc_sock *)			malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);		bzero((caddr_t)slp, sizeof (struct nfssvc_sock));		slp->ns_prev = nfssvc_sockhead.ns_prev;		slp->ns_prev->ns_next = slp;		slp->ns_next = &nfssvc_sockhead;		nfssvc_sockhead.ns_prev = slp;		slp->ns_lrunext = slp->ns_lruprev = (struct nfsuid *)slp;	}	slp->ns_so = so;	slp->ns_nam = mynam;	fp->f_count++;	slp->ns_fp = fp;	s = splnet();	so->so_upcallarg = (caddr_t)slp;	so->so_upcall = nfsrv_rcv;	slp->ns_flag = (SLP_VALID | SLP_NEEDQ);	nfsrv_wakenfsd(slp);	splx(s);	return (0);}/* * Called by nfssvc() for nfsds. Just loops around servicing rpc requests * until it is killed by a signal. */nfssvc_nfsd(nsd, argp, p)	struct nfsd_srvargs *nsd;	caddr_t argp;	struct proc *p;{	register struct mbuf *m, *nam2;	register int siz;	register struct nfssvc_sock *slp;	register struct socket *so;	register int *solockp;	struct nfsd *nd = nsd->nsd_nfsd;	struct mbuf *mreq, *nam;	struct timeval starttime;	struct nfsuid *uidp;	int error, cacherep, s;	int sotype;	s = splnet();	if (nd == (struct nfsd *)0) {		nsd->nsd_nfsd = nd = (struct nfsd *)			malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK);		bzero((caddr_t)nd, sizeof (struct nfsd));		nd->nd_procp = p;		nd->nd_cr.cr_ref = 1;		insque(nd, &nfsd_head);		nd->nd_nqlflag = NQL_NOVAL;		nfs_numnfsd++;	}	/*	 * Loop getting rpc requests until SIGKILL.	 */	for (;;) {		if ((nd->nd_flag & NFSD_REQINPROG) == 0) {			while (nd->nd_slp == (struct nfssvc_sock *)0 &&				 (nfsd_head.nd_flag & NFSD_CHECKSLP) == 0) {				nd->nd_flag |= NFSD_WAITING;				nfsd_waiting++;				error = tsleep((caddr_t)nd, PSOCK | PCATCH, "nfsd", 0);				nfsd_waiting--;				if (error)					goto done;			}			if (nd->nd_slp == (struct nfssvc_sock *)0 &&				(nfsd_head.nd_flag & NFSD_CHECKSLP)) {				slp = nfssvc_sockhead.ns_next;				while (slp != &nfssvc_sockhead) {				    if ((slp->ns_flag & (SLP_VALID | SLP_DOREC))					== (SLP_VALID | SLP_DOREC)) {					    slp->ns_flag &= ~SLP_DOREC;					    slp->ns_sref++;					    nd->nd_slp = slp;					    break;				    }				    slp = slp->ns_next;				}				if (slp == &nfssvc_sockhead)					nfsd_head.nd_flag &= ~NFSD_CHECKSLP;			}			if ((slp = nd->nd_slp) == (struct nfssvc_sock *)0)				continue;			if (slp->ns_flag & SLP_VALID) {				if (slp->ns_flag & SLP_DISCONN)					nfsrv_zapsock(slp);				else if (slp->ns_flag & SLP_NEEDQ) {					slp->ns_flag &= ~SLP_NEEDQ;					(void) nfs_sndlock(&slp->ns_solock,						(struct nfsreq *)0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -