📄 nfs_vnops.c
字号:
/* * Copyright (c) 1989, 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_vnops.c 8.5 (Berkeley) 2/13/94 *//* * vnode op calls for sun nfs version 2 */#include <sys/param.h>#include <sys/proc.h>#include <sys/kernel.h>#include <sys/systm.h>#include <sys/mount.h>#include <sys/buf.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/conf.h>#include <sys/namei.h>#include <sys/vnode.h>#include <sys/map.h>#include <sys/dirent.h>#include <vm/vm.h>#include <miscfs/specfs/specdev.h>#include <miscfs/fifofs/fifo.h>#include <nfs/rpcv2.h>#include <nfs/nfsv2.h>#include <nfs/nfs.h>#include <nfs/nfsnode.h>#include <nfs/nfsmount.h>#include <nfs/xdr_subs.h>#include <nfs/nfsm_subs.h>#include <nfs/nqnfs.h>/* Defs */#define TRUE 1#define FALSE 0/* * Global vfs data structures for nfs */int (**nfsv2_vnodeop_p)();struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = { { &vop_default_desc, vn_default_error }, { &vop_lookup_desc, nfs_lookup }, /* lookup */ { &vop_create_desc, nfs_create }, /* create */ { &vop_mknod_desc, nfs_mknod }, /* mknod */ { &vop_open_desc, nfs_open }, /* open */ { &vop_close_desc, nfs_close }, /* close */ { &vop_access_desc, nfs_access }, /* access */ { &vop_getattr_desc, nfs_getattr }, /* getattr */ { &vop_setattr_desc, nfs_setattr }, /* setattr */ { &vop_read_desc, nfs_read }, /* read */ { &vop_write_desc, nfs_write }, /* write */ { &vop_ioctl_desc, nfs_ioctl }, /* ioctl */ { &vop_select_desc, nfs_select }, /* select */ { &vop_mmap_desc, nfs_mmap }, /* mmap */ { &vop_fsync_desc, nfs_fsync }, /* fsync */ { &vop_seek_desc, nfs_seek }, /* seek */ { &vop_remove_desc, nfs_remove }, /* remove */ { &vop_link_desc, nfs_link }, /* link */ { &vop_rename_desc, nfs_rename }, /* rename */ { &vop_mkdir_desc, nfs_mkdir }, /* mkdir */ { &vop_rmdir_desc, nfs_rmdir }, /* rmdir */ { &vop_symlink_desc, nfs_symlink }, /* symlink */ { &vop_readdir_desc, nfs_readdir }, /* readdir */ { &vop_readlink_desc, nfs_readlink }, /* readlink */ { &vop_abortop_desc, nfs_abortop }, /* abortop */ { &vop_inactive_desc, nfs_inactive }, /* inactive */ { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ { &vop_lock_desc, nfs_lock }, /* lock */ { &vop_unlock_desc, nfs_unlock }, /* unlock */ { &vop_bmap_desc, nfs_bmap }, /* bmap */ { &vop_strategy_desc, nfs_strategy }, /* strategy */ { &vop_print_desc, nfs_print }, /* print */ { &vop_islocked_desc, nfs_islocked }, /* islocked */ { &vop_pathconf_desc, nfs_pathconf }, /* pathconf */ { &vop_advlock_desc, nfs_advlock }, /* advlock */ { &vop_blkatoff_desc, nfs_blkatoff }, /* blkatoff */ { &vop_valloc_desc, nfs_valloc }, /* valloc */ { &vop_reallocblks_desc, nfs_reallocblks }, /* reallocblks */ { &vop_vfree_desc, nfs_vfree }, /* vfree */ { &vop_truncate_desc, nfs_truncate }, /* truncate */ { &vop_update_desc, nfs_update }, /* update */ { &vop_bwrite_desc, vn_bwrite }, { (struct vnodeop_desc*)NULL, (int(*)())NULL }};struct vnodeopv_desc nfsv2_vnodeop_opv_desc = { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };/* * Special device vnode ops */int (**spec_nfsv2nodeop_p)();struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = { { &vop_default_desc, vn_default_error }, { &vop_lookup_desc, spec_lookup }, /* lookup */ { &vop_create_desc, spec_create }, /* create */ { &vop_mknod_desc, spec_mknod }, /* mknod */ { &vop_open_desc, spec_open }, /* open */ { &vop_close_desc, nfsspec_close }, /* close */ { &vop_access_desc, nfsspec_access }, /* access */ { &vop_getattr_desc, nfs_getattr }, /* getattr */ { &vop_setattr_desc, nfs_setattr }, /* setattr */ { &vop_read_desc, nfsspec_read }, /* read */ { &vop_write_desc, nfsspec_write }, /* write */ { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ { &vop_select_desc, spec_select }, /* select */ { &vop_mmap_desc, spec_mmap }, /* mmap */ { &vop_fsync_desc, nfs_fsync }, /* fsync */ { &vop_seek_desc, spec_seek }, /* seek */ { &vop_remove_desc, spec_remove }, /* remove */ { &vop_link_desc, spec_link }, /* link */ { &vop_rename_desc, spec_rename }, /* rename */ { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ { &vop_symlink_desc, spec_symlink }, /* symlink */ { &vop_readdir_desc, spec_readdir }, /* readdir */ { &vop_readlink_desc, spec_readlink }, /* readlink */ { &vop_abortop_desc, spec_abortop }, /* abortop */ { &vop_inactive_desc, nfs_inactive }, /* inactive */ { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ { &vop_lock_desc, nfs_lock }, /* lock */ { &vop_unlock_desc, nfs_unlock }, /* unlock */ { &vop_bmap_desc, spec_bmap }, /* bmap */ { &vop_strategy_desc, spec_strategy }, /* strategy */ { &vop_print_desc, nfs_print }, /* print */ { &vop_islocked_desc, nfs_islocked }, /* islocked */ { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ { &vop_advlock_desc, spec_advlock }, /* advlock */ { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ { &vop_valloc_desc, spec_valloc }, /* valloc */ { &vop_reallocblks_desc, spec_reallocblks }, /* reallocblks */ { &vop_vfree_desc, spec_vfree }, /* vfree */ { &vop_truncate_desc, spec_truncate }, /* truncate */ { &vop_update_desc, nfs_update }, /* update */ { &vop_bwrite_desc, vn_bwrite }, { (struct vnodeop_desc*)NULL, (int(*)())NULL }};struct vnodeopv_desc spec_nfsv2nodeop_opv_desc = { &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries };#ifdef FIFOint (**fifo_nfsv2nodeop_p)();struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = { { &vop_default_desc, vn_default_error }, { &vop_lookup_desc, fifo_lookup }, /* lookup */ { &vop_create_desc, fifo_create }, /* create */ { &vop_mknod_desc, fifo_mknod }, /* mknod */ { &vop_open_desc, fifo_open }, /* open */ { &vop_close_desc, nfsfifo_close }, /* close */ { &vop_access_desc, nfsspec_access }, /* access */ { &vop_getattr_desc, nfs_getattr }, /* getattr */ { &vop_setattr_desc, nfs_setattr }, /* setattr */ { &vop_read_desc, nfsfifo_read }, /* read */ { &vop_write_desc, nfsfifo_write }, /* write */ { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ { &vop_select_desc, fifo_select }, /* select */ { &vop_mmap_desc, fifo_mmap }, /* mmap */ { &vop_fsync_desc, nfs_fsync }, /* fsync */ { &vop_seek_desc, fifo_seek }, /* seek */ { &vop_remove_desc, fifo_remove }, /* remove */ { &vop_link_desc, fifo_link }, /* link */ { &vop_rename_desc, fifo_rename }, /* rename */ { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ { &vop_symlink_desc, fifo_symlink }, /* symlink */ { &vop_readdir_desc, fifo_readdir }, /* readdir */ { &vop_readlink_desc, fifo_readlink }, /* readlink */ { &vop_abortop_desc, fifo_abortop }, /* abortop */ { &vop_inactive_desc, nfs_inactive }, /* inactive */ { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ { &vop_lock_desc, nfs_lock }, /* lock */ { &vop_unlock_desc, nfs_unlock }, /* unlock */ { &vop_bmap_desc, fifo_bmap }, /* bmap */ { &vop_strategy_desc, fifo_badop }, /* strategy */ { &vop_print_desc, nfs_print }, /* print */ { &vop_islocked_desc, nfs_islocked }, /* islocked */ { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ { &vop_advlock_desc, fifo_advlock }, /* advlock */ { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ { &vop_valloc_desc, fifo_valloc }, /* valloc */ { &vop_reallocblks_desc, fifo_reallocblks }, /* reallocblks */ { &vop_vfree_desc, fifo_vfree }, /* vfree */ { &vop_truncate_desc, fifo_truncate }, /* truncate */ { &vop_update_desc, nfs_update }, /* update */ { &vop_bwrite_desc, vn_bwrite }, { (struct vnodeop_desc*)NULL, (int(*)())NULL }};struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc = { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries };#endif /* FIFO */void nqnfs_clientlease();/* * Global variables */extern u_long nfs_procids[NFS_NPROCS];extern u_long nfs_prog, nfs_vers, nfs_true, nfs_false;extern char nfsiobuf[MAXPHYS+NBPG];struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];int nfs_numasync = 0;#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))/* * nfs null call from vfs. */intnfs_null(vp, cred, procp) struct vnode *vp; struct ucred *cred; struct proc *procp;{ caddr_t bpos, dpos; int error = 0; struct mbuf *mreq, *mrep, *md, *mb; nfsm_reqhead(vp, NFSPROC_NULL, 0); nfsm_request(vp, NFSPROC_NULL, procp, cred); nfsm_reqdone; return (error);}/* * nfs access vnode op. * For nfs, just return ok. File accesses may fail later. * For nqnfs, use the access rpc to check accessibility. If file modes are * changed on the server, accesses might still fail later. */intnfs_access(ap) struct vop_access_args /* { struct vnode *a_vp; int a_mode; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ register struct vnode *vp = ap->a_vp; register u_long *tl; register caddr_t cp; caddr_t bpos, dpos; int error = 0; struct mbuf *mreq, *mrep, *md, *mb, *mb2; /* * For nqnfs, do an access rpc, otherwise you are stuck emulating * ufs_access() locally using the vattr. This may not be correct, * since the server may apply other access criteria such as * client uid-->server uid mapping that we do not know about, but * this is better than just returning anything that is lying about * in the cache. */ if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { nfsstats.rpccnt[NQNFSPROC_ACCESS]++; nfsm_reqhead(vp, NQNFSPROC_ACCESS, NFSX_FH + 3 * NFSX_UNSIGNED); nfsm_fhtom(vp); nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); if (ap->a_mode & VREAD) *tl++ = nfs_true; else *tl++ = nfs_false; if (ap->a_mode & VWRITE) *tl++ = nfs_true; else *tl++ = nfs_false; if (ap->a_mode & VEXEC) *tl = nfs_true; else *tl = nfs_false; nfsm_request(vp, NQNFSPROC_ACCESS, ap->a_p, ap->a_cred); nfsm_reqdone; return (error); } else return (nfsspec_access(ap));}/* * nfs open vnode op * Check to see if the type is ok * and that deletion is not in progress. * For paged in text files, you will need to flush the page cache * if consistency is lost. *//* ARGSUSED */intnfs_open(ap) struct vop_open_args /* { struct vnode *a_vp; int a_mode; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ register struct vnode *vp = ap->a_vp; struct nfsnode *np = VTONFS(vp); struct nfsmount *nmp = VFSTONFS(vp->v_mount); struct vattr vattr; int error; if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) return (EACCES); if (vp->v_flag & VTEXT) { /* * Get a valid lease. If cached data is stale, flush it. */ if (nmp->nm_flag & NFSMNT_NQNFS) { if (NQNFS_CKINVALID(vp, np, NQL_READ)) { do { error = nqnfs_getlease(vp, NQL_READ, ap->a_cred, ap->a_p); } while (error == NQNFS_EXPIRED); if (error) return (error); if (np->n_lrev != np->n_brev || (np->n_flag & NQNFSNONCACHE)) { if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1)) == EINTR) return (error); (void) vnode_pager_uncache(vp); np->n_brev = np->n_lrev; } } } else { if (np->n_flag & NMODIFIED) { if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1)) == EINTR) return (error); (void) vnode_pager_uncache(vp); np->n_attrstamp = 0; np->n_direofoffset = 0; if (error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p)) return (error); np->n_mtime = vattr.va_mtime.ts_sec; } else { if (error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p)) return (error); if (np->n_mtime != vattr.va_mtime.ts_sec) { np->n_direofoffset = 0; if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1)) == EINTR) return (error); (void) vnode_pager_uncache(vp); np->n_mtime = vattr.va_mtime.ts_sec; } } } } else if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) np->n_attrstamp = 0; /* For Open/Close consistency */ return (0);}/* * nfs close vnode op * For reg files, invalidate any buffer cache entries. *//* ARGSUSED */intnfs_close(ap) struct vop_close_args /* { struct vnodeop_desc *a_desc; struct vnode *a_vp; int a_fflag; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ register struct vnode *vp = ap->a_vp; register struct nfsnode *np = VTONFS(vp); int error = 0; if (vp->v_type == VREG) { if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 && (np->n_flag & NMODIFIED)) { error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1); np->n_attrstamp = 0; } if (np->n_flag & NWRITEERR) { np->n_flag &= ~NWRITEERR; error = np->n_error; } } return (error);}/* * nfs getattr call from vfs. */intnfs_getattr(ap) struct vop_getattr_args /* { struct vnode *a_vp; struct vattr *a_vap; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ register struct vnode *vp = ap->a_vp; register struct nfsnode *np = VTONFS(vp); register caddr_t cp; caddr_t bpos, dpos; int error = 0; struct mbuf *mreq, *mrep, *md, *mb, *mb2; /* * Update local times for special files. */ if (np->n_flag & (NACC | NUPD)) np->n_flag |= NCHG; /* * First look in the cache. */ if (nfs_getattrcache(vp, ap->a_vap) == 0) return (0); nfsstats.rpccnt[NFSPROC_GETATTR]++; nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH); nfsm_fhtom(vp); nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred); nfsm_loadattr(vp, ap->a_vap); nfsm_reqdone; return (error);}/* * nfs setattr call. */intnfs_setattr(ap) struct vop_setattr_args /* { struct vnodeop_desc *a_desc; struct vnode *a_vp; struct vattr *a_vap; struct ucred *a_cred; struct proc *a_p; } */ *ap;{ register struct nfsv2_sattr *sp; register caddr_t cp; register long t1; caddr_t bpos, dpos, cp2; u_long *tl; int error = 0, isnq; struct mbuf *mreq, *mrep, *md, *mb, *mb2; register struct vnode *vp = ap->a_vp; register struct nfsnode *np = VTONFS(vp); register struct vattr *vap = ap->a_vap; u_quad_t frev, tsize; if (vap->va_size != VNOVAL || vap->va_mtime.ts_sec != VNOVAL || vap->va_atime.ts_sec != VNOVAL) { if (vap->va_size != VNOVAL) { if (np->n_flag & NMODIFIED) { if (vap->va_size == 0) error = nfs_vinvalbuf(vp, 0, ap->a_cred, ap->a_p, 1); else error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1); if (error) return (error); } tsize = np->n_size; np->n_size = np->n_vattr.va_size = vap->va_size; vnode_pager_setsize(vp, (u_long)np->n_size); } else if ((np->n_flag & NMODIFIED) &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -