📄 nfs_vnops.c
字号:
(error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1)) == EINTR) return (error); } nfsstats.rpccnt[NFSPROC_SETATTR]++; isnq = (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS); nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH+NFSX_SATTR(isnq)); nfsm_fhtom(vp); nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); if (vap->va_mode == (u_short)-1) sp->sa_mode = VNOVAL; else sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode); if (vap->va_uid == (uid_t)-1) sp->sa_uid = VNOVAL; else sp->sa_uid = txdr_unsigned(vap->va_uid); if (vap->va_gid == (gid_t)-1) sp->sa_gid = VNOVAL; else sp->sa_gid = txdr_unsigned(vap->va_gid); if (isnq) { txdr_hyper(&vap->va_size, &sp->sa_nqsize); txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); sp->sa_nqflags = txdr_unsigned(vap->va_flags); sp->sa_nqrdev = VNOVAL; } else { sp->sa_nfssize = txdr_unsigned(vap->va_size); txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); } nfsm_request(vp, NFSPROC_SETATTR, ap->a_p, ap->a_cred); nfsm_loadattr(vp, (struct vattr *)0); if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) && NQNFS_CKCACHABLE(vp, NQL_WRITE)) { nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); fxdr_hyper(tl, &frev); if (frev > np->n_brev) np->n_brev = frev; } nfsm_reqdone; if (error) { np->n_size = np->n_vattr.va_size = tsize; vnode_pager_setsize(vp, (u_long)np->n_size); } return (error);}/* * nfs lookup call, one step at a time... * First look in cache * If not found, unlock the directory nfsnode and do the rpc */intnfs_lookup(ap) struct vop_lookup_args /* { struct vnodeop_desc *a_desc; struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; } */ *ap;{ register struct componentname *cnp = ap->a_cnp; register struct vnode *dvp = ap->a_dvp; register struct vnode **vpp = ap->a_vpp; register int flags = cnp->cn_flags; register struct vnode *vdp; register u_long *tl; register caddr_t cp; register long t1, t2; struct nfsmount *nmp; caddr_t bpos, dpos, cp2; time_t reqtime; struct mbuf *mreq, *mrep, *md, *mb, *mb2; struct vnode *newvp; long len; nfsv2fh_t *fhp; struct nfsnode *np; int lockparent, wantparent, error = 0; int nqlflag, cachable; u_quad_t frev; *vpp = NULL; if (dvp->v_type != VDIR) return (ENOTDIR); lockparent = flags & LOCKPARENT; wantparent = flags & (LOCKPARENT|WANTPARENT); nmp = VFSTONFS(dvp->v_mount); np = VTONFS(dvp); if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { struct vattr vattr; int vpid; vdp = *vpp; vpid = vdp->v_id; /* * See the comment starting `Step through' in ufs/ufs_lookup.c * for an explanation of the locking protocol */ if (dvp == vdp) { VREF(vdp); error = 0; } else error = vget(vdp, 1); if (!error) { if (vpid == vdp->v_id) { if (nmp->nm_flag & NFSMNT_NQNFS) { if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) == 0) { nfsstats.lookupcache_hits++; if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) cnp->cn_flags |= SAVENAME; return (0); } else if (NQNFS_CKCACHABLE(dvp, NQL_READ)) { if (np->n_lrev != np->n_brev || (np->n_flag & NMODIFIED)) { np->n_direofoffset = 0; cache_purge(dvp); error = nfs_vinvalbuf(dvp, 0, cnp->cn_cred, cnp->cn_proc, 1); if (error == EINTR) return (error); np->n_brev = np->n_lrev; } else { nfsstats.lookupcache_hits++; if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) cnp->cn_flags |= SAVENAME; return (0); } } } else if (!VOP_GETATTR(vdp, &vattr, cnp->cn_cred, cnp->cn_proc) && vattr.va_ctime.ts_sec == VTONFS(vdp)->n_ctime) { nfsstats.lookupcache_hits++; if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) cnp->cn_flags |= SAVENAME; return (0); } cache_purge(vdp); } vrele(vdp); } *vpp = NULLVP; } error = 0; nfsstats.lookupcache_misses++; nfsstats.rpccnt[NFSPROC_LOOKUP]++; len = cnp->cn_namelen; nfsm_reqhead(dvp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); /* * For nqnfs optionally piggyback a getlease request for the name * being looked up. */ if (nmp->nm_flag & NFSMNT_NQNFS) { nfsm_build(tl, u_long *, NFSX_UNSIGNED); if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) && ((cnp->cn_flags & MAKEENTRY) && (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)))) *tl = txdr_unsigned(nmp->nm_leaseterm); else *tl = 0; } nfsm_fhtom(dvp); nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); reqtime = time.tv_sec; nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred);nfsmout: if (error) { if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && (flags & ISLASTCN) && error == ENOENT) error = EJUSTRETURN; if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) cnp->cn_flags |= SAVENAME; return (error); } if (nmp->nm_flag & NFSMNT_NQNFS) { nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); if (*tl) { nqlflag = fxdr_unsigned(int, *tl); nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED); cachable = fxdr_unsigned(int, *tl++); reqtime += fxdr_unsigned(int, *tl++); fxdr_hyper(tl, &frev); } else nqlflag = 0; } nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH); /* * Handle RENAME case... */ if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { m_freem(mrep); return (EISDIR); } if (error = nfs_nget(dvp->v_mount, fhp, &np)) { m_freem(mrep); return (error); } newvp = NFSTOV(np); if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { vrele(newvp); m_freem(mrep); return (error); } *vpp = newvp; m_freem(mrep); cnp->cn_flags |= SAVENAME; return (0); } if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { VREF(dvp); newvp = dvp; } else { if (error = nfs_nget(dvp->v_mount, fhp, &np)) { m_freem(mrep); return (error); } newvp = NFSTOV(np); } if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { vrele(newvp); m_freem(mrep); return (error); } m_freem(mrep); *vpp = newvp; if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) cnp->cn_flags |= SAVENAME; if ((cnp->cn_flags & MAKEENTRY) && (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) np->n_ctime = np->n_vattr.va_ctime.ts_sec; else if (nqlflag && reqtime > time.tv_sec) nqnfs_clientlease(nmp, np, nqlflag, cachable, reqtime, frev); cache_enter(dvp, *vpp, cnp); } return (0);}/* * nfs read call. * Just call nfs_bioread() to do the work. */intnfs_read(ap) struct vop_read_args /* { struct vnode *a_vp; struct uio *a_uio; int a_ioflag; struct ucred *a_cred; } */ *ap;{ register struct vnode *vp = ap->a_vp; if (vp->v_type != VREG) return (EPERM); return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred));}/* * nfs readlink call */intnfs_readlink(ap) struct vop_readlink_args /* { struct vnode *a_vp; struct uio *a_uio; struct ucred *a_cred; } */ *ap;{ register struct vnode *vp = ap->a_vp; if (vp->v_type != VLNK) return (EPERM); return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred));}/* * Do a readlink rpc. * Called by nfs_doio() from below the buffer cache. */intnfs_readlinkrpc(vp, uiop, cred) register struct vnode *vp; struct uio *uiop; struct ucred *cred;{ register u_long *tl; register caddr_t cp; register long t1; caddr_t bpos, dpos, cp2; int error = 0; struct mbuf *mreq, *mrep, *md, *mb, *mb2; long len; nfsstats.rpccnt[NFSPROC_READLINK]++; nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH); nfsm_fhtom(vp); nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); nfsm_strsiz(len, NFS_MAXPATHLEN); nfsm_mtouio(uiop, len); nfsm_reqdone; return (error);}/* * nfs read rpc call * Ditto above */intnfs_readrpc(vp, uiop, cred) register struct vnode *vp; struct uio *uiop; struct ucred *cred;{ register u_long *tl; register caddr_t cp; register long t1; caddr_t bpos, dpos, cp2; int error = 0; struct mbuf *mreq, *mrep, *md, *mb, *mb2; struct nfsmount *nmp; long len, retlen, tsiz; nmp = VFSTONFS(vp->v_mount); tsiz = uiop->uio_resid; if (uiop->uio_offset + tsiz > 0xffffffff && (nmp->nm_flag & NFSMNT_NQNFS) == 0) return (EFBIG); while (tsiz > 0) { nfsstats.rpccnt[NFSPROC_READ]++; len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH+NFSX_UNSIGNED*3); nfsm_fhtom(vp); nfsm_build(tl, u_long *, NFSX_UNSIGNED*3); if (nmp->nm_flag & NFSMNT_NQNFS) { txdr_hyper(&uiop->uio_offset, tl); *(tl + 2) = txdr_unsigned(len); } else { *tl++ = txdr_unsigned(uiop->uio_offset); *tl++ = txdr_unsigned(len); *tl = 0; } nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred); nfsm_loadattr(vp, (struct vattr *)0); nfsm_strsiz(retlen, nmp->nm_rsize); nfsm_mtouio(uiop, retlen); m_freem(mrep); if (retlen < len) tsiz = 0; else tsiz -= len; }nfsmout: return (error);}/* * nfs write call */intnfs_writerpc(vp, uiop, cred, ioflags) register struct vnode *vp; struct uio *uiop; struct ucred *cred; int ioflags;{ register u_long *tl; register caddr_t cp; register long t1; caddr_t bpos, dpos, cp2; int error = 0; struct mbuf *mreq, *mrep, *md, *mb, *mb2; struct nfsmount *nmp; struct nfsnode *np = VTONFS(vp); u_quad_t frev; long len, tsiz; nmp = VFSTONFS(vp->v_mount); tsiz = uiop->uio_resid; if (uiop->uio_offset + tsiz > 0xffffffff && (nmp->nm_flag & NFSMNT_NQNFS) == 0) return (EFBIG); while (tsiz > 0) { nfsstats.rpccnt[NFSPROC_WRITE]++; len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; nfsm_reqhead(vp, NFSPROC_WRITE, NFSX_FH+NFSX_UNSIGNED*4+nfsm_rndup(len)); nfsm_fhtom(vp); nfsm_build(tl, u_long *, NFSX_UNSIGNED * 4); if (nmp->nm_flag & NFSMNT_NQNFS) { txdr_hyper(&uiop->uio_offset, tl); tl += 2; if (ioflags & IO_APPEND) *tl++ = txdr_unsigned(1); else *tl++ = 0; } else { *++tl = txdr_unsigned(uiop->uio_offset); tl += 2; } *tl = txdr_unsigned(len); nfsm_uiotom(uiop, len); nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred); nfsm_loadattr(vp, (struct vattr *)0); if (nmp->nm_flag & NFSMNT_MYWRITE) VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.ts_sec; else if ((nmp->nm_flag & NFSMNT_NQNFS) && NQNFS_CKCACHABLE(vp, NQL_WRITE)) { nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); fxdr_hyper(tl, &frev); if (frev > np->n_brev) np->n_brev = frev; } m_freem(mrep); tsiz -= len; }nfsmout: if (error) uiop->uio_resid = tsiz; return (error);}/* * nfs mknod call * This is a kludge. Use a create rpc but with the IFMT bits of the mode * set to specify the file type and the size field for rdev. *//* ARGSUSED */intnfs_mknod(ap) struct vop_mknod_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; } */ *ap;{ register struct vnode *dvp = ap->a_dvp; register struct vattr *vap = ap->a_vap; register struct componentname *cnp = ap->a_cnp; register struct nfsv2_sattr *sp; register u_long *tl; register caddr_t cp; register long t1, t2; struct vnode *newvp; struct vattr vattr; char *cp2; caddr_t bpos, dpos; int error = 0, isnq; struct mbuf *mreq, *mrep, *md, *mb, *mb2; u_long rdev; isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); if (vap->va_type == VCHR || vap->va_type == VBLK) rdev = txdr_unsigned(vap->va_rdev);#ifdef FIFO else if (vap->va_type == VFIFO) rdev = 0xffffffff;#endif /* FIFO */ else { VOP_ABORTOP(dvp, cnp); vput(dvp); return (EOPNOTSUPP); } if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { VOP_ABORTOP(dvp, cnp); vput(dvp); return (error); } nfsstats.rpccnt[NFSPROC_CREATE]++; nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR(isnq)); nfsm_fhtom(dvp); nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode); sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); sp->sa_gid = txdr_unsigned(vattr.va_gid); if (isnq) { sp->sa_nqrdev = rdev; sp->sa_nqflags = 0; txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); } else { sp->sa_nfssize = rdev; txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); } nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); nfsm_mtofh(dvp, newvp); nfsm_reqdone;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -