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

📄 nfs_syscalls.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
					nfsrv_rcv(slp->ns_so, (caddr_t)slp,						M_WAIT);					nfs_sndunlock(&slp->ns_solock);				}				error = nfsrv_dorec(slp, nd);				nd->nd_flag |= NFSD_REQINPROG;			}		} else {			error = 0;			slp = nd->nd_slp;		}		if (error || (slp->ns_flag & SLP_VALID) == 0) {			nd->nd_slp = (struct nfssvc_sock *)0;			nd->nd_flag &= ~NFSD_REQINPROG;			nfsrv_slpderef(slp);			continue;		}		splx(s);		so = slp->ns_so;		sotype = so->so_type;		starttime = time;		if (so->so_proto->pr_flags & PR_CONNREQUIRED)			solockp = &slp->ns_solock;		else			solockp = (int *)0;		/*		 * nam == nam2 for connectionless protocols such as UDP		 * nam2 == NULL for connection based protocols to disable		 *    recent request caching.		 */		if (nam2 = nd->nd_nam) {			nam = nam2;			cacherep = RC_CHECKIT;		} else {			nam = slp->ns_nam;			cacherep = RC_DOIT;		}		/*		 * Check to see if authorization is needed.		 */		if (nd->nd_flag & NFSD_NEEDAUTH) {			static int logauth = 0;			nd->nd_flag &= ~NFSD_NEEDAUTH;			/*			 * Check for a mapping already installed.			 */			uidp = slp->ns_uidh[NUIDHASH(nd->nd_cr.cr_uid)];			while (uidp) {				if (uidp->nu_uid == nd->nd_cr.cr_uid)					break;				uidp = uidp->nu_hnext;			}			if (!uidp) {			    nsd->nsd_uid = nd->nd_cr.cr_uid;			    if (nam2 && logauth++ == 0)				log(LOG_WARNING, "Kerberized NFS using UDP\n");			    nsd->nsd_haddr =			      mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;			    nsd->nsd_authlen = nd->nd_authlen;			    if (copyout(nd->nd_authstr, nsd->nsd_authstr,				nd->nd_authlen) == 0 &&				copyout((caddr_t)nsd, argp, sizeof (*nsd)) == 0)				return (ENEEDAUTH);			    cacherep = RC_DROPIT;			}		}		if (cacherep == RC_CHECKIT)			cacherep = nfsrv_getcache(nam2, nd, &mreq);		/*		 * Check for just starting up for NQNFS and send		 * fake "try again later" replies to the NQNFS clients.		 */		if (notstarted && nqnfsstarttime <= time.tv_sec) {			if (modify_flag) {				nqnfsstarttime = time.tv_sec + nqsrv_writeslack;				modify_flag = 0;			} else				notstarted = 0;		}		if (notstarted) {			if (nd->nd_nqlflag == NQL_NOVAL)				cacherep = RC_DROPIT;			else if (nd->nd_procnum != NFSPROC_WRITE) {				nd->nd_procnum = NFSPROC_NOOP;				nd->nd_repstat = NQNFS_TRYLATER;				cacherep = RC_DOIT;			} else				modify_flag = 1;		} else if (nd->nd_flag & NFSD_AUTHFAIL) {			nd->nd_flag &= ~NFSD_AUTHFAIL;			nd->nd_procnum = NFSPROC_NOOP;			nd->nd_repstat = NQNFS_AUTHERR;			cacherep = RC_DOIT;		}		switch (cacherep) {		case RC_DOIT:			error = (*(nfsrv_procs[nd->nd_procnum]))(nd,				nd->nd_mrep, nd->nd_md, nd->nd_dpos, &nd->nd_cr,				nam, &mreq);			if (nd->nd_cr.cr_ref != 1) {				printf("nfssvc cref=%d\n", nd->nd_cr.cr_ref);				panic("nfssvc cref");			}			if (error) {				if (nd->nd_procnum != NQNFSPROC_VACATED)					nfsstats.srv_errs++;				if (nam2) {					nfsrv_updatecache(nam2, nd, FALSE, mreq);					m_freem(nam2);				}				break;			}			nfsstats.srvrpccnt[nd->nd_procnum]++;			if (nam2)				nfsrv_updatecache(nam2, nd, TRUE, mreq);			nd->nd_mrep = (struct mbuf *)0;		case RC_REPLY:			m = mreq;			siz = 0;			while (m) {				siz += m->m_len;				m = m->m_next;			}			if (siz <= 0 || siz > NFS_MAXPACKET) {				printf("mbuf siz=%d\n",siz);				panic("Bad nfs svc reply");			}			m = mreq;			m->m_pkthdr.len = siz;			m->m_pkthdr.rcvif = (struct ifnet *)0;			/*			 * For stream protocols, prepend a Sun RPC			 * Record Mark.			 */			if (sotype == SOCK_STREAM) {				M_PREPEND(m, NFSX_UNSIGNED, M_WAIT);				*mtod(m, u_long *) = htonl(0x80000000 | siz);			}			if (solockp)				(void) nfs_sndlock(solockp, (struct nfsreq *)0);			if (slp->ns_flag & SLP_VALID)			    error = nfs_send(so, nam2, m, (struct nfsreq *)0);			else {			    error = EPIPE;			    m_freem(m);			}			if (nfsrtton)				nfsd_rt(&starttime, sotype, nd, nam, cacherep);			if (nam2)				MFREE(nam2, m);			if (nd->nd_mrep)				m_freem(nd->nd_mrep);			if (error == EPIPE)				nfsrv_zapsock(slp);			if (solockp)				nfs_sndunlock(solockp);			if (error == EINTR || error == ERESTART) {				nfsrv_slpderef(slp);				s = splnet();				goto done;			}			break;		case RC_DROPIT:			if (nfsrtton)				nfsd_rt(&starttime, sotype, nd, nam, cacherep);			m_freem(nd->nd_mrep);			m_freem(nam2);			break;		};		s = splnet();		if (nfsrv_dorec(slp, nd)) {			nd->nd_flag &= ~NFSD_REQINPROG;			nd->nd_slp = (struct nfssvc_sock *)0;			nfsrv_slpderef(slp);		}	}done:	remque(nd);	splx(s);	free((caddr_t)nd, M_NFSD);	nsd->nsd_nfsd = (struct nfsd *)0;	if (--nfs_numnfsd == 0)		nfsrv_init(TRUE);	/* Reinitialize everything */	return (error);}/* * 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. */nfssvc_iod(p)	struct proc *p;{	register struct buf *bp;	register int i, myiod;	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 (nfs_bufq.tqh_first == NULL && error == 0) {			nfs_iodwant[myiod] = p;			error = tsleep((caddr_t)&nfs_iodwant[myiod],				PWAIT | PCATCH, "nfsidl", 0);		}		while ((bp = nfs_bufq.tqh_first) != NULL) {			/* Take one off the front of the list */			TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);			if (bp->b_flags & B_READ)			    (void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);			else			    (void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);		}		if (error) {			nfs_asyncdaemon[myiod] = 0;			nfs_numasync--;			return (error);		}	}}/* * Shut down a socket associated with an nfssvc_sock structure. * Should be called with the send lock set, if required. * The trick here is to increment the sref at the start, so that the nfsds * will stop using it and clear ns_flag at the end so that it will not be * reassigned during cleanup. */nfsrv_zapsock(slp)	register struct nfssvc_sock *slp;{	register struct nfsuid *nuidp, *onuidp;	register int i;	struct socket *so;	struct file *fp;	struct mbuf *m;	slp->ns_flag &= ~SLP_ALLFLAGS;	if (fp = slp->ns_fp) {		slp->ns_fp = (struct file *)0;		so = slp->ns_so;		so->so_upcall = NULL;		soshutdown(so, 2);		closef(fp, (struct proc *)0);		if (slp->ns_nam)			MFREE(slp->ns_nam, m);		m_freem(slp->ns_raw);		m_freem(slp->ns_rec);		nuidp = slp->ns_lrunext;		while (nuidp != (struct nfsuid *)slp) {			onuidp = nuidp;			nuidp = nuidp->nu_lrunext;			free((caddr_t)onuidp, M_NFSUID);		}		slp->ns_lrunext = slp->ns_lruprev = (struct nfsuid *)slp;		for (i = 0; i < NUIDHASHSIZ; i++)			slp->ns_uidh[i] = (struct nfsuid *)0;	}}/* * 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. */nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)	register struct nfsmount *nmp;	struct nfsreq *rep;	struct ucred *cred;	int *auth_type;	char **auth_str;	int *auth_len;{	int error = 0;	while ((nmp->nm_flag & NFSMNT_WAITAUTH) == 0) {		nmp->nm_flag |= NFSMNT_WANTAUTH;		(void) tsleep((caddr_t)&nmp->nm_authtype, PSOCK,			"nfsauth1", 2 * hz);		if (error = nfs_sigintr(nmp, rep, rep->r_procp)) {			nmp->nm_flag &= ~NFSMNT_WANTAUTH;			return (error);		}	}	nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH);	nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK);	nmp->nm_authuid = cred->cr_uid;	wakeup((caddr_t)&nmp->nm_authstr);	/*	 * And wait for mount_nfs to do its stuff.	 */	while ((nmp->nm_flag & NFSMNT_HASAUTH) == 0 && error == 0) {		(void) tsleep((caddr_t)&nmp->nm_authlen, PSOCK,			"nfsauth2", 2 * hz);		error = nfs_sigintr(nmp, rep, rep->r_procp);	}	if (nmp->nm_flag & NFSMNT_AUTHERR) {		nmp->nm_flag &= ~NFSMNT_AUTHERR;		error = EAUTH;	}	if (error)		free((caddr_t)*auth_str, M_TEMP);	else {		*auth_type = nmp->nm_authtype;		*auth_len = nmp->nm_authlen;	}	nmp->nm_flag &= ~NFSMNT_HASAUTH;	nmp->nm_flag |= NFSMNT_WAITAUTH;	if (nmp->nm_flag & NFSMNT_WANTAUTH) {		nmp->nm_flag &= ~NFSMNT_WANTAUTH;		wakeup((caddr_t)&nmp->nm_authtype);	}	return (error);}/* * Derefence a server socket structure. If it has no more references and * is no longer valid, you can throw it away. */voidnfsrv_slpderef(slp)	register struct nfssvc_sock *slp;{	if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) {		slp->ns_prev->ns_next = slp->ns_next;		slp->ns_next->ns_prev = slp->ns_prev;		free((caddr_t)slp, M_NFSSVC);	}}/* * Initialize the data structures for the server. * Handshake with any new nfsds starting up to avoid any chance of * corruption. */voidnfsrv_init(terminating)	int terminating;{	register struct nfssvc_sock *slp;	struct nfssvc_sock *oslp;	if (nfssvc_sockhead.ns_flag & SLP_INIT)		panic("nfsd init");	nfssvc_sockhead.ns_flag |= SLP_INIT;	if (terminating) {		slp = nfssvc_sockhead.ns_next;		while (slp != &nfssvc_sockhead) {			if (slp->ns_flag & SLP_VALID)				nfsrv_zapsock(slp);			slp->ns_next->ns_prev = slp->ns_prev;			slp->ns_prev->ns_next = slp->ns_next;			oslp = slp;			slp = slp->ns_next;			free((caddr_t)oslp, M_NFSSVC);		}		nfsrv_cleancache();	/* And clear out server cache */	}	nfs_udpsock = (struct nfssvc_sock *)	    malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);	bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock));	nfs_cltpsock = (struct nfssvc_sock *)	    malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);	bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock));	nfssvc_sockhead.ns_next = nfs_udpsock;	nfs_udpsock->ns_next = nfs_cltpsock;	nfs_cltpsock->ns_next = &nfssvc_sockhead;	nfssvc_sockhead.ns_prev = nfs_cltpsock;	nfs_cltpsock->ns_prev = nfs_udpsock;	nfs_udpsock->ns_prev = &nfssvc_sockhead;	nfs_udpsock->ns_lrunext = nfs_udpsock->ns_lruprev =		(struct nfsuid *)nfs_udpsock;	nfs_cltpsock->ns_lrunext = nfs_cltpsock->ns_lruprev =		(struct nfsuid *)nfs_cltpsock;	nfsd_head.nd_next = nfsd_head.nd_prev = &nfsd_head;	nfsd_head.nd_flag = 0;	nfssvc_sockhead.ns_flag &= ~SLP_INIT;	if (nfssvc_sockhead.ns_flag & SLP_WANTINIT) {		nfssvc_sockhead.ns_flag &= ~SLP_WANTINIT;		wakeup((caddr_t)&nfssvc_sockhead);	}}/* * Add entries to the server monitor log. */static voidnfsd_rt(startp, sotype, nd, nam, cacherep)	struct timeval *startp;	int sotype;	register struct nfsd *nd;	struct mbuf *nam;	int cacherep;{	register struct drt *rt;	rt = &nfsdrt.drt[nfsdrt.pos];	if (cacherep == RC_DOIT)		rt->flag = 0;	else if (cacherep == RC_REPLY)		rt->flag = DRT_CACHEREPLY;	else		rt->flag = DRT_CACHEDROP;	if (sotype == SOCK_STREAM)		rt->flag |= DRT_TCP;	if (nd->nd_nqlflag != NQL_NOVAL)		rt->flag |= DRT_NQNFS;	rt->proc = nd->nd_procnum;	if (mtod(nam, struct sockaddr *)->sa_family == AF_INET)		rt->ipadr = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;	else		rt->ipadr = INADDR_ANY;	rt->resptime = ((time.tv_sec - startp->tv_sec) * 1000000) +		(time.tv_usec - startp->tv_usec);	rt->tstamp = time;	nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ;}

⌨️ 快捷键说明

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