📄 nfs_vnops.c
字号:
if (!error && (cnp->cn_flags & MAKEENTRY)) cache_enter(dvp, newvp, cnp); FREE(cnp->cn_pnbuf, M_NAMEI); VTONFS(dvp)->n_flag |= NMODIFIED; VTONFS(dvp)->n_attrstamp = 0; vrele(dvp); return (error);}/* * nfs file create call */intnfs_create(ap) struct vop_create_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; caddr_t bpos, dpos, cp2; int error = 0, isnq; struct mbuf *mreq, *mrep, *md, *mb, *mb2; struct vattr vattr; if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { VOP_ABORTOP(dvp, cnp); vput(dvp); return (error); } nfsstats.rpccnt[NFSPROC_CREATE]++; isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 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) { u_quad_t qval = 0; txdr_hyper(&qval, &sp->sa_nqsize); sp->sa_nqflags = 0; sp->sa_nqrdev = -1; txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); } else { sp->sa_nfssize = 0; 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, *ap->a_vpp); nfsm_reqdone; if (!error && (cnp->cn_flags & MAKEENTRY)) cache_enter(dvp, *ap->a_vpp, cnp); FREE(cnp->cn_pnbuf, M_NAMEI); VTONFS(dvp)->n_flag |= NMODIFIED; VTONFS(dvp)->n_attrstamp = 0; vrele(dvp); return (error);}/* * nfs file remove call * To try and make nfs semantics closer to ufs semantics, a file that has * other processes using the vnode is renamed instead of removed and then * removed later on the last close. * - If v_usecount > 1 * If a rename is not already in the works * call nfs_sillyrename() to set it up * else * do the remove rpc */intnfs_remove(ap) struct vop_remove_args /* { struct vnodeop_desc *a_desc; struct vnode * a_dvp; struct vnode * a_vp; struct componentname * a_cnp; } */ *ap;{ register struct vnode *vp = ap->a_vp; register struct vnode *dvp = ap->a_dvp; register struct componentname *cnp = ap->a_cnp; register struct nfsnode *np = VTONFS(vp); register u_long *tl; register caddr_t cp; register long t2; caddr_t bpos, dpos; int error = 0; struct mbuf *mreq, *mrep, *md, *mb, *mb2; if (vp->v_usecount > 1) { if (!np->n_sillyrename) error = nfs_sillyrename(dvp, vp, cnp); } else { /* * Purge the name cache so that the chance of a lookup for * the name succeeding while the remove is in progress is * minimized. Without node locking it can still happen, such * that an I/O op returns ESTALE, but since you get this if * another host removes the file.. */ cache_purge(vp); /* * Throw away biocache buffers. Mainly to avoid * unnecessary delayed writes. */ error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); if (error == EINTR) return (error); /* Do the rpc */ nfsstats.rpccnt[NFSPROC_REMOVE]++; nfsm_reqhead(dvp, NFSPROC_REMOVE, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); nfsm_fhtom(dvp); nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); nfsm_request(dvp, NFSPROC_REMOVE, cnp->cn_proc, cnp->cn_cred); nfsm_reqdone; FREE(cnp->cn_pnbuf, M_NAMEI); VTONFS(dvp)->n_flag |= NMODIFIED; VTONFS(dvp)->n_attrstamp = 0; /* * Kludge City: If the first reply to the remove rpc is lost.. * the reply to the retransmitted request will be ENOENT * since the file was in fact removed * Therefore, we cheat and return success. */ if (error == ENOENT) error = 0; } np->n_attrstamp = 0; vrele(dvp); vrele(vp); return (error);}/* * nfs file remove rpc called from nfs_inactive */intnfs_removeit(sp) register struct sillyrename *sp;{ register u_long *tl; register caddr_t cp; register long t2; caddr_t bpos, dpos; int error = 0; struct mbuf *mreq, *mrep, *md, *mb, *mb2; nfsstats.rpccnt[NFSPROC_REMOVE]++; nfsm_reqhead(sp->s_dvp, NFSPROC_REMOVE, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(sp->s_namlen)); nfsm_fhtom(sp->s_dvp); nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN); nfsm_request(sp->s_dvp, NFSPROC_REMOVE, NULL, sp->s_cred); nfsm_reqdone; VTONFS(sp->s_dvp)->n_flag |= NMODIFIED; VTONFS(sp->s_dvp)->n_attrstamp = 0; return (error);}/* * nfs file rename call */intnfs_rename(ap) struct vop_rename_args /* { struct vnode *a_fdvp; struct vnode *a_fvp; struct componentname *a_fcnp; struct vnode *a_tdvp; struct vnode *a_tvp; struct componentname *a_tcnp; } */ *ap;{ register struct vnode *fvp = ap->a_fvp; register struct vnode *tvp = ap->a_tvp; register struct vnode *fdvp = ap->a_fdvp; register struct vnode *tdvp = ap->a_tdvp; register struct componentname *tcnp = ap->a_tcnp; register struct componentname *fcnp = ap->a_fcnp; register u_long *tl; register caddr_t cp; register long t2; caddr_t bpos, dpos; int error = 0; struct mbuf *mreq, *mrep, *md, *mb, *mb2; /* Check for cross-device rename */ if ((fvp->v_mount != tdvp->v_mount) || (tvp && (fvp->v_mount != tvp->v_mount))) { error = EXDEV; goto out; } nfsstats.rpccnt[NFSPROC_RENAME]++; nfsm_reqhead(fdvp, NFSPROC_RENAME, (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(fcnp->cn_namelen)+ nfsm_rndup(fcnp->cn_namelen)); /* or fcnp->cn_cred?*/ nfsm_fhtom(fdvp); nfsm_strtom(fcnp->cn_nameptr, fcnp->cn_namelen, NFS_MAXNAMLEN); nfsm_fhtom(tdvp); nfsm_strtom(tcnp->cn_nameptr, tcnp->cn_namelen, NFS_MAXNAMLEN); nfsm_request(fdvp, NFSPROC_RENAME, tcnp->cn_proc, tcnp->cn_cred); nfsm_reqdone; VTONFS(fdvp)->n_flag |= NMODIFIED; VTONFS(fdvp)->n_attrstamp = 0; VTONFS(tdvp)->n_flag |= NMODIFIED; VTONFS(tdvp)->n_attrstamp = 0; if (fvp->v_type == VDIR) { if (tvp != NULL && tvp->v_type == VDIR) cache_purge(tdvp); cache_purge(fdvp); }out: if (tdvp == tvp) vrele(tdvp); else vput(tdvp); if (tvp) vput(tvp); vrele(fdvp); vrele(fvp); /* * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. */ if (error == ENOENT) error = 0; return (error);}/* * nfs file rename rpc called from nfs_remove() above */intnfs_renameit(sdvp, scnp, sp) struct vnode *sdvp; struct componentname *scnp; register struct sillyrename *sp;{ register u_long *tl; register caddr_t cp; register long t2; caddr_t bpos, dpos; int error = 0; struct mbuf *mreq, *mrep, *md, *mb, *mb2; nfsstats.rpccnt[NFSPROC_RENAME]++; nfsm_reqhead(sdvp, NFSPROC_RENAME, (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(scnp->cn_namelen)+ nfsm_rndup(sp->s_namlen)); nfsm_fhtom(sdvp); nfsm_strtom(scnp->cn_nameptr, scnp->cn_namelen, NFS_MAXNAMLEN); nfsm_fhtom(sdvp); nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN); nfsm_request(sdvp, NFSPROC_RENAME, scnp->cn_proc, scnp->cn_cred); nfsm_reqdone; FREE(scnp->cn_pnbuf, M_NAMEI); VTONFS(sdvp)->n_flag |= NMODIFIED; VTONFS(sdvp)->n_attrstamp = 0; return (error);}/* * nfs hard link create call */intnfs_link(ap) struct vop_link_args /* { struct vnode *a_vp; struct vnode *a_tdvp; struct componentname *a_cnp; } */ *ap;{ register struct vnode *vp = ap->a_vp; register struct vnode *tdvp = ap->a_tdvp; register struct componentname *cnp = ap->a_cnp; register u_long *tl; register caddr_t cp; register long t2; caddr_t bpos, dpos; int error = 0; struct mbuf *mreq, *mrep, *md, *mb, *mb2; if (vp->v_mount != tdvp->v_mount) { /*VOP_ABORTOP(vp, cnp);*/ if (tdvp == vp) vrele(vp); else vput(vp); return (EXDEV); } nfsstats.rpccnt[NFSPROC_LINK]++; nfsm_reqhead(tdvp, NFSPROC_LINK, NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); nfsm_fhtom(tdvp); nfsm_fhtom(vp); nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); nfsm_request(tdvp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); nfsm_reqdone; FREE(cnp->cn_pnbuf, M_NAMEI); VTONFS(tdvp)->n_attrstamp = 0; VTONFS(tdvp)->n_flag |= NMODIFIED; VTONFS(vp)->n_attrstamp = 0; vrele(vp); /* * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. */ if (error == EEXIST) error = 0; return (error);}/* * nfs symbolic link create call *//* start here */intnfs_symlink(ap) struct vop_symlink_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; char *a_target; } */ *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 t2; caddr_t bpos, dpos; int slen, error = 0, isnq; struct mbuf *mreq, *mrep, *md, *mb, *mb2; nfsstats.rpccnt[NFSPROC_SYMLINK]++; slen = strlen(ap->a_target); isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH+2*NFSX_UNSIGNED+ nfsm_rndup(cnp->cn_namelen)+nfsm_rndup(slen)+NFSX_SATTR(isnq)); nfsm_fhtom(dvp); nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN); nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode); sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); if (isnq) { quad_t qval = -1; txdr_hyper(&qval, &sp->sa_nqsize); sp->sa_nqflags = 0; txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); } else { sp->sa_nfssize = -1; txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); } nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); nfsm_reqdone; FREE(cnp->cn_pnbuf, M_NAMEI); VTONFS(dvp)->n_flag |= NMODIFIED; VTONFS(dvp)->n_attrstamp = 0; vrele(dvp); /* * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. */ if (error == EEXIST) error = 0; return (error);}/* * nfs make dir call */intnfs_mkdir(ap) struct vop_mkdir_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 vnode **vpp = ap->a_vpp; register struct nfsv2_sattr *sp; register u_long *tl; register caddr_t cp; register long t1, t2; register int len; caddr_t bpos, dpos, cp2; int error = 0, firsttry = 1, isnq; struct mbuf *mreq, *mrep, *md, *mb, *mb2; struct vattr vattr; if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { VOP_ABORTOP(dvp, cnp); vput(dvp); return (error); } len = cnp->cn_namelen; isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); nfsstats.rpccnt[NFSPROC_MKDIR]++; nfsm_reqhead(dvp, NFSPROC_MKDIR, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)+NFSX_SATTR(isnq)); nfsm_fhtom(dvp); nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode); sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); sp->sa_gid = txdr_unsigned(vattr.va_gid); if (isnq) { quad_t qval = -1; txdr_hyper(&qval, &sp->sa_nqsize); sp->sa_nqflags = 0; txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); } else { sp->sa_nfssize = -1; txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); } nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); nfsm_mtofh(dvp, *vpp); nfsm_reqdone; VTONFS(dvp)->n_flag |= NMODIFIED; VTONFS(dvp)->n_attrstamp = 0; /* * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry * if we can succeed in looking up the directory. * "firsttry" is necessary since the macros may "goto nfsmout" which * is above the if on errors. (Ugh) */ if (error == EEXIST && firsttry) { firsttry = 0; error = 0; nfsstats.rpccnt[NFSPROC_LOOKUP]++; *vpp = NULL; nfsm_reqhead(dvp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); nfsm_fhtom(dvp); nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); nfsm_mtofh(dvp, *vpp); if ((*vpp)->v_type != VDIR) { vput(*vpp); error = EEXIST; } m_freem(mrep); } FREE(cnp->cn_pnbuf, M_NAMEI); vrele(dvp); return (error);}/* * nfs remove directory call */intnfs_rmdir(ap) struct vop_rmdir_args /* { struct vnode *a_dvp; struct vnode *a_vp; struct componentname *a_cnp; } */ *ap;{ register struct vnode *vp = ap->a_vp; register struct vnode *dvp = ap->a_dvp; register struct componentname *cnp = ap->a_cnp; register u_long *tl; register caddr_t cp; register long t2; caddr_t bpos, dpos; int error = 0; struct mbuf *mreq, *mrep, *md, *mb, *mb2; if (dvp == vp) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -