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

📄 vfs_subr.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1989, 1993 *	The Regents of the University of California.  All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. * *	@(#)vfs_subr.c	8.13 (Berkeley) 4/18/94 *//* * External virtual filesystem routines */#include <sys/param.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/mount.h>#include <sys/time.h>#include <sys/vnode.h>#include <sys/stat.h>#include <sys/namei.h>#include <sys/ucred.h>#include <sys/buf.h>#include <sys/errno.h>#include <sys/malloc.h>#include <sys/domain.h>#include <sys/mbuf.h>#include <vm/vm.h>#include <sys/sysctl.h>#include <miscfs/specfs/specdev.h>enum vtype iftovt_tab[16] = {	VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,	VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,};int	vttoif_tab[9] = {	0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK,	S_IFSOCK, S_IFIFO, S_IFMT,};/* * Insq/Remq for the vnode usage lists. */#define	bufinsvn(bp, dp)	LIST_INSERT_HEAD(dp, bp, b_vnbufs)#define	bufremvn(bp) {  \	LIST_REMOVE(bp, b_vnbufs); \	(bp)->b_vnbufs.le_next = NOLIST; \}TAILQ_HEAD(freelst, vnode) vnode_free_list;	/* vnode free list */struct mntlist mountlist;			/* mounted filesystem list *//* * Initialize the vnode management data structures. */vntblinit(){	TAILQ_INIT(&vnode_free_list);	TAILQ_INIT(&mountlist);}/* * Lock a filesystem. * Used to prevent access to it while mounting and unmounting. */vfs_lock(mp)	register struct mount *mp;{	while(mp->mnt_flag & MNT_MLOCK) {		mp->mnt_flag |= MNT_MWAIT;		sleep((caddr_t)mp, PVFS);	}	mp->mnt_flag |= MNT_MLOCK;	return (0);}/* * Unlock a locked filesystem. * Panic if filesystem is not locked. */voidvfs_unlock(mp)	register struct mount *mp;{	if ((mp->mnt_flag & MNT_MLOCK) == 0)		panic("vfs_unlock: not locked");	mp->mnt_flag &= ~MNT_MLOCK;	if (mp->mnt_flag & MNT_MWAIT) {		mp->mnt_flag &= ~MNT_MWAIT;		wakeup((caddr_t)mp);	}}/* * Mark a mount point as busy. * Used to synchronize access and to delay unmounting. */vfs_busy(mp)	register struct mount *mp;{	while(mp->mnt_flag & MNT_MPBUSY) {		mp->mnt_flag |= MNT_MPWANT;		sleep((caddr_t)&mp->mnt_flag, PVFS);	}	if (mp->mnt_flag & MNT_UNMOUNT)		return (1);	mp->mnt_flag |= MNT_MPBUSY;	return (0);}/* * Free a busy filesystem. * Panic if filesystem is not busy. */vfs_unbusy(mp)	register struct mount *mp;{	if ((mp->mnt_flag & MNT_MPBUSY) == 0)		panic("vfs_unbusy: not busy");	mp->mnt_flag &= ~MNT_MPBUSY;	if (mp->mnt_flag & MNT_MPWANT) {		mp->mnt_flag &= ~MNT_MPWANT;		wakeup((caddr_t)&mp->mnt_flag);	}}/* * Lookup a mount point by filesystem identifier. */struct mount *getvfs(fsid)	fsid_t *fsid;{	register struct mount *mp;	for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {		if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] &&		    mp->mnt_stat.f_fsid.val[1] == fsid->val[1])			return (mp);	}	return ((struct mount *)0);}/* * Get a new unique fsid */voidgetnewfsid(mp, mtype)	struct mount *mp;	int mtype;{static u_short xxxfs_mntid;	fsid_t tfsid;	mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev + mtype, 0);	mp->mnt_stat.f_fsid.val[1] = mtype;	if (xxxfs_mntid == 0)		++xxxfs_mntid;	tfsid.val[0] = makedev(nblkdev + mtype, xxxfs_mntid);	tfsid.val[1] = mtype;	if (mountlist.tqh_first != NULL) {		while (getvfs(&tfsid)) {			tfsid.val[0]++;			xxxfs_mntid++;		}	}	mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];}/* * Set vnode attributes to VNOVAL */void vattr_null(vap)	register struct vattr *vap;{	vap->va_type = VNON;	vap->va_size = vap->va_bytes = VNOVAL;	vap->va_mode = vap->va_nlink = vap->va_uid = vap->va_gid =		vap->va_fsid = vap->va_fileid =		vap->va_blocksize = vap->va_rdev =		vap->va_atime.ts_sec = vap->va_atime.ts_nsec =		vap->va_mtime.ts_sec = vap->va_mtime.ts_nsec =		vap->va_ctime.ts_sec = vap->va_ctime.ts_nsec =		vap->va_flags = vap->va_gen = VNOVAL;	vap->va_vaflags = 0;}/* * Routines having to do with the management of the vnode table. */extern int (**dead_vnodeop_p)();extern void vclean();long numvnodes;extern struct vattr va_null;/* * Return the next vnode from the free list. */getnewvnode(tag, mp, vops, vpp)	enum vtagtype tag;	struct mount *mp;	int (**vops)();	struct vnode **vpp;{	register struct vnode *vp;	int s;	if ((vnode_free_list.tqh_first == NULL &&	     numvnodes < 2 * desiredvnodes) ||	    numvnodes < desiredvnodes) {		vp = (struct vnode *)malloc((u_long)sizeof *vp,		    M_VNODE, M_WAITOK);		bzero((char *)vp, sizeof *vp);		numvnodes++;	} else {		if ((vp = vnode_free_list.tqh_first) == NULL) {			tablefull("vnode");			*vpp = 0;			return (ENFILE);		}		if (vp->v_usecount)			panic("free vnode isn't");		TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);		/* see comment on why 0xdeadb is set at end of vgone (below) */		vp->v_freelist.tqe_prev = (struct vnode **)0xdeadb;		vp->v_lease = NULL;		if (vp->v_type != VBAD)			vgone(vp);#ifdef DIAGNOSTIC		if (vp->v_data)			panic("cleaned vnode isn't");		s = splbio();		if (vp->v_numoutput)			panic("Clean vnode has pending I/O's");		splx(s);#endif		vp->v_flag = 0;		vp->v_lastr = 0;		vp->v_ralen = 0;		vp->v_maxra = 0;		vp->v_lastw = 0;		vp->v_lasta = 0;		vp->v_cstart = 0;		vp->v_clen = 0;		vp->v_socket = 0;	}	vp->v_type = VNON;	cache_purge(vp);	vp->v_tag = tag;	vp->v_op = vops;	insmntque(vp, mp);	*vpp = vp;	vp->v_usecount = 1;	vp->v_data = 0;	return (0);}/* * Move a vnode from one mount queue to another. */insmntque(vp, mp)	register struct vnode *vp;	register struct mount *mp;{	/*	 * Delete from old mount point vnode list, if on one.	 */	if (vp->v_mount != NULL)		LIST_REMOVE(vp, v_mntvnodes);	/*	 * Insert into list of vnodes for the new mount point, if available.	 */	if ((vp->v_mount = mp) == NULL)		return;	LIST_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);}/* * Update outstanding I/O count and do wakeup if requested. */vwakeup(bp)	register struct buf *bp;{	register struct vnode *vp;	bp->b_flags &= ~B_WRITEINPROG;	if (vp = bp->b_vp) {		vp->v_numoutput--;		if (vp->v_numoutput < 0)			panic("vwakeup: neg numoutput");		if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {			if (vp->v_numoutput < 0)				panic("vwakeup: neg numoutput");			vp->v_flag &= ~VBWAIT;			wakeup((caddr_t)&vp->v_numoutput);		}	}}/* * Flush out and invalidate all buffers associated with a vnode. * Called with the underlying object locked. */intvinvalbuf(vp, flags, cred, p, slpflag, slptimeo)	register struct vnode *vp;	int flags;	struct ucred *cred;	struct proc *p;	int slpflag, slptimeo;{	register struct buf *bp;	struct buf *nbp, *blist;	int s, error;	if (flags & V_SAVE) {		if (error = VOP_FSYNC(vp, cred, MNT_WAIT, p))			return (error);		if (vp->v_dirtyblkhd.lh_first != NULL)			panic("vinvalbuf: dirty bufs");	}	for (;;) {		if ((blist = vp->v_cleanblkhd.lh_first) && flags & V_SAVEMETA)			while (blist && blist->b_lblkno < 0)				blist = blist->b_vnbufs.le_next;		if (!blist && (blist = vp->v_dirtyblkhd.lh_first) && 		    (flags & V_SAVEMETA))			while (blist && blist->b_lblkno < 0)				blist = blist->b_vnbufs.le_next;		if (!blist)			break;		for (bp = blist; bp; bp = nbp) {			nbp = bp->b_vnbufs.le_next;			if (flags & V_SAVEMETA && bp->b_lblkno < 0)				continue;			s = splbio();			if (bp->b_flags & B_BUSY) {				bp->b_flags |= B_WANTED;				error = tsleep((caddr_t)bp,					slpflag | (PRIBIO + 1), "vinvalbuf",					slptimeo);				splx(s);				if (error)					return (error);				break;			}			bremfree(bp);			bp->b_flags |= B_BUSY;			splx(s);			/*			 * XXX Since there are no node locks for NFS, I believe			 * there is a slight chance that a delayed write will			 * occur while sleeping just above, so check for it.			 */			if ((bp->b_flags & B_DELWRI) && (flags & V_SAVE)) {				(void) VOP_BWRITE(bp);				break;			}			bp->b_flags |= B_INVAL;			brelse(bp);		}	}	if (!(flags & V_SAVEMETA) &&	    (vp->v_dirtyblkhd.lh_first || vp->v_cleanblkhd.lh_first))		panic("vinvalbuf: flush failed");	return (0);}/* * Associate a buffer with a vnode. */bgetvp(vp, bp)	register struct vnode *vp;	register struct buf *bp;{	if (bp->b_vp)		panic("bgetvp: not free");	VHOLD(vp);	bp->b_vp = vp;	if (vp->v_type == VBLK || vp->v_type == VCHR)		bp->b_dev = vp->v_rdev;	else		bp->b_dev = NODEV;	/*	 * Insert onto list for new vnode.	 */	bufinsvn(bp, &vp->v_cleanblkhd);}/* * Disassociate a buffer from a vnode. */brelvp(bp)	register struct buf *bp;{	struct vnode *vp;	if (bp->b_vp == (struct vnode *) 0)

⌨️ 快捷键说明

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