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

📄 ffs_alloc.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	int cg;	daddr_t bpref;	int len;{	register struct fs *fs;	register struct cg *cgp;	struct buf *bp;	int i, run, bno, bit, map;	u_char *mapp;	fs = ip->i_fs;	if (fs->fs_cs(fs, cg).cs_nbfree < len)		return (NULL);	if (bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize,	    NOCRED, &bp))		goto fail;	cgp = (struct cg *)bp->b_data;	if (!cg_chkmagic(cgp))		goto fail;	/*	 * Check to see if a cluster of the needed size (or bigger) is	 * available in this cylinder group.	 */	for (i = len; i <= fs->fs_contigsumsize; i++)		if (cg_clustersum(cgp)[i] > 0)			break;	if (i > fs->fs_contigsumsize)		goto fail;	/*	 * Search the cluster map to find a big enough cluster.	 * We take the first one that we find, even if it is larger	 * than we need as we prefer to get one close to the previous	 * block allocation. We do not search before the current	 * preference point as we do not want to allocate a block	 * that is allocated before the previous one (as we will	 * then have to wait for another pass of the elevator	 * algorithm before it will be read). We prefer to fail and	 * be recalled to try an allocation in the next cylinder group.	 */	if (dtog(fs, bpref) != cg)		bpref = 0;	else		bpref = fragstoblks(fs, dtogd(fs, blknum(fs, bpref)));	mapp = &cg_clustersfree(cgp)[bpref / NBBY];	map = *mapp++;	bit = 1 << (bpref % NBBY);	for (run = 0, i = bpref; i < cgp->cg_nclusterblks; i++) {		if ((map & bit) == 0) {			run = 0;		} else {			run++;			if (run == len)				break;		}		if ((i & (NBBY - 1)) != (NBBY - 1)) {			bit <<= 1;		} else {			map = *mapp++;			bit = 1;		}	}	if (i == cgp->cg_nclusterblks)		goto fail;	/*	 * Allocate the cluster that we have found.	 */	bno = cg * fs->fs_fpg + blkstofrags(fs, i - run + 1);	len = blkstofrags(fs, len);	for (i = 0; i < len; i += fs->fs_frag)		if (ffs_alloccgblk(fs, cgp, bno + i) != bno + i)			panic("ffs_clusteralloc: lost block");	brelse(bp);	return (bno);fail:	brelse(bp);	return (0);}/* * Determine whether an inode can be allocated. * * Check to see if an inode is available, and if it is, * allocate it using the following policy: *   1) allocate the requested inode. *   2) allocate the next available inode after the requested *      inode in the specified cylinder group. */static ino_tffs_nodealloccg(ip, cg, ipref, mode)	struct inode *ip;	int cg;	daddr_t ipref;	int mode;{	register struct fs *fs;	register struct cg *cgp;	struct buf *bp;	int error, start, len, loc, map, i;	fs = ip->i_fs;	if (fs->fs_cs(fs, cg).cs_nifree == 0)		return (NULL);	error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),		(int)fs->fs_cgsize, NOCRED, &bp);	if (error) {		brelse(bp);		return (NULL);	}	cgp = (struct cg *)bp->b_data;	if (!cg_chkmagic(cgp) || cgp->cg_cs.cs_nifree == 0) {		brelse(bp);		return (NULL);	}	cgp->cg_time = time.tv_sec;	if (ipref) {		ipref %= fs->fs_ipg;		if (isclr(cg_inosused(cgp), ipref))			goto gotit;	}	start = cgp->cg_irotor / NBBY;	len = howmany(fs->fs_ipg - cgp->cg_irotor, NBBY);	loc = skpc(0xff, len, &cg_inosused(cgp)[start]);	if (loc == 0) {		len = start + 1;		start = 0;		loc = skpc(0xff, len, &cg_inosused(cgp)[0]);		if (loc == 0) {			printf("cg = %d, irotor = %d, fs = %s\n",			    cg, cgp->cg_irotor, fs->fs_fsmnt);			panic("ffs_nodealloccg: map corrupted");			/* NOTREACHED */		}	}	i = start + len - loc;	map = cg_inosused(cgp)[i];	ipref = i * NBBY;	for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) {		if ((map & i) == 0) {			cgp->cg_irotor = ipref;			goto gotit;		}	}	printf("fs = %s\n", fs->fs_fsmnt);	panic("ffs_nodealloccg: block not in map");	/* NOTREACHED */gotit:	setbit(cg_inosused(cgp), ipref);	cgp->cg_cs.cs_nifree--;	fs->fs_cstotal.cs_nifree--;	fs->fs_cs(fs, cg).cs_nifree--;	fs->fs_fmod = 1;	if ((mode & IFMT) == IFDIR) {		cgp->cg_cs.cs_ndir++;		fs->fs_cstotal.cs_ndir++;		fs->fs_cs(fs, cg).cs_ndir++;	}	bdwrite(bp);	return (cg * fs->fs_ipg + ipref);}/* * Free a block or fragment. * * The specified block or fragment is placed back in the * free map. If a fragment is deallocated, a possible  * block reassembly is checked. */ffs_blkfree(ip, bno, size)	register struct inode *ip;	daddr_t bno;	long size;{	register struct fs *fs;	register struct cg *cgp;	struct buf *bp;	daddr_t blkno;	int i, error, cg, blk, frags, bbase;	fs = ip->i_fs;	if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) {		printf("dev = 0x%x, bsize = %d, size = %d, fs = %s\n",		    ip->i_dev, fs->fs_bsize, size, fs->fs_fsmnt);		panic("blkfree: bad size");	}	cg = dtog(fs, bno);	if ((u_int)bno >= fs->fs_size) {		printf("bad block %d, ino %d\n", bno, ip->i_number);		ffs_fserr(fs, ip->i_uid, "bad block");		return;	}	error = bread(ip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),		(int)fs->fs_cgsize, NOCRED, &bp);	if (error) {		brelse(bp);		return;	}	cgp = (struct cg *)bp->b_data;	if (!cg_chkmagic(cgp)) {		brelse(bp);		return;	}	cgp->cg_time = time.tv_sec;	bno = dtogd(fs, bno);	if (size == fs->fs_bsize) {		blkno = fragstoblks(fs, bno);		if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) {			printf("dev = 0x%x, block = %d, fs = %s\n",			    ip->i_dev, bno, fs->fs_fsmnt);			panic("blkfree: freeing free block");		}		ffs_setblock(fs, cg_blksfree(cgp), blkno);		ffs_clusteracct(fs, cgp, blkno, 1);		cgp->cg_cs.cs_nbfree++;		fs->fs_cstotal.cs_nbfree++;		fs->fs_cs(fs, cg).cs_nbfree++;		i = cbtocylno(fs, bno);		cg_blks(fs, cgp, i)[cbtorpos(fs, bno)]++;		cg_blktot(cgp)[i]++;	} else {		bbase = bno - fragnum(fs, bno);		/*		 * decrement the counts associated with the old frags		 */		blk = blkmap(fs, cg_blksfree(cgp), bbase);		ffs_fragacct(fs, blk, cgp->cg_frsum, -1);		/*		 * deallocate the fragment		 */		frags = numfrags(fs, size);		for (i = 0; i < frags; i++) {			if (isset(cg_blksfree(cgp), bno + i)) {				printf("dev = 0x%x, block = %d, fs = %s\n",				    ip->i_dev, bno + i, fs->fs_fsmnt);				panic("blkfree: freeing free frag");			}			setbit(cg_blksfree(cgp), bno + i);		}		cgp->cg_cs.cs_nffree += i;		fs->fs_cstotal.cs_nffree += i;		fs->fs_cs(fs, cg).cs_nffree += i;		/*		 * add back in counts associated with the new frags		 */		blk = blkmap(fs, cg_blksfree(cgp), bbase);		ffs_fragacct(fs, blk, cgp->cg_frsum, 1);		/*		 * if a complete block has been reassembled, account for it		 */		blkno = fragstoblks(fs, bbase);		if (ffs_isblock(fs, cg_blksfree(cgp), blkno)) {			cgp->cg_cs.cs_nffree -= fs->fs_frag;			fs->fs_cstotal.cs_nffree -= fs->fs_frag;			fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;			ffs_clusteracct(fs, cgp, blkno, 1);			cgp->cg_cs.cs_nbfree++;			fs->fs_cstotal.cs_nbfree++;			fs->fs_cs(fs, cg).cs_nbfree++;			i = cbtocylno(fs, bbase);			cg_blks(fs, cgp, i)[cbtorpos(fs, bbase)]++;			cg_blktot(cgp)[i]++;		}	}	fs->fs_fmod = 1;	bdwrite(bp);}/* * Free an inode. * * The specified inode is placed back in the free map. */intffs_vfree(ap)	struct vop_vfree_args /* {		struct vnode *a_pvp;		ino_t a_ino;		int a_mode;	} */ *ap;{	register struct fs *fs;	register struct cg *cgp;	register struct inode *pip;	ino_t ino = ap->a_ino;	struct buf *bp;	int error, cg;	pip = VTOI(ap->a_pvp);	fs = pip->i_fs;	if ((u_int)ino >= fs->fs_ipg * fs->fs_ncg)		panic("ifree: range: dev = 0x%x, ino = %d, fs = %s\n",		    pip->i_dev, ino, fs->fs_fsmnt);	cg = ino_to_cg(fs, ino);	error = bread(pip->i_devvp, fsbtodb(fs, cgtod(fs, cg)),		(int)fs->fs_cgsize, NOCRED, &bp);	if (error) {		brelse(bp);		return (0);	}	cgp = (struct cg *)bp->b_data;	if (!cg_chkmagic(cgp)) {		brelse(bp);		return (0);	}	cgp->cg_time = time.tv_sec;	ino %= fs->fs_ipg;	if (isclr(cg_inosused(cgp), ino)) {		printf("dev = 0x%x, ino = %d, fs = %s\n",		    pip->i_dev, ino, fs->fs_fsmnt);		if (fs->fs_ronly == 0)			panic("ifree: freeing free inode");	}	clrbit(cg_inosused(cgp), ino);	if (ino < cgp->cg_irotor)		cgp->cg_irotor = ino;	cgp->cg_cs.cs_nifree++;	fs->fs_cstotal.cs_nifree++;	fs->fs_cs(fs, cg).cs_nifree++;	if ((ap->a_mode & IFMT) == IFDIR) {		cgp->cg_cs.cs_ndir--;		fs->fs_cstotal.cs_ndir--;		fs->fs_cs(fs, cg).cs_ndir--;	}	fs->fs_fmod = 1;	bdwrite(bp);	return (0);}/* * Find a block of the specified size in the specified cylinder group. * * It is a panic if a request is made to find a block if none are * available. */static daddr_tffs_mapsearch(fs, cgp, bpref, allocsiz)	register struct fs *fs;	register struct cg *cgp;	daddr_t bpref;	int allocsiz;{	daddr_t bno;	int start, len, loc, i;	int blk, field, subfield, pos;	/*	 * find the fragment by searching through the free block	 * map for an appropriate bit pattern	 */	if (bpref)		start = dtogd(fs, bpref) / NBBY;	else		start = cgp->cg_frotor / NBBY;	len = howmany(fs->fs_fpg, NBBY) - start;	loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[start],		(u_char *)fragtbl[fs->fs_frag],		(u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));	if (loc == 0) {		len = start + 1;		start = 0;		loc = scanc((u_int)len, (u_char *)&cg_blksfree(cgp)[0],			(u_char *)fragtbl[fs->fs_frag],			(u_char)(1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));		if (loc == 0) {			printf("start = %d, len = %d, fs = %s\n",			    start, len, fs->fs_fsmnt);			panic("ffs_alloccg: map corrupted");			/* NOTREACHED */		}	}	bno = (start + len - loc) * NBBY;	cgp->cg_frotor = bno;	/*	 * found the byte in the map	 * sift through the bits to find the selected frag	 */	for (i = bno + NBBY; bno < i; bno += fs->fs_frag) {		blk = blkmap(fs, cg_blksfree(cgp), bno);		blk <<= 1;		field = around[allocsiz];		subfield = inside[allocsiz];		for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) {			if ((blk & field) == subfield)				return (bno + pos);			field <<= 1;			subfield <<= 1;		}	}	printf("bno = %d, fs = %s\n", bno, fs->fs_fsmnt);	panic("ffs_alloccg: block not in map");	return (-1);}/* * Update the cluster map because of an allocation or free. * * Cnt == 1 means free; cnt == -1 means allocating. */ffs_clusteracct(fs, cgp, blkno, cnt)	struct fs *fs;	struct cg *cgp;	daddr_t blkno;	int cnt;{	long *sump;	u_char *freemapp, *mapp;	int i, start, end, forw, back, map, bit;	if (fs->fs_contigsumsize <= 0)		return;	freemapp = cg_clustersfree(cgp);	sump = cg_clustersum(cgp);	/*	 * Allocate or clear the actual block.	 */	if (cnt > 0)		setbit(freemapp, blkno);	else		clrbit(freemapp, blkno);	/*	 * Find the size of the cluster going forward.	 */	start = blkno + 1;	end = start + fs->fs_contigsumsize;	if (end >= cgp->cg_nclusterblks)		end = cgp->cg_nclusterblks;	mapp = &freemapp[start / NBBY];	map = *mapp++;	bit = 1 << (start % NBBY);	for (i = start; i < end; i++) {		if ((map & bit) == 0)			break;		if ((i & (NBBY - 1)) != (NBBY - 1)) {			bit <<= 1;		} else {			map = *mapp++;			bit = 1;		}	}	forw = i - start;	/*	 * Find the size of the cluster going backward.	 */	start = blkno - 1;	end = start - fs->fs_contigsumsize;	if (end < 0)		end = -1;	mapp = &freemapp[start / NBBY];	map = *mapp--;	bit = 1 << (start % NBBY);	for (i = start; i > end; i--) {		if ((map & bit) == 0)			break;		if ((i & (NBBY - 1)) != 0) {			bit >>= 1;		} else {			map = *mapp--;			bit = 1 << (NBBY - 1);		}	}	back = start - i;	/*	 * Account for old cluster and the possibly new forward and	 * back clusters.	 */	i = back + forw + 1;	if (i > fs->fs_contigsumsize)		i = fs->fs_contigsumsize;	sump[i] += cnt;	if (back > 0)		sump[back] -= cnt;	if (forw > 0)		sump[forw] -= cnt;}/* * Fserr prints the name of a file system with an error diagnostic. *  * The form of the error message is: *	fs: error message */static voidffs_fserr(fs, uid, cp)	struct fs *fs;	u_int uid;	char *cp;{	log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp);}

⌨️ 快捷键说明

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