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

📄 balloc.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/ufs/balloc.c * * Copyright (C) 1998 * Daniel Pirkl <daniel.pirkl@email.cz> * Charles University, Faculty of Mathematics and Physics */#include <linux/fs.h>#include <linux/ufs_fs.h>#include <linux/stat.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/locks.h>#include <linux/quotaops.h>#include <asm/bitops.h>#include <asm/byteorder.h>#include "swab.h"#include "util.h"#undef UFS_BALLOC_DEBUG#ifdef UFS_BALLOC_DEBUG#define UFSD(x) printk("(%s, %d), %s:", __FILE__, __LINE__, __FUNCTION__); printk x;#else#define UFSD(x)#endifunsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);unsigned ufs_bitmap_search (struct super_block *, struct ufs_cg_private_info *, unsigned, unsigned);static unsigned char ufs_fragtable_8fpb[], ufs_fragtable_other[];void ufs_clusteracct(struct super_block *, struct ufs_cg_private_info *, unsigned, int);/* * Free 'count' fragments from fragment number 'fragment' */void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count) {	struct super_block * sb;	struct ufs_sb_private_info * uspi;	struct ufs_super_block_first * usb1;	struct ufs_cg_private_info * ucpi;	struct ufs_cylinder_group * ucg;	unsigned cgno, bit, end_bit, bbase, blkmap, i, blkno, cylno;		sb = inode->i_sb;	uspi = sb->u.ufs_sb.s_uspi;	usb1 = ubh_get_usb_first(USPI_UBH);		UFSD(("ENTER, fragment %u, count %u\n", fragment, count))		if (ufs_fragnum(fragment) + count > uspi->s_fpg)		ufs_error (sb, "ufs_free_fragments", "internal error");		lock_super(sb);		cgno = ufs_dtog(fragment);	bit = ufs_dtogd(fragment);	if (cgno >= uspi->s_ncg) {		ufs_panic (sb, "ufs_free_fragments", "freeing blocks are outside device");		goto failed;	}			ucpi = ufs_load_cylinder (sb, cgno);	if (!ucpi) 		goto failed;	ucg = ubh_get_ucg (UCPI_UBH);	if (!ufs_cg_chkmagic(sb, ucg)) {		ufs_panic (sb, "ufs_free_fragments", "internal error, bad magic number on cg %u", cgno);		goto failed;	}	end_bit = bit + count;	bbase = ufs_blknum (bit);	blkmap = ubh_blkmap (UCPI_UBH, ucpi->c_freeoff, bbase);	ufs_fragacct (sb, blkmap, ucg->cg_frsum, -1);	for (i = bit; i < end_bit; i++) {		if (ubh_isclr (UCPI_UBH, ucpi->c_freeoff, i))			ubh_setbit (UCPI_UBH, ucpi->c_freeoff, i);		else ufs_error (sb, "ufs_free_fragments",			"bit already cleared for fragment %u", i);	}		DQUOT_FREE_BLOCK (inode, count);		fs32_add(sb, &ucg->cg_cs.cs_nffree, count);	fs32_add(sb, &usb1->fs_cstotal.cs_nffree, count);	fs32_add(sb, &sb->fs_cs(cgno).cs_nffree, count);	blkmap = ubh_blkmap (UCPI_UBH, ucpi->c_freeoff, bbase);	ufs_fragacct(sb, blkmap, ucg->cg_frsum, 1);	/*	 * Trying to reassemble free fragments into block	 */	blkno = ufs_fragstoblks (bbase);	if (ubh_isblockset(UCPI_UBH, ucpi->c_freeoff, blkno)) {		fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb);		fs32_sub(sb, &usb1->fs_cstotal.cs_nffree, uspi->s_fpb);		fs32_sub(sb, &sb->fs_cs(cgno).cs_nffree, uspi->s_fpb);		if ((sb->u.ufs_sb.s_flags & UFS_CG_MASK) == UFS_CG_44BSD)			ufs_clusteracct (sb, ucpi, blkno, 1);		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);		fs32_add(sb, &usb1->fs_cstotal.cs_nbfree, 1);		fs32_add(sb, &sb->fs_cs(cgno).cs_nbfree, 1);		cylno = ufs_cbtocylno (bbase);		fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(bbase)), 1);		fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);	}		ubh_mark_buffer_dirty (USPI_UBH);	ubh_mark_buffer_dirty (UCPI_UBH);	if (sb->s_flags & MS_SYNCHRONOUS) {		ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi);		ubh_wait_on_buffer (UCPI_UBH);	}	sb->s_dirt = 1;		unlock_super (sb);	UFSD(("EXIT\n"))	return;failed:	unlock_super (sb);	UFSD(("EXIT (FAILED)\n"))	return;}/* * Free 'count' fragments from fragment number 'fragment' (free whole blocks) */void ufs_free_blocks (struct inode * inode, unsigned fragment, unsigned count) {	struct super_block * sb;	struct ufs_sb_private_info * uspi;	struct ufs_super_block_first * usb1;	struct ufs_cg_private_info * ucpi;	struct ufs_cylinder_group * ucg;	unsigned overflow, cgno, bit, end_bit, blkno, i, cylno;		sb = inode->i_sb;	uspi = sb->u.ufs_sb.s_uspi;	usb1 = ubh_get_usb_first(USPI_UBH);	UFSD(("ENTER, fragment %u, count %u\n", fragment, count))		if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {		ufs_error (sb, "ufs_free_blocks", "internal error, "			"fragment %u, count %u\n", fragment, count);		goto failed;	}	lock_super(sb);	do_more:	overflow = 0;	cgno = ufs_dtog (fragment);	bit = ufs_dtogd (fragment);	if (cgno >= uspi->s_ncg) {		ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device");		goto failed;	}	end_bit = bit + count;	if (end_bit > uspi->s_fpg) {		overflow = bit + count - uspi->s_fpg;		count -= overflow;		end_bit -= overflow;	}	ucpi = ufs_load_cylinder (sb, cgno);	if (!ucpi) 		goto failed;	ucg = ubh_get_ucg (UCPI_UBH);	if (!ufs_cg_chkmagic(sb, ucg)) {		ufs_panic (sb, "ufs_free_blocks", "internal error, bad magic number on cg %u", cgno);		goto failed;	}	for (i = bit; i < end_bit; i += uspi->s_fpb) {		blkno = ufs_fragstoblks(i);		if (ubh_isblockset(UCPI_UBH, ucpi->c_freeoff, blkno)) {			ufs_error(sb, "ufs_free_blocks", "freeing free fragment");		}		ubh_setblock(UCPI_UBH, ucpi->c_freeoff, blkno);		if ((sb->u.ufs_sb.s_flags & UFS_CG_MASK) == UFS_CG_44BSD)			ufs_clusteracct (sb, ucpi, blkno, 1);		DQUOT_FREE_BLOCK(inode, uspi->s_fpb);		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);		fs32_add(sb, &usb1->fs_cstotal.cs_nbfree, 1);		fs32_add(sb, &sb->fs_cs(cgno).cs_nbfree, 1);		cylno = ufs_cbtocylno(i);		fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(i)), 1);		fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);	}	ubh_mark_buffer_dirty (USPI_UBH);	ubh_mark_buffer_dirty (UCPI_UBH);	if (sb->s_flags & MS_SYNCHRONOUS) {		ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi);		ubh_wait_on_buffer (UCPI_UBH);	}	if (overflow) {		fragment += count;		count = overflow;		goto do_more;	}	sb->s_dirt = 1;	unlock_super (sb);	UFSD(("EXIT\n"))	return;failed:	unlock_super (sb);	UFSD(("EXIT (FAILED)\n"))	return;}#define NULLIFY_FRAGMENTS \	for (i = oldcount; i < newcount; i++) { \		bh = sb_getblk(sb, result + i); \		memset (bh->b_data, 0, sb->s_blocksize); \		mark_buffer_uptodate(bh, 1); \		mark_buffer_dirty (bh); \		if (IS_SYNC(inode)) { \			ll_rw_block (WRITE, 1, &bh); \			wait_on_buffer (bh); \		} \		brelse (bh); \	}unsigned ufs_new_fragments (struct inode * inode, u32 * p, unsigned fragment,	unsigned goal, unsigned count, int * err ){	struct super_block * sb;	struct ufs_sb_private_info * uspi;	struct ufs_super_block_first * usb1;	struct buffer_head * bh;	unsigned cgno, oldcount, newcount, tmp, request, i, result;		UFSD(("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count))		sb = inode->i_sb;	uspi = sb->u.ufs_sb.s_uspi;	usb1 = ubh_get_usb_first(USPI_UBH);	*err = -ENOSPC;	lock_super (sb);		tmp = fs32_to_cpu(sb, *p);	if (count + ufs_fragnum(fragment) > uspi->s_fpb) {		ufs_warning (sb, "ufs_new_fragments", "internal warning"			" fragment %u, count %u", fragment, count);		count = uspi->s_fpb - ufs_fragnum(fragment); 	}	oldcount = ufs_fragnum (fragment);	newcount = oldcount + count;	/*	 * Somebody else has just allocated our fragments	 */	if (oldcount) {		if (!tmp) {			ufs_error (sb, "ufs_new_fragments", "internal error, "				"fragment %u, tmp %u\n", fragment, tmp);			unlock_super (sb);			return (unsigned)-1;		}		if (fragment < inode->u.ufs_i.i_lastfrag) {			UFSD(("EXIT (ALREADY ALLOCATED)\n"))			unlock_super (sb);			return 0;		}	}	else {		if (tmp) {			UFSD(("EXIT (ALREADY ALLOCATED)\n"))			unlock_super(sb);			return 0;		}	}	/*	 * There is not enough space for user on the device	 */	if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(usb1, UFS_MINFREE) <= 0) {		unlock_super (sb);		UFSD(("EXIT (FAILED)\n"))		return 0;	}	if (goal >= uspi->s_size) 		goal = 0;	if (goal == 0) 		cgno = ufs_inotocg (inode->i_ino);	else		cgno = ufs_dtog (goal);	 	/*	 * allocate new fragment	 */	if (oldcount == 0) {		result = ufs_alloc_fragments (inode, cgno, goal, count, err);		if (result) {			*p = cpu_to_fs32(sb, result);			*err = 0;			inode->i_blocks += count << uspi->s_nspfshift;			inode->u.ufs_i.i_lastfrag = max_t(u32, inode->u.ufs_i.i_lastfrag, fragment + count);			NULLIFY_FRAGMENTS		}		unlock_super(sb);		UFSD(("EXIT, result %u\n", result))		return result;	}	/*	 * resize block	 */	result = ufs_add_fragments (inode, tmp, oldcount, newcount, err);	if (result) {		*err = 0;		inode->i_blocks += count << uspi->s_nspfshift;		inode->u.ufs_i.i_lastfrag = max_t(u32, inode->u.ufs_i.i_lastfrag, fragment + count);		NULLIFY_FRAGMENTS		unlock_super(sb);		UFSD(("EXIT, result %u\n", result))		return result;	}	/*	 * allocate new block and move data	 */	switch (fs32_to_cpu(sb, usb1->fs_optim)) {	    case UFS_OPTSPACE:		request = newcount;		if (uspi->s_minfree < 5 || fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree) 		    > uspi->s_dsize * uspi->s_minfree / (2 * 100) )			break;		usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);		break;	    default:		usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);		    case UFS_OPTTIME:		request = uspi->s_fpb;		if (fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree) < uspi->s_dsize *		    (uspi->s_minfree - 2) / 100)			break;		usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);		break;	}	result = ufs_alloc_fragments (inode, cgno, goal, request, err);	if (result) {		for (i = 0; i < oldcount; i++) {			bh = sb_bread(sb, tmp + i);			if(bh)			{				mark_buffer_clean (bh);				bh->b_blocknr = result + i;				mark_buffer_dirty (bh);				if (IS_SYNC(inode)) {					ll_rw_block (WRITE, 1, &bh);					wait_on_buffer (bh);				}				brelse (bh);			}			else			{				printk(KERN_ERR "ufs_new_fragments: bread fail\n");				return 0;			}		}		*p = cpu_to_fs32(sb, result);		*err = 0;		inode->i_blocks += count << uspi->s_nspfshift;		inode->u.ufs_i.i_lastfrag = max_t(u32, inode->u.ufs_i.i_lastfrag, fragment + count);		NULLIFY_FRAGMENTS		unlock_super(sb);		if (newcount < request)			ufs_free_fragments (inode, result + newcount, request - newcount);		ufs_free_fragments (inode, tmp, oldcount);		UFSD(("EXIT, result %u\n", result))		return result;	}	unlock_super(sb);	UFSD(("EXIT (FAILED)\n"))	return 0;}		unsigned ufs_add_fragments (struct inode * inode, unsigned fragment,	unsigned oldcount, unsigned newcount, int * err){	struct super_block * sb;	struct ufs_sb_private_info * uspi;	struct ufs_super_block_first * usb1;	struct ufs_cg_private_info * ucpi;	struct ufs_cylinder_group * ucg;	unsigned cgno, fragno, fragoff, count, fragsize, i;		UFSD(("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount))		sb = inode->i_sb;

⌨️ 快捷键说明

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