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

📄 ufs_gnode.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
		for (i = 0; i < count; i += CLSIZE) {			smp_lock(&lk_cmap, LK_RETRY);			if (mfind(ogp->g_dev, bn + i, ogp))				munhash(ogp->g_dev, bn + i, ogp);			smp_unlock(&lk_cmap);		}		splx(s);		bp = bread(ogp->g_dev, bn, size, (struct gnode *)0);		if (bp->b_flags & B_ERROR) {			u.u_error = EIO;			ogp->g_size = osize;			brelse(bp);			return(EIO);		}		bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));		bdwrite(bp);	}	/*	 * Update file and block pointers	 * on disk before we start freeing blocks.	 * If we crash before free'ing blocks below,	 * the blocks will be returned to the free list.	 * lastiblock values are also normalized to -1	 * for calls to indirtrunc below.	 */	tip = *ogp;			/*  structure copy */	tip.g_size = osize;	for (level = TRIPLE; level >= SINGLE; level--)		if (lastiblock[level] < 0) {			G_TO_I(ogp)->di_ib[level] = 0;			lastiblock[level] = -1;		}	for (i = NDADDR - 1; i > lastblock; i--) {		G_TO_I(ogp)->di_db[i] = 0;	}		ogp->g_size = length;	ogp->g_flag |= GCHG|GUPD;	ufs_gupdat(ogp, timepick, timepick, 1, (struct ucred *) 0);	/*	 * Indirect blocks first.	 */	ufs_ip = G_TO_I(&tip);	for (level = TRIPLE; level >= SINGLE; level--) {		bn = ufs_ip->di_ib[level];		if (bn != 0) {			blocksreleased +=			indirtrunc(&tip, bn, lastiblock[level], level);			if (lastiblock[level] < 0) {				ufs_ip->di_ib[level] = 0;				free(&tip, bn, (off_t)fs->fs_bsize);				blocksreleased += nblocks;			}		}		if (lastiblock[level] >= 0)			goto done;	}	/*	 * All whole direct blocks or frags.	 */	for (i = NDADDR - 1; i > lastblock; i--) {		register int bsize;		bn = ufs_ip->di_db[i];		if (bn == 0)			continue;		ufs_ip->di_db[i] = 0;		bsize = (off_t)blksize(fs, &tip, i);		free(&tip, bn, bsize);		blocksreleased += btodb(bsize);	}	if (lastblock < 0)		goto done;	/*	 * Finally, look for a change in size of the	 * last direct block; release any frags.	 */	bn = ufs_ip->di_db[lastblock];	if (bn != 0) {		int oldspace, newspace;		/*		 * Calculate amount of space we're giving		 * back as old block size minus new block size.		 */		oldspace = blksize(fs, &tip, lastblock);		tip.g_size = length;		newspace = blksize(fs, &tip, lastblock);		if (newspace == 0)			panic("ufs_gtrunc: newspace");		if (oldspace - newspace > 0) {			/*			 * Block number of space to be free'd is			 * the old block # plus the number of frags			 * required for the storage we're keeping.			 */			bn += numfrags(fs, newspace);			free(&tip, bn, oldspace - newspace);			blocksreleased += btodb(oldspace - newspace);		}	}done:/* BEGIN PARANOIA */	for (level = SINGLE; level <= TRIPLE; level++)		if (ufs_ip->di_ib[level] != G_TO_I(ogp)->di_ib[level])			panic("ufs_gtrunc1");	for (i = 0; i < NDADDR; i++)		if (ufs_ip->di_db[i] != G_TO_I(ogp)->di_db[i])			panic("ufs_gtrunc2");/* END PARANOIA */	ogp->g_blocks -= blocksreleased;	G_TO_I(ogp)->di_blocks = ogp->g_blocks;	if (G_TO_I(ogp)->di_blocks < 0) {		/* sanity */		ogp->g_blocks = G_TO_I(ogp)->di_blocks = 0;	}		ogp->g_flag |= GCHG;#ifdef QUOTA	(void) chkdq(ogp, -blocksreleased, 0);#endif	return(0);}/* * Release blocks associated with the gnode gp and * stored in the indirect block bn.  Blocks are free'd * in LIFO order up to (but not including) lastbn.  If * level is greater than SINGLE, the block is an indirect * block and recursive calls to indirtrunc must be used to * cleanse other indirect blocks. * * NB: triple indirect blocks are untested. */longindirtrunc(gp, bn, lastbn, level)	register struct gnode *gp;	daddr_t bn, lastbn;	int level;{	register int i;	struct buf *bp, *copy;	register daddr_t *bap;	register struct fs *fs = FS(gp);	register daddr_t nb;	daddr_t last;	register long factor;	int blocksreleased = 0, nblocks;	/*	 * Calculate index in current block of last	 * block to be kept.  -1 indicates the entire	 * block so we need not calculate the index.	 */	factor = 1;/*	printf("indirtrunc: fs 0x%x\n", fs);	*/	for (i = SINGLE; i < level; i++)		factor *= NINDIR(fs);	last = lastbn;	if (lastbn > 0)		last /= factor;	nblocks = btodb(fs->fs_bsize);	/*	 * Get buffer of block pointers, zero those 	 * entries corresponding to blocks to be free'd,	 * and update on disk copy first.	 */	copy = geteblk((int)fs->fs_bsize);	bp = bread(gp->g_dev, fsbtodb(fs, bn), (int)fs->fs_bsize, 		(struct gnode *) NULL);	if (bp->b_flags&B_ERROR) {		brelse(copy);		brelse(bp);		return (0);	}	bap = bp->b_un.b_daddr;	bcopy((caddr_t)bap, (caddr_t)copy->b_un.b_daddr, (u_int)fs->fs_bsize);	bzero((caddr_t)&bap[last + 1],	  (u_int)(NINDIR(fs) - (last + 1)) * sizeof (daddr_t));	bwrite(bp);	bp = copy, bap = bp->b_un.b_daddr;	/*	 * Recursively free totally unused blocks.	 */	for (i = NINDIR(fs) - 1; i > last; i--) {		nb = bap[i];		if (nb == 0)			continue;		if (level > SINGLE)			blocksreleased +=			    indirtrunc(gp, nb, (daddr_t)-1, level - 1);		free(gp, nb, (int)fs->fs_bsize);		blocksreleased += nblocks;	}	/*	 * Recursively free last partial block.	 */	if (level > SINGLE && lastbn >= 0) {		last = lastbn % factor;		nb = bap[i];		if (nb != 0)			blocksreleased += indirtrunc(gp, nb, last, level - 1);	}	brelse(bp);	return (blocksreleased);}/* * Lock a gnode. If its already locked, set the WANT bit and sleep. */ufs_glock(gp)	register struct gnode *gp;{	if (gp->g_mp->m_fstype != GT_ULTRIX) {		printf("ufs_glock: gp 0x%x type %d\n", gp,		gp->g_mp->m_fstype);		panic("ufs_glock: gp type not GT_ULTRIX");	}	gfs_lock(gp);}/* * Unlock a gnode.  If WANT bit is on, wakeup. */ufs_gunlock(gp)	register struct gnode *gp;{	if (!glocked(gp)) {		cprintf("ufs_gunlock: gp unlocked, dev 0x%x gno %d\n",		gp->g_dev, gp->g_number);		panic("ufs_gunlock");	}	if (gp->g_mp->m_fstype != GT_ULTRIX) {		printf("ufs_gulock: gp 0x%x type %d\n", gp,		gp->g_mp->m_fstype);		panic("ufs_gulock: gp type not GT_ULTRIX");	}	gfs_unlock(gp);}/* * Check accessed and update flags on * a gnode structure. * If any is on, update the gnode * with the appropriate time. * If waitfor is given, then must insure * i/o order so wait for write to complete. */struct timeval guniqtm;	/* unique UFS timestamp */extern struct lock_t lk_gnode;extern struct timeval atime;extern struct timeval btime;ufs_gupdat(gp, ta, tm, waitfor, cred)	register struct gnode *gp;	register struct timeval *ta, *tm;	int waitfor;	struct ucred *cred;{	register struct buf *bp;	register struct ufs_inode *dp;	register struct fs *fs;	gassert(gp);	if ((gp->g_flag & (GUPD|GACC|GCHG|GMOD)) != 0) {		fs = FS(gp);		G_TO_I(gp)->di_blocks = gp->g_blocks;		if (((gp->g_mode & GFMT) == GFCHR) ||		    ((gp->g_mode & GFMT) == GFBLK))			G_TO_I(gp)->di_rdev = gp->g_rdev;		if (fs->fs_ronly)			return(EROFS);		bp = bread(gp->g_dev, fsbtodb(fs, itod(fs, gp->g_number)),			(int)fs->fs_bsize, (struct gnode *) NULL);					if (bp->b_flags & B_ERROR) {			brelse(bp);			return(EIO);		}		if ((gp->g_flag & (GUPD|GACC|GCHG)) != 0) {			/*			 * Mark gnode with the current (unique) timestamp.			 * We need to synchronize with a spin lock to do this,			 * lk_gnode seems reasonable to me -- chet.			 */			smp_lock(&lk_gnode, LK_RETRY);			if (timepick->tv_sec > guniqtm.tv_sec ||			    timepick->tv_usec > guniqtm.tv_usec)				guniqtm = *(timepick);			else				guniqtm.tv_usec++;			if (gp->g_flag & GACC) {				if (ta == &atime || ta == &btime)					gp->g_atime = guniqtm;				else					gp->g_atime= *ta;			}			if (gp->g_flag & GUPD) {				if (tm == &atime || tm == &btime)					gp->g_mtime = guniqtm;				else					gp->g_mtime = *tm;			}			if (gp->g_flag & GCHG)				gp->g_ctime = guniqtm;			smp_unlock(&lk_gnode);		}				gp->g_flag &= ~(GUPD|GACC|GCHG|GMOD);		dp = bp->b_un.b_dino + itoo(fs, gp->g_number);		bcopy(&G_TO_I(gp)->di_ic, &dp->di_ic,		      sizeof(struct ufs_inode));		if (waitfor)			bwrite(bp);		else {			if (gp->g_mp->m_flags & M_SYNC)				bwrite(bp);			else				bdwrite(bp);		}	}	return(u.u_error);}

⌨️ 快捷键说明

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