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

📄 gfs_gnode.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)gfs_gnode.c	4.2	(ULTRIX)	11/9/90";#endif/************************************************************************ *									* *			Copyright (c) 1986 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.	* *									* ************************************************************************//*********************************************************************** * *		Modification History * * 10 May 90 -- prs for cb *	Added wantid argument to ggrab(). ufs_namei() calls ggrab with *	the expected g_id, so ggrab() can perform an advisory check *	before locking gnode. * *  2 Feb 90 -- chet *	Change getegnode to use cacheinval() * * 12-Jan-90 -- prs *	Changed km_free to use KM_FREE macro to keep malloc *	counters in sync with actual number of free's. *  * 09-Nov-89 -- jaw *	remove smp_owner check on gnode lock. * * 24 Jul 89 -- prs *	Added unggrab() primitive. * * 06 Apr 89 -- prs *	Added SMP quota locks. Cleaned up gflush(). * * 9 Mar 89 -- chet *	Put code in gget() to ask NFS dnlc to give up gnode *	references when out of free gnodes. * * 05 jan 89 -- condylis *	Added check for state of mount table entry to ggrab. *	Restructured gflush for SMP umount, mount and sync.  Added fref *	primitive. * * 06 Sep 88 -- prs *      SMP - Changed grele() to dealloc space associated with a *      named pipe since fifo_rele() is not called. * * 19 May 88 -- cb  *      Added SMP lock mechanisms.  Changed GFS interface. * * 11 Sep 86 -- koehler  *	changed gflush * * 16 Oct 86 -- koehler *	ggrab needs to make sure that the last free gnode is not being *	consumed. * ***********************************************************************/#include "../h/param.h"#include "../h/systm.h"#include "../h/mount.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/gnode.h"#include "../h/conf.h"#include "../h/buf.h"#ifdef QUOTA#include "../h/quota.h"#include "../h/kmalloc.h"#endif#include "../h/kernel.h"union ghead ghead[GNOHSZ]; struct gnode *gfreeh, **gfreet;struct lock_t lk_gnode;struct gstats {        int greuse;        int greclaims;        int gfound;        int grefs;        int greles;        int gfrees;};struct gstats gstats;/* * Initialize hash links for gnodes * and build gnode free list. */ghinit(){	register int i;	register struct gnode *gp = gnode;	register union  ghead *gh = ghead;	for (i = GNOHSZ; --i >= 0; gh++) {		gh->gh_head[0] = gh;		gh->gh_head[1] = gh;	}	gfreeh = gp;	gfreet = &gp->g_freef;	gp->g_freeb = &gfreeh;	gp->g_forw = gp;	gp->g_back = gp;	lockinit(&gp->g_lk, &lock_eachgnode_d);	for (i = ngnode; --i > 0; ) {		++gp;		gp->g_forw = gp;		gp->g_back = gp;		*gfreet = gp;		gp->g_freeb = gfreet;		gfreet = &gp->g_freef;		lockinit(&gp->g_lk, &lock_eachgnode_d);	}	gp->g_freef = NULL;	gstats.greuse = 0;	gstats.greclaims = 0;	gstats.gfound = 0;	gstats.grefs = 0;	gstats.greles = 0;	gstats.gfrees = 0;	finit();   /* initialize the file table */}/* * Convert a pointer to an gnode into a reference to an gnode. * * This is basically the internal piece of gget (after the * gnode pointer is located) but without the test for mounted * filesystems.  It is caller's responsibility to check that * the gnode pointer is valid. ufs_namei() is currently the * only invoker. Please note the unggrab() must be used * to deallocate the gnode if the gnode pointer is not valid. */struct gnode *ggrab(gp, wantid)        register struct gnode *gp;	int wantid;{        caddr_t ptr = (caddr_t) NULL;    /* XXX */	smp_lock(&lk_gnode, LK_RETRY);	/*	 * Has the file system been unmounted	 */	if (!(gp->g_mp->m_flgs & MTE_DONE)) {		smp_unlock(&lk_gnode);		return(NULL);	}	/*	 * get an advisory opinion, that's binding if	 * it says the gnode has been reused, the	 * caller must check again (while holding 	 * the lock) if it looks like the right gnode.	 */		if (gp->g_id != wantid) {		smp_unlock(&lk_gnode);		return(NULL);	}	gp->g_count++;	if (gp->g_count != 1) 	        gstats.grefs++;	else {		gstats.greclaims++;		gremque(gp);		if (gisready(gp))		        panic("ggrab: active unreferenced gnode");	}	smp_unlock(&lk_gnode);	gfs_lock(gp);	if (!gisready(gp)) {		if (!ginitialize(gp, ptr)) {	        	gclobber(gp);			gfs_unlock(gp);			grele(gp);			return(NULL);		}	}	return(gp);}/* * ufs_namei() needs to un ggrab a gnode. The ggrab() routine * pays no attention to nlink. The case where nlink is equal to * zero, and we hold the only reference, we must set the g_init * field to the reclaim state, or the sfs inactive routine * will attempt to deallocate a previously deallocated gnode. * All other cases will go through proper channels. */unggrab(gp)	register struct gnode *gp;{	gassert(gp);	if ((gp->g_count == 1) && (gp->g_nlink == 0))		gp->g_init = RECLAIM_GNODE;	gfs_unlock(gp);	grele(gp);}/* * Decrement reference count of * an gnode structure. * On the last reference, * write the gnode out and if necessary, * truncate and deallocate the file. */gput(gp)	register struct gnode *gp;{	gactive(gp);	if(gp->g_count == 1 && (gp->g_mode& GFMT)  != GFPIPE) {	        GINACTIVE(gp);		gp->g_init = RECLAIM_GNODE;	}		gfs_unlock(gp);	grele(gp);}/* * remove any gnodes in the gnode cache belonging to dev * * There should not be any active ones, return error if any are found * (nb: this is a user error, not a system err) * * Also, count the references to dev by block devices - this really * has nothing to do with the object of the procedure, but as we have * to scan the gnode table here anyway, we might as well get the * extra benefit. * */#ifdef QUOTAgflush(dev, gq, mgp)	dev_t dev;	register struct gnode *gq;	struct gnode *mgp;#elsegflush(dev, mgp)	dev_t dev;	struct gnode *mgp;#endif{	register struct gnode *gp;	register int open = 0;#ifdef QUOTA	register struct dquot *dq;	struct dquot **dqq;	struct dquot *dquot_array;	KM_ALLOC(dquot_array, struct dquot *, (ngnode + 1) * 4, 		 KM_TEMP, KM_CLEAR);	dqq = (struct dquot **)dquot_array;#endifsmp_lock(&lk_gnode, LK_RETRY);	for (gp = gnode; gp < gnodeNGNODE; gp++) {#ifdef QUOTA		if (gp != gq && gp->g_dev == dev && gp != gp->g_mp->m_gnodp) {#else		if ((gp->g_dev == dev) && (gp != gp->g_mp->m_gnodp)) {#endif			if((gp == mgp) && (mgp->g_count == 1))				continue;			if (gp->g_count) {				smp_unlock(&lk_gnode);				open = -1;				goto out;			}			else {				remque(gp);				gp->g_forw = gp;				gp->g_back = gp;				/*				 * as g_count == 0, the gnode was on the free				 * list already, just leave it there, it will				 * fall off the bottom eventually. We could				 * perhaps move it to the head of the free				 * list, but as umounts are done so				 * infrequently, we would gain very little,				 * while making the code bigger.				 */#ifdef QUOTA				if (gp->g_dquot != NODQUOT) {					*dqq = gp->g_dquot;					dqq++;				}				gp->g_dquot = NODQUOT;#endif			}		}		else if (gp->g_count && (gp->g_mode&GFMT)==GFBLK &&		   gp->g_rdev == dev) /* hack? */			open++;	}	if (mgp != NULL) {		smp_lock(&mgp->g_mp->m_lk, LK_RETRY);		mgp->g_mp->m_flgs &= ~MTE_DONE;	/* mount table entry is being 					/* unmounted.  (Can't get a ref					/* on gnode in file system and					/* mount table entry cannot be					/* reclaimed)					 */		smp_unlock(&mgp->g_mp->m_lk);	}	smp_unlock(&lk_gnode);out:#ifdef QUOTA	/* Now free up quota related stuff */	for (dqq = (struct dquot **)dquot_array; *dqq; dqq++) {		dquot_lock((*dqq));		dqrele((*dqq));		dquot_unlock((*dqq));	}	KM_FREE(dquot_array, KM_TEMP);#endif	return (open);}int getegnode_ufs, getegnode_nfs;int getegnode_purge_worked, getegnode_purge1_worked;/* * Look up a gnode by device, number. If it is in core (in the gnode * table), return it locked. If it is not in core, get an empty gnode * and call a filesystem-specific routine to initialize it.  If the gnode * is mounted on, jump over the mount point.  In all cases a pointer to * a locked gnode is returned. */struct gnode *gget(mp, gno, nocross, ptr)	register struct mount *mp;	register gno_t gno;	int nocross;	caddr_t ptr;{	register struct gnode *gp = (struct gnode *)0;	register union  ghead *gh;	struct gnode *rootgp;	register dev_t dev = mp->m_dev;	int	purge_state = 0;start:	gh = &ghead[GNOHASH(mp->m_dev, gno)];	smp_lock(&lk_gnode, LK_RETRY);	for (gp = gh->gh_chain[0]; gp != (struct gnode *)gh; gp = gp->g_forw) {		if (gno == gp->g_number && dev == gp->g_dev && GMATCH(gp, ptr)) {			gp->g_count++;			if ((gp->g_flag&GMOUNT) && (nocross == 0)) {				mp = gp->g_mpp;				rootgp = mp->m_rootgp;				gp->g_count--;				rootgp->g_count++;				smp_unlock(&lk_gnode);				gfs_lock(rootgp);				return(rootgp);							}			if (gp->g_count == 1) {				gremque(gp);			}			smp_unlock(&lk_gnode);			gfs_lock(gp);			if (gisready(gp))				gstats.gfound++;			else {				gstats.greclaims++;				gp->g_mp = mp;				if (!ginitialize(gp, ptr)) {					gclobber(gp);					gfs_unlock(gp);					grele(gp);					return(NULL);				}			}

⌨️ 快捷键说明

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