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

📄 nfs_vnodeops.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)nfs_vnodeops.c	4.10	(ULTRIX)	4/25/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1990 by			* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* *	Portions of this software have been licensed to  *	Digital Equipment Company, Maynard, MA. *	Copyright (c) 1986 Sun Microsystems, Inc.  ALL RIGHTS RESERVED. *//* * *   Modification history: * * 25 Apr 91 -- chet *	Add access check in nfs_lookup() after dnlc hit. * * 28 Feb 91 -- dws *	Clean up client view of fhandle. * * 27 Feb 91 -- chet *	Fix client side attribute problems when modify time goes backwards. * * 15 Feb 91 *	Fixed nfs_fsync for case where file size > (0x7fffffff - (blksize-1)). * * 10 Feb 91 -- chet *	Change nfs_attrcache() calls (again). * * 29 Jan 91 -- chet *	Make kernel RPC calls interruptible. * * 28 Oct 90 -- chet *	Change nfs_fsync() scheme to keep rnode dirty and gp locked *	during complete operation. * *  8-Sep-90 -- Fred *	Transfer complete file handle to lock handle structure in nfs_rlock (). * *  7 Jul 90 -- chet *	Change nfs_write(), nfs_fsync() and nfs_attrcache() schemes; *	remove count of outstanding write buffers. *	 * 20 Jun 90 -- cb *	Fix the attribute cache. * *  9 Mar 90 -- chet *	Change nfs_fsync() and nfs_attrcache() schemes to *	use a count of outstanding write buffers. * * 23-Feb-90 -- sekhar *      Merged Joe Martin's fix for 3.1 cld. When copying user PTEs, *      check for page crossing and reevaluate vtopte. * * 15 Feb 90 -- prs *	Added referencing the gnode in nfs_strategy() before scheduling a *	wakeup to a sleeping async daemon. This way, a biod will hold *	a ref to a gnode even if the invoking process closes the file. * *  7 Feb 90 -- chet *	Change asynch daemon work list scheme. * *  6 Feb 90 -- chet *	Change block I/O gnode referencing and nfs_fsync() gnode *	locking schemes. * *  2 Feb 90 -- chet *	Change asynchronous I/O gnode and buffer synchronization * *  1 Feb 90 -- prs *	Fixed leaf node caching into dnlc. * * 13 Dec 89 -- chet *	Add attribute cache timeout values. * * 10 Dec 89 -- chet *	Remove dnlc purge call for non-directories in nfs_attrcache. * * 05 Oct 89 -- prs *	Added locking of the [vg]node to nfs_close(). * * 25 Jul 89 -- chet *	Changes for new bflush() and faster cache invalidations * *  6 Mar 89 -- chet *	Put regular files into dnlc; make size of dnlc a function *	of system size. * * 06 Feb 89 -- prs *      Modified nfs_readdir() and nfs_close() to set u.u_error before *      returning with an error value. These routines are called by *      GFS directly, and assumed to set u.u_error before returning. * * 21 Nov 88 -- condylis *	Added freeing of vnode credential to nfs_inactive. * * 07 Nov 88 -- dgg *      Corrected calculation of pte from proc pointer in nfs_strategy. *      [ dgg001 ] * * 28 Sep 88 -- chet *	Put R_IN_FSYNC define where it belongs (vnode.h) * *  1 Sep 88 -- chet *	Set u.u_error after a failed rfscall to readdir * * 5 Aug 88 -- condylis *	Merge of 2.4 changes.  Minimize number of calls to vtor and *	check change in file size in nfs_attrcache. * * 18 Jul 88 -- condylis *	Add SMP locking for bio daemon buffer list and async_daemon_count *	variable.  dnlc_lookup now bumps ref count of returned gnode; *	removed VN_HOLD after call.  Replaced unsafe modification of gnodes *	with calls to SMP gnode primitives. * * 2 Mar 88 -- chet *	Add RNOCACHE stuff for locked files to rwvp(). * * 4 Feb 88 -- chet for cb *	add fifo mode fix in nfs_create() * * 26 Jan 88 -- chet *	Put access check in nfs_getdirent(); lock gnode before doing *	the access check to synchronize with any other process that has *	it locked. * * 12 Jan 88 - Fred Glover *	Add routine nfs_rlock for Sys-V file locking. * * 12-11-87	Robin L. and Larry C. and Ricky P. *	Added new kmalloc memory allocation to system. * * 14 Jul 87 -- cb *	added in rr's changes to remote execution. * * 14 Jul 87 -- chet *	Changed binval() calls to binvalfree() calls in nfs_attrcache() *	and nfs_close(). * * 16 Jun 87 -- cb *      Added check to biod code to die gracefully on termination. * * 12 May 87 -- chet *	Added commented check for opening special files. * * 11-May-87 -- logcher *	Removed the mpurge which had wrong logic anyways.  Does *	not gain much if right logic was there. * * 02-Mar-87 -- logcher *	Merged in diskless changes, removed an unused argument from *	nfs_create, added support for mknod of non-regular files, *	added code to support swapping to an NFS file. */#include "../h/param.h"#include "../h/mount.h"#include "../h/systm.h"#include "../h/user.h"#include "../h/gnode.h"#include "../h/file.h"#include "../h/uio.h"#include "../h/buf.h"#include "../h/kernel.h"#include "../h/cmap.h"#include "../h/proc.h"#include "../h/ipc.h"#include "../h/shm.h"#include "../h/vmmac.h"#include "../net/netinet/in.h"#include "../net/rpc/types.h"#include "../net/rpc/auth.h"#include "../net/rpc/clnt.h"#include "../net/rpc/xdr.h"#include "../nfs/nfs.h"#include "../nfs/nfs_clnt.h"#include "../nfs/vfs.h"#include "../nfs/vnode.h"#include "../h/fs_types.h"#include "../net/rpc/lockmgr.h"/* SMP lock for biod bfr list */struct lock_t	lk_nfsbiod;/* MPC Counter to monitor wasted biod wakeups */int	biod_has_work;int	biod_has_no_work;struct vnode *makenfsnode();struct vnode *dnlc_lookup();char *newname();int nfs_dnlc = 1;#define check_stale_fh(errno, vp) if ((errno) == ESTALE) { dnlc_purge_vp(vp); }#define	nfsattr_inval(vp)	(vtor(vp)->r_nfsattrtime.tv_sec = 0)#define ISVDEV(t) ((t == VBLK) || (t == VCHR) || (t == VFIFO))/* * These are the vnode ops routines which implement the vnode interface to * the networked file system.  These routines just take their parameters, * make them look networkish by putting the right info into interface structs, * and then calling the appropriate remote routine(s) to do the work. * * Note on directory name lookup cacheing:  we desire that all operations * on a given client machine come out the same with or without the cache. * This is the same property we have with the disk buffer cache.  In order * to guarantee this, we serialize all operations on a given directory, * by using lock and unlock around rfscalls to the server.  This way, * we cannot get into races with ourself that would cause invalid information * in the cache.  Other clients (or the server itself) can cause our * cached information to become invalid, the same as with data buffers. * Also, if we do detect a stale fhandle, we purge the directory cache * relative to that vnode.  This way, the user won't get burned by the * cache repeatedly. */intnfs_open(vp, flag)	register struct	vnode *vp;	int flag;{	register struct ucred *cred = u.u_cred;	register int error;	/*	 * refresh cached attributes	 */	nfsattr_inval(vp);	error = nfs_getattr(vp, cred);	if (!error) {		vtor(vp)->r_flags |= ROPEN;	}	return (error);}intnfs_close(vp, flag)	register struct	vnode *vp;	int	flag;{	register struct ucred *cred = u.u_cred;	register struct rnode *rp = vtor(vp);	gfs_lock(vp);	rp->r_flags &= ~ROPEN;	/*	 * If this is a close of a file open for writing or an unlinked	 * open file or a file that has had an asynchronous write error,	 * flush synchronously. This allows us to invalidate the file's	 * buffers if there was a write error or the file was unlinked.	 */	if (flag & FWRITE || rp->r_unldvp != NULL || rp->r_error) {		(void) nfs_fsync(vp); /* NB: nfs_getattr() will unlock vp */	}	if (rp->r_unldvp != NULL || rp->r_error) {		cacheinval((struct gnode *)vp);				/* binvalfree((struct gnode *)vp); */		dnlc_purge_vp(vp);	}	gfs_unlock(vp);	if (flag & FWRITE) {		/* r_error is never cleared on a ref'd gnode */		u.u_error = rp->r_error;                return;        }}int nfs_read_incore = 0;int nfs_read_not_incore = 0;int nfs_bread1 = 0;int nfs_breada1 = 0;int nfs_bread2 = 0;int nfs_rfsread_count = 0;intrwvp(vp, uio, rw, ioflag)	register struct vnode *vp;	register struct uio *uio;	enum uio_rw rw;	int ioflag;{	register struct buf *bp;	register struct rnode *rp = vtor(vp);	register int n, on, size;	daddr_t bn, mapped_bn, mapped_rabn;	int eof = 0;	int error = 0;	if (uio->uio_resid == 0) {		return (0);	}	if (uio->uio_offset < 0 || (uio->uio_offset + uio->uio_resid) < 0) {		return (EINVAL);	}	if (rw == UIO_WRITE && vp->v_type == VREG &&	    uio->uio_offset + uio->uio_resid >	      u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {		psignal(u.u_procp, SIGXFSZ);		return (EFBIG);	}	size = vtoblksz(vp);	size &= ~(DEV_BSIZE - 1);	if (size <= 0) {		panic("rwvp: zero size");	}	do {		bn = uio->uio_offset / size;		on = uio->uio_offset % size;		n = MIN((unsigned)(size - on), uio->uio_resid);		nfs_bmap(vp, bn, &mapped_bn);		/* Don't use cache for RNOCACHE reads */		if (rp->r_flags & RNOCACHE) {			bp = geteblk(size);			if (rw == UIO_READ) {				error = nfsread(bp, vp, bp->b_un.b_addr+on,						uio->uio_offset, n,						u.u_cred, NFS_NOT_BLOCKIO);				if (error) {					brelse(bp);					goto bad;				}			}	        } else if (rw == UIO_READ) {			if (incore(vp->g_dev, mapped_bn, vp)) {				/*				 * get attributes to check whether in				 * core data is stale				 */				++nfs_read_incore;				(void) nfs_getattr(vp, u.u_cred);			}			else				++nfs_read_not_incore;			if (vp->g_lastr + 1 == bn) {				nfs_bmap(vp, bn + 1, &mapped_rabn);				++nfs_breada1;				bp = breada(vp->g_dev, mapped_bn,					    size, mapped_rabn, size,					    vp);			} else {				++nfs_bread1;				bp = bread(vp->g_dev, mapped_bn,					   size, vp);			}		} else {  /* (rw == UIO_WRITE) */			struct gnode *gp = (struct gnode *) (vp);			if (rp->r_error) {				error = rp->r_error;				goto bad;			}			if (gp->g_textp) xuntext(gp->g_textp);			if (n == size) {				bp = getblk(vp->g_dev, mapped_bn, size, vp);			} else {				++nfs_bread2;				bp = bread(vp->g_dev, mapped_bn, size, vp);			}		}/* CJXXX */		if (bp->b_flags & B_ERROR) {			error = geterror(bp);			brelse(bp);			goto bad;		}		/*		 * The following code was moved down here when RNOCACHE		 * was put in so that both cached and non-cached reads		 * fall through.		 */		if (rw == UIO_READ) {			int diff;			vp->g_lastr = bn;			diff = vp->g_size - uio->uio_offset;			if (diff < n) {				if (diff <= 0) {					brelse(bp);					return(0);				}				n = diff;				eof = 1;			}		}		u.u_error = uiomove(bp->b_un.b_addr+on, n, rw, uio);		if (rw == UIO_READ) {			if (rp->r_flags & RNOCACHE)			  bp->b_flags |= B_NOCACHE;			brelse(bp);		} else {   /* (rw == UIO_WRITE) */			/*			 * g_size is the maximum number of bytes known			 * to be in the file.			 * Make sure it is at least as high as the last			 * byte we just wrote into the buffer.			 */			if (vp->g_size < uio->uio_offset) {				vp->g_size = uio->uio_offset;			} 			/* Don't cache any RNOCACHE writes */			if (rp->r_flags & RNOCACHE) {				error = nfswrite(bp, vp, bp->b_un.b_addr+on,						 uio->uio_offset-n, n,						 u.u_cred, NFS_NOT_BLOCKIO);				bp->b_flags |= B_NOCACHE;				brelse(bp);                        } else  {				rp->r_flags |= RDIRTY;				if (n + on == size) {					bp->b_resid = 0;					if ((ioflag & IO_SYNC) ||					    vp->g_mp->m_flags & M_SYNC)						bwrite(bp);				        else						bawrite(bp);				} else {					/*					 * The bp->b_resid field is the number					 * of bytes in the buffer that are NOT					 * part of the file. We first compute					 * how many bytes beyond the end of					 * the file the last byte in the buffer					 * is (think about it). If the file					 * continues past the end of the block					 * then this value will be negative,					 * and we set it to zero since all the					 * bytes in the buffer are valid. The					 * result is used by nfswrite to decide					 * how many bytes to send to the					 * server.					 */					bp->b_resid = (size * (bn + 1)) -					  vp->g_size;					if (bp->b_resid < 0)					  bp->b_resid = 0;					if (ioflag & IO_SYNC ||					    vp->g_mp->m_flags & M_SYNC)						bwrite(bp);				        else {						/* gid could have changed */						/* due to a cacheinval as */						/* part of bread() above; */						/* set gid so that buffer */						/* is not orphaned */						bp->b_gid = vp->g_id;						bdwrite(bp);					}				}			}		}	} while (u.u_error == 0 && uio->uio_resid > 0 && !eof);	if (rw == UIO_WRITE && uio->uio_resid && u.u_error == 0) {		printf("rwvp: short write. resid %d vp %x bn %d\n",		    uio->uio_resid, vp, bn);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -