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

📄 gfs_gnode.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	XXX		gp->g_blocks = G_TO_I(gp)->di_blocks;		XXX */			return(gp);		}	}	/*	 * Get a free gnode.	 * If there aren't any, then ask NFS to give one up from	 * its name lookup cache.	 * If that doesn't work, ask NFS to free all of its lookup	 * cache gnode references.	 * If that doesn't work, bail out.	 */	if((gp = getegnode(GNOHASH(dev, gno), mp, gno)) == NULL) {		smp_unlock(&lk_gnode);		switch (purge_state) {			case 0:				if (major(dev) < nblkdev + nchrdev)					getegnode_ufs++;				else					getegnode_nfs++;				dnlc_purge1();				purge_state++;				goto start;				break;			case 1:				dnlc_purge();				purge_state++;				goto start;				break;			default:				tablefull("gnode");				u.u_error = ENFILE;				return(NULL);				break;		}	} else if (purge_state) {		switch (purge_state) {			case 1:				getegnode_purge1_worked++;				break;			default:				getegnode_purge_worked++;				break;		}	}	gp->g_count++;	gstats.greuse++;	smp_unlock(&lk_gnode);	gfs_lock(gp);#ifdef QUOTA	dquot_lock(gp->g_dquot);	dqrele(gp->g_dquot);	dquot_unlock(gp->g_dquot);#endif	if (!gisready(gp)) {		if (!ginitialize(gp, ptr)) {			gclobber(gp);			gfs_unlock(gp);			grele(gp);			return(NULL);		}	}#ifdef QUOTA	if (gp->g_mode == 0)		gp->g_dquot = NODQUOT;	else 		gp->g_dquot = inoquota(gp);#endif	return (gp);}/*intgfs_lock(gp)	register struct gnode *gp;{	if (gp->g_count < 1)	        panic("gfs_lock: locking unrefed gnode");	smp_lock(&gp->g_lk, LK_RETRY);}intgfs_unlock(gp)	register struct gnode *gp;{	if (gp->g_count < 1)	        panic("gfs_unlock: unlocking unrefed gnode");	if (!glocked(gp))	        panic("gfs_unlock: unlocking unlocked gnode");	smp_unlock(&gp->g_lk);}*//* * Pull an empty gnode off of the free list and prepare to reuse it for * another file.  Link it onto its new hash chain.  Caller must hold * the gnode table spin lock. */struct gnode *getegnode(hash, mp, gno)	register int	hash;	struct	 mount  *mp;	register gno_t	gno;{	register struct gnode *gp;	register struct gnode *gq;	register struct gnode *xp;	dev_t	dev = mp->m_dev;		if ((gp = gfreeh) == NULL) {		return(NULL);	}	if (gp->g_count) {		cprintf("getegnode: gp 0x%x (%d)\n", gp, gp->g_number);		panic("getegnode: free gnode isn't");	}	/*	 * Free resources hanging off the gnode from its previous life.	 * XXX What if the filesystem has already been unmounted?  This	 * code is unused by UFS and NFS and it causes problems.  It should	 * probably be moved up to gget() since we can't release the spin	 * lock here.	 *	if ((gp->g_mp) && (gp->g_mp->m_dev != NODEV))		(void)GFREEGN(gp);	 */	/*	 * Take the gnode off of the free list.  We could call gremque	 * but we can do it faster here.	 */	if (gq = gp->g_freef)		gq->g_freeb = &gfreeh;	gfreeh = gq;	gp->g_freef = NULL;	gp->g_freeb = NULL;			/*	 * Now to take gnode off the hash chain it was on (initially, or	 * after a gflush, it is on a "hash chain" consisting entirely of	 * itself, and pointed to by no-one, but that doesn't matter), and	 * put it on the chain for its new (gno, dev) pair.	 */			remque(gp);	insque(gp, &ghead[hash]);	/*	 * Initialize some of the easy stuff.  We leave the rest for the	 * caller to do, but these we to set up here for convenience.	 */	gp->g_dev = dev;	gp->g_mp = mp;	gp->g_number = gno;	gp->g_lastr = 0;	gp->g_textp = NULL;	gp->g_rdev = 0;	gp->g_blocks = 0;	gp->g_flag = 0;	gp->g_fifo = 0;	gp->g_init = NEW_GNODE;	bzero((caddr_t)gp->g_in.pad, sizeof(gp->g_in));	cacheinval(gp);	if (glocked(gp)) {		printf("getegnode: free gnode locked 0x%x\n", gp);		panic("getegnode: locked gnode on freelist");	}	return(gp);}/* * Put a gnode on the end of the free list.  Caller must hold gnode table * spin lock.  Historical comment: * *  "Possibly in some cases it would be better to put the inode at the head *   of the free list, eg: where g_mode == 0 || g_number == 0).  The g_number *   field is rarely 0 - only after an i/o error in gget, where g_mode == 0, *   the gnode will probably be wanted again soon for an ialloc, so possibly *   we should keep it."     - kre */freegnode(gp)	register struct gnode *gp;{	if (gp < gnode || gp > gnodeNGNODE)		panic("freegnode: not a gnode");	if(gp->g_count != 0) {		cprintf("freegnode: gp 0x%x (%d)\n", gp, gp->g_number);		panic("freegnode: freeing active gnode");	}	if(glocked(gp)) {		cprintf("freegnode: gp 0x%x (%d)\n", gp, gp->g_number);		panic("freegnode: freeing locked gnode");	}	if (gfreeh) {		*gfreet = gp;		gp->g_freeb = gfreet;	} else {		gfreeh = gp;		gp->g_freeb = &gfreeh;		wakeup((caddr_t)&gfreeh);	}	gp->g_freef = NULL;	gfreet = &gp->g_freef;}/* * Call the correct filesystem-specific initialization routine * to initialize a gnode, and return success or failure. */intginitialize(gp, ptr)	register struct gnode *gp;	caddr_t ptr;{	int status = 0;	switch (gp->g_init) {	case NEW_GNODE:		status = GINIT(gp, gp->g_init, ptr);		break;	case RECLAIM_GNODE:		status = GRECLAIM(gp, gp->g_init, ptr);		break;	default:		panic("initializing ready gnode");	}	if (status == 1)		gp->g_init = READY_GNODE;	return(status);}/* * Called when an error occurred while initializing a gnode. * The gnode doesn't contain anything useful, so it would be * misleading to leave it on its hash chain. */gclobber(gp)	struct gnode *gp;{	gassert(gp);	smp_lock(&lk_gnode, LK_RETRY);	remque(gp);	gp->g_forw = gp;	gp->g_back = gp;	gp->g_number = 0;#ifdef QUOTA	gp->g_dquot = NODQUOT;#endif	smp_unlock(&lk_gnode);}/* * Insist that a gnode be active.  We panic if the gnode has * a zero reference count or is marked as uninitialized. * Caller (must, should, can) hold the gnode table spin lock. */gactive(gp)	struct gnode *gp;{	if (gp->g_count <= 0)		panic("gnode is inactive");	if (gp->g_init != READY_GNODE)		panic("uninitialized gnode");}/* * There are several examples in gput() and grele() of the gnode count * being examined without holding the spin lock.  Some are safe because * the result is used only as a "hint" on whether or not we are releasing * the last reference...we grab the spin lock and check again before * deciding to make the gnode inactive.  Others are safe because we hold * a lock on the gnode, so we know that although a new reference can be * created, it is safe to make the gnode inactive because a new LOCKED * reference cannot be created. * * Also, in the while loop in grele, we look at the g_init field without * holding the gnode sleep lock.  This is safe because we know that we * have the only reference to the gnode, and we hold the gnode table spin * lock so we know that no new references can be created. * * The while loop in grele is necessary because there is a window between * making the gnode inactive and placing it on the free list when we have * released both the gnode sleep lock and the gnode table spin lock.  Another * process(or) could conceivably come in, create a reference to the gnode, * reinitialize it, and destroy their reference before we get the spin lock * back again, leaving us with the last reference to a gnode which needs to * be made inactive again.  In practice this will never happen, but the code * needs to protect against it. * * The routine inactive_hack() is the internal part of that while loop.  It * tries to lock the gnode (failure ==> not last reference, so give up), * checks to make sure that no new references have been created, and calls * the fs-specific inactive routine.  We check the count without holding the * spin lock: this is safe because we hold the gnode sleep lock so no new * LOCKED references to this gnode may be created while we're making it * inactive (see above).  Unlocked references are OK. */voidinactive_hack(gp)        struct gnode *gp;{        if (smp_lock(&gp->g_lk, 0) == LK_WON) { /* XXX hack? */                if (gp->g_count == 1) {                        GINACTIVE(gp);                        gp->g_init = RECLAIM_GNODE;                }                gfs_unlock(gp);        } else {#ifdef GFSDEBUG                smp_lock(&lk_gnode, LK_RETRY);                if ((gp->g_count == 1) && glocked(gp))                        panic("grele: inactive gnode is locked");                smp_unlock(&lk_gnode);#endif GFSDEBUG        }}voidgrele(gp)	register struct gnode *gp;{	int loopcount = 0;	register int ret;	if ((gp->g_mode & GFMT) == GFPIPE) {		fifo_rele(gp);		return;	}#ifdef notdef	if (gp < gnode || gp > (gnode + ngnode * sizeof (struct gnode)))		panic("grele: not a gnode");#endif        smp_lock(&lk_gnode, LK_RETRY);        gstats.greles++;        while ((gp->g_count == 1) && gisready(gp)) {                smp_unlock(&lk_gnode);#ifdef GFSDEBUG                if (loopcount++ > 1)                        panic("grele: round and round and round we go");#endif GFSDEBUG                inactive_hack(gp);                smp_lock(&lk_gnode, LK_RETRY);        }        if (gp->g_count == 1) {#ifdef GFSDEBUG                if (gisready(gp))                        panic("grele: freeing initialized gnode");#endif GFSDEBUG                gstats.gfrees++;                gp->g_flag = 0;                gp->g_count--;                freegnode(gp);                smp_unlock(&lk_gnode);                return;        }        if((gp->g_count--) < 1)                panic("grele: gp count bad");        smp_unlock(&lk_gnode);}/* * Create a new reference to a previously referenced gnode. */gref(gp)        register struct gnode *gp;{        smp_lock(&lk_gnode, LK_RETRY);        gactive(gp);        gstats.grefs++;        gp->g_count++;        smp_unlock(&lk_gnode);}/* * Create a ref on a file system to prevent it from * being umounted.  Ref is destroyed by calling grele * with returned gnode pointer.  dev is optional. */struct gnode *fref(mp, dev)	register struct mount *mp;	register dev_t dev;{	smp_lock(&lk_gnode, LK_RETRY);	if ((mp == NULL) || (mp == (struct mount *) MSWAPX) || !(mp->m_flgs & MTE_DONE) || (dev && (mp->m_dev != dev))) {		smp_unlock(&lk_gnode);		return(NULL);	}	gactive(mp->m_rootgp);	mp->m_rootgp->g_count++;	smp_unlock(&lk_gnode);	return(mp->m_rootgp);}

⌨️ 快捷键说明

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