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

📄 nfs_nqlease.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1992, 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_nqlease.c	8.3 (Berkeley) 1/4/94 *//* * References: *	Cary G. Gray and David R. Cheriton, "Leases: An Efficient Fault-Tolerant *		Mechanism for Distributed File Cache Consistency", *		In Proc. of the Twelfth ACM Symposium on Operating Systems *		Principals, pg. 202-210, Litchfield Park, AZ, Dec. 1989. *	Michael N. Nelson, Brent B. Welch and John K. Ousterhout, "Caching *		in the Sprite Network File System", ACM TOCS 6(1), *		pages 134-154, February 1988. *	V. Srinivasan and Jeffrey C. Mogul, "Spritely NFS: Implementation and *		Performance of Cache-Consistency Protocols", Digital *		Equipment Corporation WRL Research Report 89/5, May 1989. */#include <sys/param.h>#include <sys/vnode.h>#include <sys/mount.h>#include <sys/kernel.h>#include <sys/proc.h>#include <sys/systm.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/file.h>#include <sys/buf.h>#include <sys/stat.h>#include <sys/protosw.h>#include <netinet/in.h>#include <nfs/rpcv2.h>#include <nfs/nfsv2.h>#include <nfs/nfs.h>#include <nfs/nfsm_subs.h>#include <nfs/xdr_subs.h>#include <nfs/nqnfs.h>#include <nfs/nfsnode.h>#include <nfs/nfsmount.h>/* * List head for the lease queue and other global data. * At any time a lease is linked into a list ordered by increasing expiry time. */#define	NQFHHASH(f)	((*((u_long *)(f)))&nqfheadhash)union nqsrvthead nqthead;struct nqlease **nqfhead;u_long nqfheadhash;time_t nqnfsstarttime = (time_t)0;u_long nqnfs_prog, nqnfs_vers;int nqsrv_clockskew = NQ_CLOCKSKEW;int nqsrv_writeslack = NQ_WRITESLACK;int nqsrv_maxlease = NQ_MAXLEASE;int nqsrv_maxnumlease = NQ_MAXNUMLEASE;void nqsrv_instimeq(), nqsrv_send_eviction(), nfs_sndunlock();void nqsrv_unlocklease(), nqsrv_waitfor_expiry(), nfsrv_slpderef();void nqsrv_addhost(), nqsrv_locklease(), nqnfs_serverd();void nqnfs_clientlease();struct mbuf *nfsm_rpchead();/* * Signifies which rpcs can have piggybacked lease requests */int nqnfs_piggy[NFS_NPROCS] = {	0,	NQL_READ,	NQL_WRITE,	0,	NQL_READ,	NQL_READ,	NQL_READ,	0,	NQL_WRITE,	0,	0,	0,	0,	0,	0,	0,	NQL_READ,	0,	NQL_READ,	0,	0,	0,	0,};int nnnnnn = sizeof (struct nqlease);int oooooo = sizeof (struct nfsnode);extern nfstype nfs_type[9];extern struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock;extern struct nfsd nfsd_head;extern int nfsd_waiting;extern struct nfsreq nfsreqh;#define TRUE	1#define	FALSE	0/* * Get or check for a lease for "vp", based on NQL_CHECK flag. * The rules are as follows: * - if a current non-caching lease, reply non-caching * - if a current lease for same host only, extend lease * - if a read cachable lease and a read lease request *	add host to list any reply cachable * - else { set non-cachable for read-write sharing } *	send eviction notice messages to all other hosts that have lease *	wait for lease termination { either by receiving vacated messages *					from all the other hosts or expiry *					via. timeout } *	modify lease to non-cachable * - else if no current lease, issue new one * - reply * - return boolean TRUE iff nam should be m_freem()'d * NB: Since nqnfs_serverd() is called from a timer, any potential tsleep() *     in here must be framed by nqsrv_locklease() and nqsrv_unlocklease(). *     nqsrv_locklease() is coded such that at least one of LC_LOCKED and *     LC_WANTED is set whenever a process is tsleeping in it. The exception *     is when a new lease is being allocated, since it is not in the timer *     queue yet. (Ditto for the splsoftclock() and splx(s) calls) */nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)	struct vnode *vp;	u_long *duration;	int flags;	struct nfsd *nd;	struct mbuf *nam;	int *cachablep;	u_quad_t *frev;	struct ucred *cred;{	register struct nqlease *lp, *lq, **lpp;	register struct nqhost *lph;	struct nqlease *tlp;	struct nqm **lphp;	struct vattr vattr;	fhandle_t fh;	int i, ok, error, s;	if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)		return (0);	if (*duration > nqsrv_maxlease)		*duration = nqsrv_maxlease;	if (error = VOP_GETATTR(vp, &vattr, cred, nd->nd_procp))		return (error);	*frev = vattr.va_filerev;	s = splsoftclock();	tlp = vp->v_lease;	if ((flags & NQL_CHECK) == 0)		nfsstats.srvnqnfs_getleases++;	if (tlp == (struct nqlease *)0) {		/*		 * Find the lease by searching the hash list.		 */		fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;		if (error = VFS_VPTOFH(vp, &fh.fh_fid)) {			splx(s);			return (error);		}		lpp = &nqfhead[NQFHHASH(fh.fh_fid.fid_data)];		for (lp = *lpp; lp; lp = lp->lc_fhnext)			if (fh.fh_fsid.val[0] == lp->lc_fsid.val[0] &&			    fh.fh_fsid.val[1] == lp->lc_fsid.val[1] &&			    !bcmp(fh.fh_fid.fid_data, lp->lc_fiddata,				  fh.fh_fid.fid_len - sizeof (long))) {				/* Found it */				lp->lc_vp = vp;				vp->v_lease = lp;				tlp = lp;				break;			}	}	lp = tlp;	if (lp) {		if ((lp->lc_flag & LC_NONCACHABLE) ||		    (lp->lc_morehosts == (struct nqm *)0 &&		     nqsrv_cmpnam(nd->nd_slp, nam, &lp->lc_host)))			goto doreply;		if ((flags & NQL_READ) && (lp->lc_flag & LC_WRITE)==0) {			if (flags & NQL_CHECK)				goto doreply;			if (nqsrv_cmpnam(nd->nd_slp, nam, &lp->lc_host))				goto doreply;			i = 0;			if (lp->lc_morehosts) {				lph = lp->lc_morehosts->lpm_hosts;				lphp = &lp->lc_morehosts->lpm_next;				ok = 1;			} else {				lphp = &lp->lc_morehosts;				ok = 0;			}			while (ok && (lph->lph_flag & LC_VALID)) {				if (nqsrv_cmpnam(nd->nd_slp, nam, lph))					goto doreply;				if (++i == LC_MOREHOSTSIZ) {					i = 0;					if (*lphp) {						lph = (*lphp)->lpm_hosts;						lphp = &((*lphp)->lpm_next);					} else						ok = 0;				} else					lph++;			}			nqsrv_locklease(lp);			if (!ok) {				*lphp = (struct nqm *)					malloc(sizeof (struct nqm),						M_NQMHOST, M_WAITOK);				bzero((caddr_t)*lphp, sizeof (struct nqm));				lph = (*lphp)->lpm_hosts;			}			nqsrv_addhost(lph, nd->nd_slp, nam);			nqsrv_unlocklease(lp);		} else {			lp->lc_flag |= LC_NONCACHABLE;			nqsrv_locklease(lp);			nqsrv_send_eviction(vp, lp, nd->nd_slp, nam, cred);			nqsrv_waitfor_expiry(lp);			nqsrv_unlocklease(lp);		}doreply:		/*		 * Update the lease and return		 */		if ((flags & NQL_CHECK) == 0)			nqsrv_instimeq(lp, *duration);		if (lp->lc_flag & LC_NONCACHABLE)			*cachablep = 0;		else {			*cachablep = 1;			if (flags & NQL_WRITE)				lp->lc_flag |= LC_WRITTEN;		}		splx(s);		return (0);	}	splx(s);	if (flags & NQL_CHECK)		return (0);	/*	 * Allocate new lease	 * The value of nqsrv_maxnumlease should be set generously, so that	 * the following "printf" happens infrequently.	 */	if (nfsstats.srvnqnfs_leases > nqsrv_maxnumlease) {		printf("Nqnfs server, too many leases\n");		do {			(void) tsleep((caddr_t)&lbolt, PSOCK,					"nqsrvnuml", 0);		} while (nfsstats.srvnqnfs_leases > nqsrv_maxnumlease);	}	MALLOC(lp, struct nqlease *, sizeof (struct nqlease), M_NQLEASE, M_WAITOK);	bzero((caddr_t)lp, sizeof (struct nqlease));	if (flags & NQL_WRITE)		lp->lc_flag |= (LC_WRITE | LC_WRITTEN);	nqsrv_addhost(&lp->lc_host, nd->nd_slp, nam);	lp->lc_vp = vp;	lp->lc_fsid = fh.fh_fsid;	bcopy(fh.fh_fid.fid_data, lp->lc_fiddata, fh.fh_fid.fid_len - sizeof (long));	if (lq = *lpp)		lq->lc_fhprev = &lp->lc_fhnext;	lp->lc_fhnext = lq;	lp->lc_fhprev = lpp;	*lpp = lp;	vp->v_lease = lp;	s = splsoftclock();	nqsrv_instimeq(lp, *duration);	splx(s);	*cachablep = 1;	if (++nfsstats.srvnqnfs_leases > nfsstats.srvnqnfs_maxleases)		nfsstats.srvnqnfs_maxleases = nfsstats.srvnqnfs_leases;	return (0);}/* * Local lease check for server syscalls. * Just set up args and let nqsrv_getlease() do the rest. */voidlease_check(vp, p, cred, flag)	struct vnode *vp;	struct proc *p;	struct ucred *cred;	int flag;{	int duration = 0, cache;	struct nfsd nfsd;	u_quad_t frev;	nfsd.nd_slp = NQLOCALSLP;	nfsd.nd_procp = p;	(void) nqsrv_getlease(vp, &duration, NQL_CHECK | flag, &nfsd,		(struct mbuf *)0, &cache, &frev, cred);}/* * Add a host to an nqhost structure for a lease. */voidnqsrv_addhost(lph, slp, nam)	register struct nqhost *lph;	struct nfssvc_sock *slp;	struct mbuf *nam;{	register struct sockaddr_in *saddr;	if (slp == NQLOCALSLP)		lph->lph_flag |= (LC_VALID | LC_LOCAL);	else if (slp == nfs_udpsock) {		saddr = mtod(nam, struct sockaddr_in *);		lph->lph_flag |= (LC_VALID | LC_UDP);		lph->lph_inetaddr = saddr->sin_addr.s_addr;		lph->lph_port = saddr->sin_port;	} else if (slp == nfs_cltpsock) {		lph->lph_nam = m_copym(nam, 0, M_COPYALL, M_WAIT);		lph->lph_flag |= (LC_VALID | LC_CLTP);	} else {		lph->lph_flag |= (LC_VALID | LC_SREF);		lph->lph_slp = slp;		slp->ns_sref++;	}}/* * Update the lease expiry time and position it in the timer queue correctly. */voidnqsrv_instimeq(lp, duration)	register struct nqlease *lp;	u_long duration;{	register struct nqlease *tlp;	time_t newexpiry;	newexpiry = time.tv_sec + duration + nqsrv_clockskew;	if (lp->lc_expiry == newexpiry)		return;	if (lp->lc_chain1[0])		remque(lp);	lp->lc_expiry = newexpiry;	/*	 * Find where in the queue it should be.	 */	tlp = nqthead.th_chain[1];	while (tlp->lc_expiry > newexpiry && tlp != (struct nqlease *)&nqthead)		tlp = tlp->lc_chain1[1];	if (tlp == nqthead.th_chain[1])		NQSTORENOVRAM(newexpiry);	insque(lp, tlp);}/* * Compare the requesting host address with the lph entry in the lease. * Return true iff it is the same. * This is somewhat messy due to the union in the nqhost structure. * The local host is indicated by the special value of NQLOCALSLP for slp. */nqsrv_cmpnam(slp, nam, lph)	register struct nfssvc_sock *slp;	struct mbuf *nam;	register struct nqhost *lph;{	register struct sockaddr_in *saddr;	struct mbuf *addr;	union nethostaddr lhaddr;	int ret;

⌨️ 快捷键说明

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