⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nfs_vnops.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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 + -