balloc.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 770 行 · 第 1/2 页

C
770
字号
	      !in_group_p (sb->u.ext2_sb.s_resgid)) && 	     !capable(CAP_SYS_RESOURCE))) {		unlock_super (sb);		return 0;	}	ext2_debug ("goal=%lu.\n", goal);repeat:	/*	 * 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)) / EXT2_BLOCKS_PER_GROUP(sb);	gdp = ext2_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)) % EXT2_BLOCKS_PER_GROUP(sb));#ifdef EXT2FS_DEBUG		if (j)			goal_attempts++;#endif		bitmap_nr = load_block_bitmap (sb, i);		if (bitmap_nr < 0)			goto io_error;				bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];		ext2_debug ("goal is at %d:%d.\n", i, j);		if (!ext2_test_bit(j, bh->b_data)) {#ifdef EXT2FS_DEBUG			goal_hits++;			ext2_debug ("goal bit allocated.\n");#endif			goto got_block;		}		if (j) {			/*			 * The goal was occupied; search forward for a free 			 * block within the next XX blocks.			 *			 * end_goal is more or less random, but it has to be			 * less than EXT2_BLOCKS_PER_GROUP. Aligning up to the			 * next 64-bit boundary is simple..			 */			int end_goal = (j + 63) & ~63;			j = ext2_find_next_zero_bit(bh->b_data, end_goal, j);			if (j < end_goal)				goto got_block;		}			ext2_debug ("Bit not found near goal\n");		/*		 * There has been no free block found in the near vicinity		 * of the goal: do a search forward through the block groups,		 * searching in each group first for an entire free byte in		 * the bitmap and then for any free bit.		 * 		 * Search first in the remainder of the current group; then,		 * cyclicly search through the rest of the groups.		 */		p = ((char *) bh->b_data) + (j >> 3);		r = memscan(p, 0, (EXT2_BLOCKS_PER_GROUP(sb) - j + 7) >> 3);		k = (r - ((char *) bh->b_data)) << 3;		if (k < EXT2_BLOCKS_PER_GROUP(sb)) {			j = k;			goto search_back;		}		k = ext2_find_next_zero_bit ((unsigned long *) bh->b_data, 					EXT2_BLOCKS_PER_GROUP(sb),					j);		if (k < EXT2_BLOCKS_PER_GROUP(sb)) {			j = k;			goto got_block;		}	}	ext2_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.ext2_sb.s_groups_count; k++) {		i++;		if (i >= sb->u.ext2_sb.s_groups_count)			i = 0;		gdp = ext2_get_group_desc (sb, i, &bh2);		if (!gdp) {			*err = -EIO;			unlock_super (sb);			return 0;		}		if (le16_to_cpu(gdp->bg_free_blocks_count) > 0)			break;	}	if (k >= sb->u.ext2_sb.s_groups_count) {		unlock_super (sb);		return 0;	}	bitmap_nr = load_block_bitmap (sb, i);	if (bitmap_nr < 0)		goto io_error;		bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];	r = memscan(bh->b_data, 0, EXT2_BLOCKS_PER_GROUP(sb) >> 3);	j = (r - bh->b_data) << 3;	if (j < EXT2_BLOCKS_PER_GROUP(sb))		goto search_back;	else		j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,					 EXT2_BLOCKS_PER_GROUP(sb));	if (j >= EXT2_BLOCKS_PER_GROUP(sb)) {		ext2_error (sb, "ext2_new_block",			    "Free blocks count corrupted for block group %d", i);		unlock_super (sb);		return 0;	}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 && !ext2_test_bit (j - 1, bh->b_data); k++, j--);	got_block:	ext2_debug ("using block group %d(%d)\n", i, gdp->bg_free_blocks_count);	/*	 * Check quota for allocation of this block.	 */	if(DQUOT_ALLOC_BLOCK(sb, inode, 1)) {		unlock_super(sb);		*err = -EDQUOT;		return 0;	}	tmp = j + i * EXT2_BLOCKS_PER_GROUP(sb) + le32_to_cpu(es->s_first_data_block);	if (test_opt (sb, CHECK_STRICT) &&	    (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.ext2_sb.s_itb_per_group)))		ext2_panic (sb, "ext2_new_block",			    "Allocating block in system zone - "			    "block = %u", tmp);	if (ext2_set_bit (j, bh->b_data)) {		ext2_warning (sb, "ext2_new_block",			      "bit already set for block %d", j);		DQUOT_FREE_BLOCK(sb, inode, 1);		goto repeat;	}	ext2_debug ("found bit %d\n", j);	/*	 * Do block preallocation now if required.	 */#ifdef EXT2_PREALLOCATE	if (prealloc_block) {		int	prealloc_goal;		prealloc_goal = es->s_prealloc_blocks ?			es->s_prealloc_blocks : EXT2_DEFAULT_PREALLOC_BLOCKS;		*prealloc_count = 0;		*prealloc_block = tmp + 1;		for (k = 1;		     k < prealloc_goal && (j + k) < EXT2_BLOCKS_PER_GROUP(sb);		     k++) {			if (DQUOT_PREALLOC_BLOCK(sb, inode, 1))				break;			if (ext2_set_bit (j + k, bh->b_data)) {				DQUOT_FREE_BLOCK(sb, inode, 1); 				break;			}			(*prealloc_count)++;		}			gdp->bg_free_blocks_count =			cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) -			       *prealloc_count);		es->s_free_blocks_count =			cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) -			       *prealloc_count);		ext2_debug ("Preallocated a further %lu bits.\n",			    *prealloc_count);	}#endif	j = tmp;	mark_buffer_dirty(bh, 1);	if (sb->s_flags & MS_SYNCHRONOUS) {		ll_rw_block (WRITE, 1, &bh);		wait_on_buffer (bh);	}	if (j >= le32_to_cpu(es->s_blocks_count)) {		ext2_error (sb, "ext2_new_block",			    "block >= blocks count - "			    "block_group = %d, block=%d", i, j);		unlock_super (sb);		return 0;	}	if (!(bh = getblk (sb->s_dev, j, sb->s_blocksize))) {		ext2_error (sb, "ext2_new_block", "cannot get block %d", j);		unlock_super (sb);		return 0;	}	memset(bh->b_data, 0, sb->s_blocksize);	mark_buffer_uptodate(bh, 1);	mark_buffer_dirty(bh, 1);	brelse (bh);	ext2_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);	mark_buffer_dirty(bh2, 1);	es->s_free_blocks_count = cpu_to_le32(le32_to_cpu(es->s_free_blocks_count) - 1);	mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);	sb->s_dirt = 1;	unlock_super (sb);	*err = 0;	return j;	io_error:	*err = -EIO;	unlock_super (sb);	return 0;	}unsigned long ext2_count_free_blocks (struct super_block * sb){#ifdef EXT2FS_DEBUG	struct ext2_super_block * es;	unsigned long desc_count, bitmap_count, x;	int bitmap_nr;	struct ext2_group_desc * gdp;	int i;		lock_super (sb);	es = sb->u.ext2_sb.s_es;	desc_count = 0;	bitmap_count = 0;	gdp = NULL;	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {		gdp = ext2_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 = ext2_count_free (sb->u.ext2_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("ext2_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.ext2_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 ext2_test_bit ((block - le32_to_cpu(sb->u.ext2_sb.s_es->s_first_data_block)) %			 EXT2_BLOCKS_PER_GROUP(sb), map);}static 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 ext2_group_sparse(int group){	return (test_root(group, 3) || test_root(group, 5) ||		test_root(group, 7));}void ext2_check_blocks_bitmap (struct super_block * sb){	struct buffer_head * bh;	struct ext2_super_block * es;	unsigned long desc_count, bitmap_count, x;	unsigned long desc_blocks;	int bitmap_nr;	struct ext2_group_desc * gdp;	int i, j;	lock_super (sb);	es = sb->u.ext2_sb.s_es;	desc_count = 0;	bitmap_count = 0;	gdp = NULL;	desc_blocks = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /		      EXT2_DESC_PER_BLOCK(sb);	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {		gdp = ext2_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 = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];		if (!(sb->u.ext2_sb.s_feature_ro_compat &		     EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||		    ext2_group_sparse(i)) {			if (!ext2_test_bit (0, bh->b_data))				ext2_error (sb, "ext2_check_blocks_bitmap",					    "Superblock in group %d "					    "is marked free", i);			for (j = 0; j < desc_blocks; j++)				if (!ext2_test_bit (j + 1, bh->b_data))					ext2_error (sb,					    "ext2_check_blocks_bitmap",					    "Descriptor block #%d in group "					    "%d is marked free", j, i);		}		if (!block_in_use (le32_to_cpu(gdp->bg_block_bitmap), sb, bh->b_data))			ext2_error (sb, "ext2_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))			ext2_error (sb, "ext2_check_blocks_bitmap",				    "Inode bitmap for group %d is marked free",				    i);		for (j = 0; j < sb->u.ext2_sb.s_itb_per_group; j++)			if (!block_in_use (le32_to_cpu(gdp->bg_inode_table) + j, sb, bh->b_data))				ext2_error (sb, "ext2_check_blocks_bitmap",					    "Block #%d of the inode table in "					    "group %d is marked free", j, i);		x = ext2_count_free (bh, sb->s_blocksize);		if (le16_to_cpu(gdp->bg_free_blocks_count) != x)			ext2_error (sb, "ext2_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)		ext2_error (sb, "ext2_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);	unlock_super (sb);}

⌨️ 快捷键说明

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