📄 nfs_nqlease.c
字号:
u_quad_t frev; nfsstats.rpccnt[NQNFSPROC_GETLEASE]++; mb = mreq = nfsm_reqh(vp, NQNFSPROC_GETLEASE, NFSX_FH+2*NFSX_UNSIGNED, &bpos); nfsm_fhtom(vp); nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED); *tl++ = txdr_unsigned(rwflag); *tl = txdr_unsigned(nmp->nm_leaseterm); reqtime = time.tv_sec; nfsm_request(vp, NQNFSPROC_GETLEASE, p, cred); np = VTONFS(vp); nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED); cachable = fxdr_unsigned(int, *tl++); reqtime += fxdr_unsigned(int, *tl++); if (reqtime > time.tv_sec) { fxdr_hyper(tl, &frev); nqnfs_clientlease(nmp, np, rwflag, cachable, reqtime, frev); nfsm_loadattr(vp, (struct vattr *)0); } else error = NQNFS_EXPIRED; nfsm_reqdone; return (error);}/* * Client vacated message function. */nqnfs_vacated(vp, cred) register struct vnode *vp; struct ucred *cred;{ register caddr_t cp; register struct mbuf *m; register int i; caddr_t bpos; u_long xid; int error = 0; struct mbuf *mreq, *mb, *mb2, *mheadend; struct nfsmount *nmp; struct nfsreq myrep; nmp = VFSTONFS(vp->v_mount); nfsstats.rpccnt[NQNFSPROC_VACATED]++; nfsm_reqhead(vp, NQNFSPROC_VACATED, NFSX_FH); nfsm_fhtom(vp); m = mreq; i = 0; while (m) { i += m->m_len; m = m->m_next; } m = nfsm_rpchead(cred, TRUE, NQNFSPROC_VACATED, RPCAUTH_UNIX, 5*NFSX_UNSIGNED, (char *)0, mreq, i, &mheadend, &xid); if (nmp->nm_sotype == SOCK_STREAM) { M_PREPEND(m, NFSX_UNSIGNED, M_WAIT); *mtod(m, u_long *) = htonl(0x80000000 | (m->m_pkthdr.len - NFSX_UNSIGNED)); } myrep.r_flags = 0; myrep.r_nmp = nmp; if (nmp->nm_soflags & PR_CONNREQUIRED) (void) nfs_sndlock(&nmp->nm_flag, (struct nfsreq *)0); (void) nfs_send(nmp->nm_so, nmp->nm_nam, m, &myrep); if (nmp->nm_soflags & PR_CONNREQUIRED) nfs_sndunlock(&nmp->nm_flag); return (error);}/* * Called for client side callbacks */nqnfs_callback(nmp, mrep, md, dpos) struct nfsmount *nmp; struct mbuf *mrep, *md; caddr_t dpos;{ register struct vnode *vp; register u_long *tl; register long t1; nfsv2fh_t nfh; fhandle_t *fhp; struct nfsnode *np; struct nfsd nd; int error; char *cp2; nd.nd_mrep = mrep; nd.nd_md = md; nd.nd_dpos = dpos; if (error = nfs_getreq(&nd, FALSE)) return (error); md = nd.nd_md; dpos = nd.nd_dpos; if (nd.nd_procnum != NQNFSPROC_EVICTED) { m_freem(mrep); return (EPERM); } fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); m_freem(mrep); if (error = nfs_nget(nmp->nm_mountp, fhp, &np)) return (error); vp = NFSTOV(np); if (np->n_tnext) { np->n_expiry = 0; np->n_flag |= NQNFSEVICTED; if (np->n_tprev != (struct nfsnode *)nmp) { if (np->n_tnext == (struct nfsnode *)nmp) nmp->nm_tprev = np->n_tprev; else np->n_tnext->n_tprev = np->n_tprev; np->n_tprev->n_tnext = np->n_tnext; np->n_tnext = nmp->nm_tnext; nmp->nm_tnext = np; np->n_tprev = (struct nfsnode *)nmp; if (np->n_tnext == (struct nfsnode *)nmp) nmp->nm_tprev = np; else np->n_tnext->n_tprev = np; } } vrele(vp); nfsm_srvdone;}/* * Nqnfs client helper daemon. Runs once a second to expire leases. * It also get authorization strings for "kerb" mounts. * It must start at the beginning of the list again after any potential * "sleep" since nfs_reclaim() called from vclean() can pull a node off * the list asynchronously. */nqnfs_clientd(nmp, cred, ncd, flag, argp, p) register struct nfsmount *nmp; struct ucred *cred; struct nfsd_cargs *ncd; int flag; caddr_t argp; struct proc *p;{ register struct nfsnode *np; struct vnode *vp; struct nfsreq myrep; int error, vpid; /* * First initialize some variables */ nqnfs_prog = txdr_unsigned(NQNFS_PROG); nqnfs_vers = txdr_unsigned(NQNFS_VER1); /* * If an authorization string is being passed in, get it. */ if ((flag & NFSSVC_GOTAUTH) && (nmp->nm_flag & (NFSMNT_WAITAUTH | NFSMNT_DISMNT)) == 0) { if (nmp->nm_flag & NFSMNT_HASAUTH) panic("cld kerb"); if ((flag & NFSSVC_AUTHINFAIL) == 0) { if (ncd->ncd_authlen <= RPCAUTH_MAXSIZ && copyin(ncd->ncd_authstr, nmp->nm_authstr, ncd->ncd_authlen) == 0) { nmp->nm_authtype = ncd->ncd_authtype; nmp->nm_authlen = ncd->ncd_authlen; } else nmp->nm_flag |= NFSMNT_AUTHERR; } else nmp->nm_flag |= NFSMNT_AUTHERR; nmp->nm_flag |= NFSMNT_HASAUTH; wakeup((caddr_t)&nmp->nm_authlen); } else nmp->nm_flag |= NFSMNT_WAITAUTH; /* * Loop every second updating queue until there is a termination sig. */ while ((nmp->nm_flag & NFSMNT_DISMNT) == 0) { if (nmp->nm_flag & NFSMNT_NQNFS) { /* * If there are no outstanding requests (and therefore no * processes in nfs_reply) and there is data in the receive * queue, poke for callbacks. */ if (nfsreqh.r_next == &nfsreqh && nmp->nm_so && nmp->nm_so->so_rcv.sb_cc > 0) { myrep.r_flags = R_GETONEREP; myrep.r_nmp = nmp; myrep.r_mrep = (struct mbuf *)0; myrep.r_procp = (struct proc *)0; (void) nfs_reply(&myrep); } /* * Loop through the leases, updating as required. */ np = nmp->nm_tnext; while (np != (struct nfsnode *)nmp && (nmp->nm_flag & NFSMNT_DISMINPROG) == 0) { vp = NFSTOV(np);if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash2"); vpid = vp->v_id; if (np->n_expiry < time.tv_sec) { if (vget(vp, 1) == 0) { nmp->nm_inprog = vp; if (vpid == vp->v_id) {if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash3"); if (np->n_tnext == (struct nfsnode *)nmp) nmp->nm_tprev = np->n_tprev; else np->n_tnext->n_tprev = np->n_tprev; if (np->n_tprev == (struct nfsnode *)nmp) nmp->nm_tnext = np->n_tnext; else np->n_tprev->n_tnext = np->n_tnext; np->n_tnext = (struct nfsnode *)0; if ((np->n_flag & (NMODIFIED | NQNFSEVICTED)) && vp->v_type == VREG) { if (np->n_flag & NQNFSEVICTED) { (void) nfs_vinvalbuf(vp, V_SAVE, cred, p, 0); np->n_flag &= ~NQNFSEVICTED; (void) nqnfs_vacated(vp, cred); } else { (void) VOP_FSYNC(vp, cred, MNT_WAIT, p); np->n_flag &= ~NMODIFIED; } } } vrele(vp); nmp->nm_inprog = NULLVP; } if (np != nmp->nm_tnext) np = nmp->nm_tnext; else break; } else if ((np->n_expiry - NQ_RENEWAL) < time.tv_sec) { if ((np->n_flag & (NQNFSWRITE | NQNFSNONCACHE)) == NQNFSWRITE && vp->v_dirtyblkhd.lh_first && vget(vp, 1) == 0) { nmp->nm_inprog = vp;if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash4"); if (vpid == vp->v_id && nqnfs_getlease(vp, NQL_WRITE, cred, p)==0) np->n_brev = np->n_lrev; vrele(vp); nmp->nm_inprog = NULLVP; } if (np != nmp->nm_tnext) np = nmp->nm_tnext; else break; } else break; } } /* * Get an authorization string, if required. */ if ((nmp->nm_flag & (NFSMNT_WAITAUTH | NFSMNT_DISMNT | NFSMNT_HASAUTH)) == 0) { ncd->ncd_authuid = nmp->nm_authuid; if (copyout((caddr_t)ncd, argp, sizeof (struct nfsd_cargs))) nmp->nm_flag |= NFSMNT_WAITAUTH; else return (ENEEDAUTH); } /* * Wait a bit (no pun) and do it again. */ if ((nmp->nm_flag & NFSMNT_DISMNT) == 0 && (nmp->nm_flag & (NFSMNT_WAITAUTH | NFSMNT_HASAUTH))) { error = tsleep((caddr_t)&nmp->nm_authstr, PSOCK | PCATCH, "nqnfstimr", hz / 3); if (error == EINTR || error == ERESTART) (void) dounmount(nmp->nm_mountp, 0, p); } } free((caddr_t)nmp, M_NFSMNT); if (error == EWOULDBLOCK) error = 0; return (error);}/* * Adjust all timer queue expiry times when the time of day clock is changed. * Called from the settimeofday() syscall. */voidlease_updatetime(deltat) register int deltat;{ register struct nqlease *lp; register struct nfsnode *np; struct mount *mp; struct nfsmount *nmp; int s; if (nqnfsstarttime != 0) nqnfsstarttime += deltat; s = splsoftclock(); lp = nqthead.th_chain[0]; while (lp != (struct nqlease *)&nqthead) { lp->lc_expiry += deltat; lp = lp->lc_chain1[0]; } splx(s); /* * Search the mount list for all nqnfs mounts and do their timer * queues. */ for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) { if (mp->mnt_stat.f_fsid.val[1] == MOUNT_NFS) { nmp = VFSTONFS(mp); if (nmp->nm_flag & NFSMNT_NQNFS) { np = nmp->nm_tnext; while (np != (struct nfsnode *)nmp) { np->n_expiry += deltat; np = np->n_tnext; } } } }}/* * Lock a server lease. */voidnqsrv_locklease(lp) struct nqlease *lp;{ while (lp->lc_flag & LC_LOCKED) { lp->lc_flag |= LC_WANTED; (void) tsleep((caddr_t)lp, PSOCK, "nqlc", 0); } lp->lc_flag |= LC_LOCKED; lp->lc_flag &= ~LC_WANTED;}/* * Unlock a server lease. */voidnqsrv_unlocklease(lp) struct nqlease *lp;{ lp->lc_flag &= ~LC_LOCKED; if (lp->lc_flag & LC_WANTED) wakeup((caddr_t)lp);}/* * Update a client lease. */voidnqnfs_clientlease(nmp, np, rwflag, cachable, expiry, frev) register struct nfsmount *nmp; register struct nfsnode *np; int rwflag, cachable; time_t expiry; u_quad_t frev;{ register struct nfsnode *tp; if (np->n_tnext) { if (np->n_tnext == (struct nfsnode *)nmp) nmp->nm_tprev = np->n_tprev; else np->n_tnext->n_tprev = np->n_tprev; if (np->n_tprev == (struct nfsnode *)nmp) nmp->nm_tnext = np->n_tnext; else np->n_tprev->n_tnext = np->n_tnext; if (rwflag == NQL_WRITE) np->n_flag |= NQNFSWRITE; } else if (rwflag == NQL_READ) np->n_flag &= ~NQNFSWRITE; else np->n_flag |= NQNFSWRITE; if (cachable) np->n_flag &= ~NQNFSNONCACHE; else np->n_flag |= NQNFSNONCACHE; np->n_expiry = expiry; np->n_lrev = frev; tp = nmp->nm_tprev; while (tp != (struct nfsnode *)nmp && tp->n_expiry > np->n_expiry) tp = tp->n_tprev; if (tp == (struct nfsnode *)nmp) { np->n_tnext = nmp->nm_tnext; nmp->nm_tnext = np; } else { np->n_tnext = tp->n_tnext; tp->n_tnext = np; } np->n_tprev = tp; if (np->n_tnext == (struct nfsnode *)nmp) nmp->nm_tprev = np; else np->n_tnext->n_tprev = np;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -