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

📄 nfs_nqlease.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (slp == NQLOCALSLP) {		if (lph->lph_flag & LC_LOCAL)			return (1);		else			return (0);	}	if (slp == nfs_udpsock || slp == nfs_cltpsock)		addr = nam;	else		addr = slp->ns_nam;	if (lph->lph_flag & LC_UDP)		ret = netaddr_match(AF_INET, &lph->lph_haddr, addr);	else if (lph->lph_flag & LC_CLTP)		ret = netaddr_match(AF_ISO, &lph->lph_claddr, addr);	else {		if ((lph->lph_slp->ns_flag & SLP_VALID) == 0)			return (0);		saddr = mtod(lph->lph_slp->ns_nam, struct sockaddr_in *);		if (saddr->sin_family == AF_INET)			lhaddr.had_inetaddr = saddr->sin_addr.s_addr;		else			lhaddr.had_nam = lph->lph_slp->ns_nam;		ret = netaddr_match(saddr->sin_family, &lhaddr, addr);	}	return (ret);}/* * Send out eviction notice messages to all other hosts for the lease. */voidnqsrv_send_eviction(vp, lp, slp, nam, cred)	struct vnode *vp;	register struct nqlease *lp;	struct nfssvc_sock *slp;	struct mbuf *nam;	struct ucred *cred;{	register struct nqhost *lph = &lp->lc_host;	register struct mbuf *m;	register int siz;	struct nqm *lphnext = lp->lc_morehosts;	struct mbuf *mreq, *mb, *mb2, *nam2, *mheadend;	struct socket *so;	struct sockaddr_in *saddr;	fhandle_t *fhp;	caddr_t bpos, cp;	u_long xid;	int len = 1, ok = 1, i = 0;	int sotype, *solockp;	while (ok && (lph->lph_flag & LC_VALID)) {		if (nqsrv_cmpnam(slp, nam, lph))			lph->lph_flag |= LC_VACATED;		else if ((lph->lph_flag & (LC_LOCAL | LC_VACATED)) == 0) {			if (lph->lph_flag & LC_UDP) {				MGET(nam2, M_WAIT, MT_SONAME);				saddr = mtod(nam2, struct sockaddr_in *);				nam2->m_len = saddr->sin_len =					sizeof (struct sockaddr_in);				saddr->sin_family = AF_INET;				saddr->sin_addr.s_addr = lph->lph_inetaddr;				saddr->sin_port = lph->lph_port;				so = nfs_udpsock->ns_so;			} else if (lph->lph_flag & LC_CLTP) {				nam2 = lph->lph_nam;				so = nfs_cltpsock->ns_so;			} else if (lph->lph_slp->ns_flag & SLP_VALID) {				nam2 = (struct mbuf *)0;				so = lph->lph_slp->ns_so;			} else				goto nextone;			sotype = so->so_type;			if (so->so_proto->pr_flags & PR_CONNREQUIRED)				solockp = &lph->lph_slp->ns_solock;			else				solockp = (int *)0;			nfsm_reqhead((struct vnode *)0, NQNFSPROC_EVICTED,				NFSX_FH);			nfsm_build(cp, caddr_t, NFSX_FH);			bzero(cp, NFSX_FH);			fhp = (fhandle_t *)cp;			fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;			VFS_VPTOFH(vp, &fhp->fh_fid);			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 = nfsm_rpchead(cred, TRUE, NQNFSPROC_EVICTED,				RPCAUTH_UNIX, 5*NFSX_UNSIGNED, (char *)0,				mreq, siz, &mheadend, &xid);			/*			 * 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 |					(m->m_pkthdr.len - NFSX_UNSIGNED));			}			if (((lph->lph_flag & (LC_UDP | LC_CLTP)) == 0 &&			    (lph->lph_slp->ns_flag & SLP_VALID) == 0) ||			    (solockp && (*solockp & NFSMNT_SNDLOCK)))				m_freem(m);			else {				if (solockp)					*solockp |= NFSMNT_SNDLOCK;				(void) nfs_send(so, nam2, m,						(struct nfsreq *)0);				if (solockp)					nfs_sndunlock(solockp);			}			if (lph->lph_flag & LC_UDP)				MFREE(nam2, m);		}nextone:		if (++i == len) {			if (lphnext) {				i = 0;				len = LC_MOREHOSTSIZ;				lph = lphnext->lpm_hosts;				lphnext = lphnext->lpm_next;			} else				ok = 0;		} else			lph++;	}}/* * Wait for the lease to expire. * This will occur when all clients have sent "vacated" messages to * this server OR when it expires do to timeout. */voidnqsrv_waitfor_expiry(lp)	register struct nqlease *lp;{	register struct nqhost *lph;	register int i;	struct nqm *lphnext;	int len, ok;tryagain:	if (time.tv_sec > lp->lc_expiry)		return;	lph = &lp->lc_host;	lphnext = lp->lc_morehosts;	len = 1;	i = 0;	ok = 1;	while (ok && (lph->lph_flag & LC_VALID)) {		if ((lph->lph_flag & (LC_LOCAL | LC_VACATED)) == 0) {			lp->lc_flag |= LC_EXPIREDWANTED;			(void) tsleep((caddr_t)&lp->lc_flag, PSOCK,					"nqexp", 0);			goto tryagain;		}		if (++i == len) {			if (lphnext) {				i = 0;				len = LC_MOREHOSTSIZ;				lph = lphnext->lpm_hosts;				lphnext = lphnext->lpm_next;			} else				ok = 0;		} else			lph++;	}}/* * Nqnfs server timer that maintains the server lease queue. * Scan the lease queue for expired entries: * - when one is found, wakeup anyone waiting for it *   else dequeue and free */voidnqnfs_serverd(){	register struct nqlease *lp, *lq;	register struct nqhost *lph;	struct nqlease *nextlp;	struct nqm *lphnext, *olphnext;	struct mbuf *n;	int i, len, ok;	lp = nqthead.th_chain[0];	while (lp != (struct nqlease *)&nqthead) {		if (lp->lc_expiry >= time.tv_sec)			break;		nextlp = lp->lc_chain1[0];		if (lp->lc_flag & LC_EXPIREDWANTED) {			lp->lc_flag &= ~LC_EXPIREDWANTED;			wakeup((caddr_t)&lp->lc_flag);		} else if ((lp->lc_flag & (LC_LOCKED | LC_WANTED)) == 0) {		    /*		     * Make a best effort at keeping a write caching lease long		     * enough by not deleting it until it has been explicitly		     * vacated or there have been no writes in the previous		     * write_slack seconds since expiry and the nfsds are not		     * all busy. The assumption is that if the nfsds are not		     * all busy now (no queue of nfs requests), then the client		     * would have been able to do at least one write to the		     * file during the last write_slack seconds if it was still		     * trying to push writes to the server.		     */		    if ((lp->lc_flag & (LC_WRITE | LC_VACATED)) == LC_WRITE &&			((lp->lc_flag & LC_WRITTEN) || nfsd_waiting == 0)) {			lp->lc_flag &= ~LC_WRITTEN;			nqsrv_instimeq(lp, nqsrv_writeslack);		    } else {			remque(lp);			if (lq = lp->lc_fhnext)				lq->lc_fhprev = lp->lc_fhprev;			*lp->lc_fhprev = lq;			/*			 * This soft reference may no longer be valid, but			 * no harm done. The worst case is if the vnode was			 * recycled and has another valid lease reference,			 * which is dereferenced prematurely.			 */			lp->lc_vp->v_lease = (struct nqlease *)0;			lph = &lp->lc_host;			lphnext = lp->lc_morehosts;			olphnext = (struct nqm *)0;			len = 1;			i = 0;			ok = 1;			while (ok && (lph->lph_flag & LC_VALID)) {				if (lph->lph_flag & LC_CLTP)					MFREE(lph->lph_nam, n);				if (lph->lph_flag & LC_SREF)					nfsrv_slpderef(lph->lph_slp);				if (++i == len) {					if (olphnext) {						free((caddr_t)olphnext, M_NQMHOST);						olphnext = (struct nqm *)0;					}					if (lphnext) {						olphnext = lphnext;						i = 0;						len = LC_MOREHOSTSIZ;						lph = lphnext->lpm_hosts;						lphnext = lphnext->lpm_next;					} else						ok = 0;				} else					lph++;			}			FREE((caddr_t)lp, M_NQLEASE);			if (olphnext)				free((caddr_t)olphnext, M_NQMHOST);			nfsstats.srvnqnfs_leases--;		    }		}		lp = nextlp;	}}/* * Called from nfssvc_nfsd() for a getlease rpc request. * Do the from/to xdr translation and call nqsrv_getlease() to * do the real work. */nqnfsrv_getlease(nfsd, mrep, md, dpos, cred, nam, mrq)	struct nfsd *nfsd;	struct mbuf *mrep, *md;	caddr_t dpos;	struct ucred *cred;	struct mbuf *nam, **mrq;{	register struct nfsv2_fattr *fp;	struct vattr va;	register struct vattr *vap = &va;	struct vnode *vp;	nfsv2fh_t nfh;	fhandle_t *fhp;	register u_long *tl;	register long t1;	u_quad_t frev;	caddr_t bpos;	int error = 0;	char *cp2;	struct mbuf *mb, *mb2, *mreq;	int flags, rdonly, cache;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);	flags = fxdr_unsigned(int, *tl++);	nfsd->nd_duration = fxdr_unsigned(int, *tl);	if (error = nfsrv_fhtovp(fhp,	    TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly))		nfsm_reply(0);	if (rdonly && flags == NQL_WRITE) {		error = EROFS;		nfsm_reply(0);	}	(void) nqsrv_getlease(vp, &nfsd->nd_duration, flags, nfsd,		nam, &cache, &frev, cred);	error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);	vput(vp);	nfsm_reply(NFSX_NQFATTR + 4*NFSX_UNSIGNED);	nfsm_build(tl, u_long *, 4*NFSX_UNSIGNED);	*tl++ = txdr_unsigned(cache);	*tl++ = txdr_unsigned(nfsd->nd_duration);	txdr_hyper(&frev, tl);	nfsm_build(fp, struct nfsv2_fattr *, NFSX_NQFATTR);	nfsm_srvfillattr;	nfsm_srvdone;}/* * Called from nfssvc_nfsd() when a "vacated" message is received from a * client. Find the entry and expire it. */nqnfsrv_vacated(nfsd, mrep, md, dpos, cred, nam, mrq)	struct nfsd *nfsd;	struct mbuf *mrep, *md;	caddr_t dpos;	struct ucred *cred;	struct mbuf *nam, **mrq;{	register struct nqlease *lp;	register struct nqhost *lph;	struct nqlease *tlp = (struct nqlease *)0;	nfsv2fh_t nfh;	fhandle_t *fhp;	register u_long *tl;	register long t1;	struct nqm *lphnext;	int error = 0, i, len, ok, gotit = 0;	char *cp2;	fhp = &nfh.fh_generic;	nfsm_srvmtofh(fhp);	m_freem(mrep);	/*	 * Find the lease by searching the hash list.	 */	for (lp = nqfhead[NQFHHASH(fhp->fh_fid.fid_data)]; lp;	     lp = lp->lc_fhnext)		if (fhp->fh_fsid.val[0] == lp->lc_fsid.val[0] &&		    fhp->fh_fsid.val[1] == lp->lc_fsid.val[1] &&		    !bcmp(fhp->fh_fid.fid_data, lp->lc_fiddata,			  MAXFIDSZ)) {			/* Found it */			tlp = lp;			break;		}	if (tlp) {		lp = tlp;		len = 1;		i = 0;		lph = &lp->lc_host;		lphnext = lp->lc_morehosts;		ok = 1;		while (ok && (lph->lph_flag & LC_VALID)) {			if (nqsrv_cmpnam(nfsd->nd_slp, nam, lph)) {				lph->lph_flag |= LC_VACATED;				gotit++;				break;			}			if (++i == len) {				if (lphnext) {					len = LC_MOREHOSTSIZ;					i = 0;					lph = lphnext->lpm_hosts;					lphnext = lphnext->lpm_next;				} else					ok = 0;			} else				lph++;		}		if ((lp->lc_flag & LC_EXPIREDWANTED) && gotit) {			lp->lc_flag &= ~LC_EXPIREDWANTED;			wakeup((caddr_t)&lp->lc_flag);		}nfsmout:		return (EPERM);	}	return (EPERM);}/* * Client get lease rpc function. */nqnfs_getlease(vp, rwflag, cred, p)	register struct vnode *vp;	int rwflag;	struct ucred *cred;	struct proc *p;{	register u_long *tl;	register caddr_t cp;	register long t1;	register struct nfsnode *np;	struct nfsmount *nmp = VFSTONFS(vp->v_mount);	caddr_t bpos, dpos, cp2;	time_t reqtime;	int error = 0;	struct mbuf *mreq, *mrep, *md, *mb, *mb2;	int cachable;

⌨️ 快捷键说明

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