?? balloc.c
字號:
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;
goto out;
}
if (le16_to_cpu(gdp->bg_free_blocks_count) > 0)
break;
}
if (k >= sb->u.ext2_sb.s_groups_count)
goto out;
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);
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 && !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)) {
*err = -EDQUOT;
goto out;
}
tmp = j + i * EXT2_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.ext2_sb.s_itb_per_group))
ext2_error (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
/* 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 : EXT2_DEFAULT_PREALLOC_BLOCKS;
*prealloc_block = next_block;
/* Writer: end */
for (k = 1;
k < prealloc_goal && (j + k) < EXT2_BLOCKS_PER_GROUP(sb);
k++, next_block++) {
if (DQUOT_PREALLOC_BLOCK(sb, inode, 1))
break;
/* Writer: ->i_prealloc* */
if (*prealloc_block + *prealloc_count != next_block ||
ext2_set_bit (j + k, bh->b_data)) {
/* Writer: end */
DQUOT_FREE_BLOCK(sb, 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));
ext2_debug ("Preallocated a further %lu bits.\n",
(k - 1));
}
#endif
j = tmp;
mark_buffer_dirty(bh);
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(%d) >= blocks count(%d) - "
"block_group = %d, es == %p ",j,
le32_to_cpu(es->s_blocks_count), i, es);
goto out;
}
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);
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);
sb->s_dirt = 1;
unlock_super (sb);
*err = 0;
return j;
io_error:
*err = -EIO;
out:
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 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 ext2_group_sparse(int group)
{
return (test_root(group, 3) || test_root(group, 5) ||
test_root(group, 7));
}
/**
* ext2_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 ext2_bg_has_super(struct super_block *sb, int group)
{
if (EXT2_HAS_RO_COMPAT_FEATURE(sb,EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)&&
!ext2_group_sparse(group))
return 0;
return 1;
}
/**
* ext2_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 ext2_bg_num_gdb(struct super_block *sb, int group)
{
if (EXT2_HAS_RO_COMPAT_FEATURE(sb,EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)&&
!ext2_group_sparse(group))
return 0;
return EXT2_SB(sb)->s_gdb_count;
}
#ifdef CONFIG_EXT2_CHECK
/* Called at mount-time, super-block is locked */
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, j;
unsigned long desc_blocks;
int bitmap_nr;
struct ext2_group_desc * gdp;
int i;
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;
bh = EXT2_SB(sb)->s_block_bitmap[bitmap_nr];
if (ext2_bg_has_super(sb, i) && !ext2_test_bit(0, bh->b_data))
ext2_error(sb, __FUNCTION__,
"Superblock in group %d is marked free", i);
desc_blocks = ext2_bg_num_gdb(sb, i);
for (j = 0; j < desc_blocks; j++)
if (!ext2_test_bit(j + 1, bh->b_data))
ext2_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))
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);
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -