📄 balloc.c
字号:
goto out; } while (prealloc_goal && DQUOT_PREALLOC_BLOCK(inode, prealloc_goal)) prealloc_goal--; dq_alloc = prealloc_goal + 1; es_alloc = reserve_blocks(sb, dq_alloc); if (!es_alloc) { *err = -ENOSPC; goto out_dquot; } ext2_debug ("goal=%lu.\n", goal); 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); group_no = (goal - le32_to_cpu(es->s_first_data_block)) / group_size; desc = ext2_get_group_desc (sb, group_no, &gdp_bh); if (!desc) { /* * gdp_bh may still be uninitialised. But group_release_blocks * will not touch it because group_alloc is zero. */ goto io_error; } group_alloc = group_reserve_blocks(sbi, group_no, desc, gdp_bh, es_alloc); if (group_alloc) { ret_block = ((goal - le32_to_cpu(es->s_first_data_block)) % group_size); brelse(bitmap_bh); bitmap_bh = read_block_bitmap(sb, group_no); if (!bitmap_bh) goto io_error; ext2_debug("goal is at %d:%d.\n", group_no, ret_block); ret_block = grab_block(sb_bgl_lock(sbi, group_no), bitmap_bh->b_data, group_size, ret_block); if (ret_block >= 0) goto got_block; group_release_blocks(sb, group_no, desc, gdp_bh, group_alloc); group_alloc = 0; } ext2_debug ("Bit not found in block group %d.\n", group_no); /* * Now search the rest of the groups. We assume that * i and desc correctly point to the last group visited. */ nr_scanned_groups = 0;retry: for (group_idx = 0; !group_alloc && group_idx < sbi->s_groups_count; group_idx++) { group_no++; if (group_no >= sbi->s_groups_count) group_no = 0; desc = ext2_get_group_desc(sb, group_no, &gdp_bh); if (!desc) goto io_error; group_alloc = group_reserve_blocks(sbi, group_no, desc, gdp_bh, es_alloc); } if (!group_alloc) { *err = -ENOSPC; goto out_release; } brelse(bitmap_bh); bitmap_bh = read_block_bitmap(sb, group_no); if (!bitmap_bh) goto io_error; ret_block = grab_block(sb_bgl_lock(sbi, group_no), bitmap_bh->b_data, group_size, 0); if (ret_block < 0) { /* * If a free block counter is corrupted we can loop inifintely. * Detect that here. */ nr_scanned_groups++; if (nr_scanned_groups > 2 * sbi->s_groups_count) { ext2_error(sb, "ext2_new_block", "corrupted free blocks counters"); goto io_error; } /* * Someone else grabbed the last free block in this blockgroup * before us. Retry the scan. */ group_release_blocks(sb, group_no, desc, gdp_bh, group_alloc); group_alloc = 0; goto retry; }got_block: ext2_debug("using block group %d(%d)\n", group_no, desc->bg_free_blocks_count); target_block = ret_block + group_no * group_size + le32_to_cpu(es->s_first_data_block); if (target_block == le32_to_cpu(desc->bg_block_bitmap) || target_block == le32_to_cpu(desc->bg_inode_bitmap) || in_range(target_block, le32_to_cpu(desc->bg_inode_table), sbi->s_itb_per_group)) ext2_error (sb, "ext2_new_block", "Allocating block in system zone - " "block = %u", target_block); if (target_block >= le32_to_cpu(es->s_blocks_count)) { ext2_error (sb, "ext2_new_block", "block(%d) >= blocks count(%d) - " "block_group = %d, es == %p ", ret_block, le32_to_cpu(es->s_blocks_count), group_no, es); goto io_error; } block = target_block; /* OK, we _had_ allocated something */ ext2_debug("found bit %d\n", ret_block); dq_alloc--; es_alloc--; group_alloc--; /* * Do block preallocation now if required. */ write_lock(&EXT2_I(inode)->i_meta_lock); if (group_alloc && !*prealloc_count) { unsigned n; for (n = 0; n < group_alloc && ++ret_block < group_size; n++) { if (ext2_set_bit_atomic(sb_bgl_lock(sbi, group_no), ret_block, (void*) bitmap_bh->b_data)) break; } *prealloc_block = block + 1; *prealloc_count = n; es_alloc -= n; dq_alloc -= n; group_alloc -= n; } write_unlock(&EXT2_I(inode)->i_meta_lock); mark_buffer_dirty(bitmap_bh); if (sb->s_flags & MS_SYNCHRONOUS) sync_dirty_buffer(bitmap_bh); ext2_debug ("allocating block %d. ", block); *err = 0;out_release: group_release_blocks(sb, group_no, desc, gdp_bh, group_alloc); release_blocks(sb, es_alloc);out_dquot: DQUOT_FREE_BLOCK(inode, dq_alloc);out: brelse(bitmap_bh); return block;io_error: *err = -EIO; goto out_release;}unsigned long ext2_count_free_blocks (struct super_block * sb){ struct ext2_group_desc * desc; unsigned long desc_count = 0; int i;#ifdef EXT2FS_DEBUG unsigned long bitmap_count, x; struct ext2_super_block *es; lock_super (sb); es = EXT2_SB(sb)->s_es; desc_count = 0; bitmap_count = 0; desc = NULL; for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) { struct buffer_head *bitmap_bh; desc = ext2_get_group_desc (sb, i, NULL); if (!desc) continue; desc_count += le16_to_cpu(desc->bg_free_blocks_count); bitmap_bh = read_block_bitmap(sb, i); if (!bitmap_bh) continue; x = ext2_count_free(bitmap_bh, sb->s_blocksize); printk ("group %d: stored = %d, counted = %lu\n", i, le16_to_cpu(desc->bg_free_blocks_count), x); bitmap_count += x; brelse(bitmap_bh); } printk("ext2_count_free_blocks: stored = %lu, computed = %lu, %lu\n", (long)le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count); unlock_super (sb); return bitmap_count;#else for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) { desc = ext2_get_group_desc (sb, i, NULL); if (!desc) continue; desc_count += le16_to_cpu(desc->bg_free_blocks_count); } return desc_count;#endif}static inline intblock_in_use(unsigned long block, struct super_block *sb, unsigned char *map){ return ext2_test_bit ((block - le32_to_cpu(EXT2_SB(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; }}static 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 *bitmap_bh = NULL; struct ext2_super_block * es; unsigned long desc_count, bitmap_count, x, j; unsigned long desc_blocks; struct ext2_group_desc * desc; int i; es = EXT2_SB(sb)->s_es; desc_count = 0; bitmap_count = 0; desc = NULL; for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) { desc = ext2_get_group_desc (sb, i, NULL); if (!desc) continue; desc_count += le16_to_cpu(desc->bg_free_blocks_count); brelse(bitmap_bh); bitmap_bh = read_block_bitmap(sb, i); if (!bitmap_bh) continue; if (ext2_bg_has_super(sb, i) && !ext2_test_bit(0, bitmap_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, bitmap_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(desc->bg_block_bitmap), sb, bitmap_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(desc->bg_inode_bitmap), sb, bitmap_bh->b_data)) ext2_error(sb, "ext2_check_blocks_bitmap", "Inode bitmap for group %d is marked free", i); for (j = 0; j < EXT2_SB(sb)->s_itb_per_group; j++) if (!block_in_use(le32_to_cpu(desc->bg_inode_table) + j, sb, bitmap_bh->b_data)) ext2_error (sb, "ext2_check_blocks_bitmap", "Block #%ld of the inode table in " "group %d is marked free", j, i); x = ext2_count_free(bitmap_bh, sb->s_blocksize); if (le16_to_cpu(desc->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(desc->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); brelse(bitmap_bh);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -