📄 nfs_nqlease.c
字号:
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 + -