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

📄 balloc.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
📖 第 1 页 / 共 2 页
字号:
		if (next < maxblocks && ext3_test_allocatable(next, bh))		return next;		/* The bitmap search --- search forward alternately	 * through the actual bitmap and the last-committed copy	 * until we find a bit free in both. */	while (here < maxblocks) {		next  = ext3_find_next_zero_bit ((unsigned long *) bh->b_data, 						 maxblocks, here);		if (next >= maxblocks)			return -1;		if (ext3_test_allocatable(next, bh))			return next;		J_ASSERT_BH(bh, bh2jh(bh)->b_committed_data);		here = ext3_find_next_zero_bit			((unsigned long *) bh2jh(bh)->b_committed_data, 			 maxblocks, next);	}	return -1;}/* * ext3_new_block uses a goal block to assist allocation.  If the goal is * free, or there is a free block within 32 blocks of the goal, that block * is allocated.  Otherwise a forward search is made for a free block; within  * each block group the search first looks for an entire free byte in the block * bitmap, and then for any free bit if that fails. * This function also updates quota and i_blocks field. */int ext3_new_block (handle_t *handle, struct inode * inode,		unsigned long goal, u32 * prealloc_count,		u32 * prealloc_block, int * errp){	struct buffer_head * bh, *bhtmp;	struct buffer_head * bh2;#if 0	char * p, * r;#endif	int i, j, k, tmp, alloctmp;	int bitmap_nr;	int fatal = 0, err;	int performed_allocation = 0;	struct super_block * sb;	struct ext3_group_desc * gdp;	struct ext3_super_block * es;#ifdef EXT3FS_DEBUG	static int goal_hits = 0, goal_attempts = 0;#endif	*errp = -ENOSPC;	sb = inode->i_sb;	if (!sb) {		printk ("ext3_new_block: nonexistent device");		return 0;	}	/*	 * Check quota for allocation of this block.	 */	if (DQUOT_ALLOC_BLOCK(inode, 1)) {		*errp = -EDQUOT;		return 0;	}	lock_super (sb);	es = sb->u.ext3_sb.s_es;	if (le32_to_cpu(es->s_free_blocks_count) <=			le32_to_cpu(es->s_r_blocks_count) &&	    ((sb->u.ext3_sb.s_resuid != current->fsuid) &&	     (sb->u.ext3_sb.s_resgid == 0 ||	      !in_group_p (sb->u.ext3_sb.s_resgid)) && 	     !capable(CAP_SYS_RESOURCE)))		goto out;	ext3_debug ("goal=%lu.\n", goal);	/*	 * First, test whether the goal block is free.	 */	if (goal < le32_to_cpu(es->s_first_data_block) ||	    goal >= le32_to_cpu(es->s_blocks_count))		goal = le32_to_cpu(es->s_first_data_block);	i = (goal - le32_to_cpu(es->s_first_data_block)) /			EXT3_BLOCKS_PER_GROUP(sb);	gdp = ext3_get_group_desc (sb, i, &bh2);	if (!gdp)		goto io_error;	if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) {		j = ((goal - le32_to_cpu(es->s_first_data_block)) %				EXT3_BLOCKS_PER_GROUP(sb));#ifdef EXT3FS_DEBUG		if (j)			goal_attempts++;#endif		bitmap_nr = load_block_bitmap (sb, i);		if (bitmap_nr < 0)			goto io_error;				bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];		ext3_debug ("goal is at %d:%d.\n", i, j);		if (ext3_test_allocatable(j, bh)) {#ifdef EXT3FS_DEBUG			goal_hits++;			ext3_debug ("goal bit allocated.\n");#endif			goto got_block;		}		j = find_next_usable_block(j, bh, EXT3_BLOCKS_PER_GROUP(sb));		if (j >= 0)			goto search_back;	}	ext3_debug ("Bit not found in block group %d.\n", i);	/*	 * Now search the rest of the groups.  We assume that 	 * i and gdp correctly point to the last group visited.	 */	for (k = 0; k < sb->u.ext3_sb.s_groups_count; k++) {		i++;		if (i >= sb->u.ext3_sb.s_groups_count)			i = 0;		gdp = ext3_get_group_desc (sb, i, &bh2);		if (!gdp) {			*errp = -EIO;			goto out;		}		if (le16_to_cpu(gdp->bg_free_blocks_count) > 0) {			bitmap_nr = load_block_bitmap (sb, i);			if (bitmap_nr < 0)				goto io_error;				bh = sb->u.ext3_sb.s_block_bitmap[bitmap_nr];			j = find_next_usable_block(-1, bh, 						   EXT3_BLOCKS_PER_GROUP(sb));			if (j >= 0) 				goto search_back;		}	}	/* No space left on the device */	goto out;search_back:	/* 	 * We have succeeded in finding a free byte in the block	 * bitmap.  Now search backwards up to 7 bits to find the	 * start of this group of free blocks.	 */	for (	k = 0;		k < 7 && j > 0 && ext3_test_allocatable(j - 1, bh);		k++, j--)		;	got_block:	ext3_debug ("using block group %d(%d)\n", i, gdp->bg_free_blocks_count);	/* Make sure we use undo access for the bitmap, because it is           critical that we do the frozen_data COW on bitmap buffers in           all cases even if the buffer is in BJ_Forget state in the           committing transaction.  */	BUFFER_TRACE(bh, "get undo access for marking new block");	fatal = ext3_journal_get_undo_access(handle, bh);	if (fatal) goto out;		BUFFER_TRACE(bh2, "get_write_access");	fatal = ext3_journal_get_write_access(handle, bh2);	if (fatal) goto out;	BUFFER_TRACE(sb->u.ext3_sb.s_sbh, "get_write_access");	fatal = ext3_journal_get_write_access(handle, sb->u.ext3_sb.s_sbh);	if (fatal) goto out;	tmp = j + i * EXT3_BLOCKS_PER_GROUP(sb)				+ le32_to_cpu(es->s_first_data_block);	if (tmp == le32_to_cpu(gdp->bg_block_bitmap) ||	    tmp == le32_to_cpu(gdp->bg_inode_bitmap) ||	    in_range (tmp, le32_to_cpu(gdp->bg_inode_table),		      sb->u.ext3_sb.s_itb_per_group))		ext3_error (sb, "ext3_new_block",			    "Allocating block in system zone - "			    "block = %u", tmp);	/* The superblock lock should guard against anybody else beating	 * us to this point! */	J_ASSERT_BH(bh, !ext3_test_bit(j, bh->b_data));	BUFFER_TRACE(bh, "setting bitmap bit");	ext3_set_bit(j, bh->b_data);	performed_allocation = 1;#ifdef CONFIG_JBD_DEBUG	{		struct buffer_head *debug_bh;		/* Record bitmap buffer state in the newly allocated block */		debug_bh = sb_get_hash_table(sb, tmp);		if (debug_bh) {			BUFFER_TRACE(debug_bh, "state when allocated");			BUFFER_TRACE2(debug_bh, bh, "bitmap state");			brelse(debug_bh);		}	}#endif	if (buffer_jbd(bh) && bh2jh(bh)->b_committed_data)		J_ASSERT_BH(bh, !ext3_test_bit(j, bh2jh(bh)->b_committed_data));	bhtmp = bh;	alloctmp = j;	ext3_debug ("found bit %d\n", j);	/*	 * Do block preallocation now if required.	 */#ifdef EXT3_PREALLOCATE	/*	 * akpm: this is not enabled for ext3.  Need to use	 * ext3_test_allocatable()	 */	/* Writer: ->i_prealloc* */	if (prealloc_count && !*prealloc_count) {		int	prealloc_goal;		unsigned long next_block = tmp + 1;		prealloc_goal = es->s_prealloc_blocks ?			es->s_prealloc_blocks : EXT3_DEFAULT_PREALLOC_BLOCKS;		*prealloc_block = next_block;		/* Writer: end */		for (k = 1;		     k < prealloc_goal && (j + k) < EXT3_BLOCKS_PER_GROUP(sb);		     k++, next_block++) {			if (DQUOT_PREALLOC_BLOCK(inode, 1))				break;			/* Writer: ->i_prealloc* */			if (*prealloc_block + *prealloc_count != next_block ||			    ext3_set_bit (j + k, bh->b_data)) {				/* Writer: end */				DQUOT_FREE_BLOCK(inode, 1); 				break;			}			(*prealloc_count)++;			/* Writer: end */		}			/*		 * As soon as we go for per-group spinlocks we'll need these		 * done inside the loop above.		 */		gdp->bg_free_blocks_count =			cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) -			       (k - 1));		es->s_free_blocks_count =			cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) -			       (k - 1));		ext3_debug ("Preallocated a further %lu bits.\n",			       (k - 1));	}#endif	j = tmp;	BUFFER_TRACE(bh, "journal_dirty_metadata for bitmap block");	err = ext3_journal_dirty_metadata(handle, bh);	if (!fatal) fatal = err;		if (j >= le32_to_cpu(es->s_blocks_count)) {		ext3_error (sb, "ext3_new_block",			    "block(%d) >= blocks count(%d) - "			    "block_group = %d, es == %p ",j,			le32_to_cpu(es->s_blocks_count), i, es);		goto out;	}	/*	 * It is up to the caller to add the new buffer to a journal	 * list of some description.  We don't know in advance whether	 * the caller wants to use it as metadata or data.	 */	ext3_debug ("allocating block %d. "		    "Goal hits %d of %d.\n", j, goal_hits, goal_attempts);	gdp->bg_free_blocks_count =			cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - 1);	es->s_free_blocks_count =			cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - 1);	BUFFER_TRACE(bh2, "journal_dirty_metadata for group descriptor");	err = ext3_journal_dirty_metadata(handle, bh2);	if (!fatal) fatal = err;		BUFFER_TRACE(bh, "journal_dirty_metadata for superblock");	err = ext3_journal_dirty_metadata(handle, sb->u.ext3_sb.s_sbh);	if (!fatal) fatal = err;	sb->s_dirt = 1;	if (fatal)		goto out;	unlock_super (sb);	*errp = 0;	return j;	io_error:	*errp = -EIO;out:	if (fatal) {		*errp = fatal;		ext3_std_error(sb, fatal);	}	unlock_super (sb);	/*	 * Undo the block allocation	 */	if (!performed_allocation)		DQUOT_FREE_BLOCK(inode, 1);	return 0;	}unsigned long ext3_count_free_blocks (struct super_block * sb){#ifdef EXT3FS_DEBUG	struct ext3_super_block * es;	unsigned long desc_count, bitmap_count, x;	int bitmap_nr;	struct ext3_group_desc * gdp;	int i;		lock_super (sb);	es = sb->u.ext3_sb.s_es;	desc_count = 0;	bitmap_count = 0;	gdp = NULL;	for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {		gdp = ext3_get_group_desc (sb, i, NULL);		if (!gdp)			continue;		desc_count += le16_to_cpu(gdp->bg_free_blocks_count);		bitmap_nr = load_block_bitmap (sb, i);		if (bitmap_nr < 0)			continue;				x = ext3_count_free (sb->u.ext3_sb.s_block_bitmap[bitmap_nr],				     sb->s_blocksize);		printk ("group %d: stored = %d, counted = %lu\n",			i, le16_to_cpu(gdp->bg_free_blocks_count), x);		bitmap_count += x;	}	printk("ext3_count_free_blocks: stored = %lu, computed = %lu, %lu\n",	       le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count);	unlock_super (sb);	return bitmap_count;#else	return le32_to_cpu(sb->u.ext3_sb.s_es->s_free_blocks_count);#endif}static inline int block_in_use (unsigned long block,				struct super_block * sb,				unsigned char * map){	return ext3_test_bit ((block -		le32_to_cpu(sb->u.ext3_sb.s_es->s_first_data_block)) %			 EXT3_BLOCKS_PER_GROUP(sb), map);}static inline int test_root(int a, int b){	if (a == 0)		return 1;	while (1) {		if (a == 1)			return 1;		if (a % b)			return 0;		a = a / b;	}}int ext3_group_sparse(int group){	return (test_root(group, 3) || test_root(group, 5) ||		test_root(group, 7));}/** *	ext3_bg_has_super - number of blocks used by the superblock in group *	@sb: superblock for filesystem *	@group: group number to check * *	Return the number of blocks used by the superblock (primary or backup) *	in this group.  Currently this will be only 0 or 1. */int ext3_bg_has_super(struct super_block *sb, int group){	if (EXT3_HAS_RO_COMPAT_FEATURE(sb,EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)&&	    !ext3_group_sparse(group))		return 0;	return 1;}/** *	ext3_bg_num_gdb - number of blocks used by the group table in group *	@sb: superblock for filesystem *	@group: group number to check * *	Return the number of blocks used by the group descriptor table *	(primary or backup) in this group.  In the future there may be a *	different number of descriptor blocks in each group. */unsigned long ext3_bg_num_gdb(struct super_block *sb, int group){	if (EXT3_HAS_RO_COMPAT_FEATURE(sb,EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)&&	    !ext3_group_sparse(group))		return 0;	return EXT3_SB(sb)->s_gdb_count;}#ifdef CONFIG_EXT3_CHECK/* Called at mount-time, super-block is locked */void ext3_check_blocks_bitmap (struct super_block * sb){	struct buffer_head * bh;	struct ext3_super_block * es;	unsigned long desc_count, bitmap_count, x, j;	unsigned long desc_blocks;	int bitmap_nr;	struct ext3_group_desc * gdp;	int i;	es = sb->u.ext3_sb.s_es;	desc_count = 0;	bitmap_count = 0;	gdp = NULL;	for (i = 0; i < sb->u.ext3_sb.s_groups_count; i++) {		gdp = ext3_get_group_desc (sb, i, NULL);		if (!gdp)			continue;		desc_count += le16_to_cpu(gdp->bg_free_blocks_count);		bitmap_nr = load_block_bitmap (sb, i);		if (bitmap_nr < 0)			continue;		bh = EXT3_SB(sb)->s_block_bitmap[bitmap_nr];		if (ext3_bg_has_super(sb, i) && !ext3_test_bit(0, bh->b_data))			ext3_error(sb, __FUNCTION__,				   "Superblock in group %d is marked free", i);		desc_blocks = ext3_bg_num_gdb(sb, i);		for (j = 0; j < desc_blocks; j++)			if (!ext3_test_bit(j + 1, bh->b_data))				ext3_error(sb, __FUNCTION__,					   "Descriptor block #%ld in group "					   "%d is marked free", j, i);		if (!block_in_use (le32_to_cpu(gdp->bg_block_bitmap),						sb, bh->b_data))			ext3_error (sb, "ext3_check_blocks_bitmap",				    "Block bitmap for group %d is marked free",				    i);		if (!block_in_use (le32_to_cpu(gdp->bg_inode_bitmap),						sb, bh->b_data))			ext3_error (sb, "ext3_check_blocks_bitmap",				    "Inode bitmap for group %d is marked free",				    i);		for (j = 0; j < sb->u.ext3_sb.s_itb_per_group; j++)			if (!block_in_use (le32_to_cpu(gdp->bg_inode_table) + j,							sb, bh->b_data))				ext3_error (sb, "ext3_check_blocks_bitmap",					    "Block #%d of the inode table in "					    "group %d is marked free", j, i);		x = ext3_count_free (bh, sb->s_blocksize);		if (le16_to_cpu(gdp->bg_free_blocks_count) != x)			ext3_error (sb, "ext3_check_blocks_bitmap",				    "Wrong free blocks count for group %d, "				    "stored = %d, counted = %lu", i,				    le16_to_cpu(gdp->bg_free_blocks_count), x);		bitmap_count += x;	}	if (le32_to_cpu(es->s_free_blocks_count) != bitmap_count)		ext3_error (sb, "ext3_check_blocks_bitmap",			"Wrong free blocks count in super block, "			"stored = %lu, counted = %lu",			(unsigned long)le32_to_cpu(es->s_free_blocks_count),			bitmap_count);}#endif

⌨️ 快捷键说明

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