* balloc.c contains the blocks allocation and deallocation routines
*/
+/*
+ * Calculate the block group number and offset, given a block number
+ */
+void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+ unsigned long *blockgrpp, ext4_grpblk_t *offsetp)
+{
+ struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+ ext4_grpblk_t offset;
+
+ blocknr = blocknr - le32_to_cpu(es->s_first_data_block);
+ offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb));
+ if (offsetp)
+ *offsetp = offset;
+ if (blockgrpp)
+ *blockgrpp = blocknr;
+
+}
+
/*
* The free blocks are managed by bitmaps. A file system contains several
* blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap
* The file system contains group descriptors which are located after the
* super block. Each descriptor contains the number of the bitmap block and
* the free blocks count in the block. The descriptors are loaded in memory
- * when a file system is mounted (see ext4_read_super).
+ * when a file system is mounted (see ext4_fill_super).
*/
desc = ext4_get_group_desc (sb, block_group, NULL);
if (!desc)
goto error_out;
- bh = sb_bread(sb, ext4_block_bitmap(desc));
+ bh = sb_bread(sb, ext4_block_bitmap(sb, desc));
if (!bh)
ext4_error (sb, "read_block_bitmap",
"Cannot read block bitmap - "
"block_group = %d, block_bitmap = %llu",
block_group,
- ext4_block_bitmap(desc));
+ ext4_block_bitmap(sb, desc));
error_out:
return bh;
}
printk("Block Allocation Reservation Windows Map (%s):\n", fn);
while (n) {
- rsv = list_entry(n, struct ext4_reserve_window_node, rsv_node);
+ rsv = rb_entry(n, struct ext4_reserve_window_node, rsv_node);
if (verbose)
printk("reservation window 0x%p "
"start: %llu, end: %llu\n",
if (!desc)
goto error_return;
- if (in_range(ext4_block_bitmap(desc), block, count) ||
- in_range(ext4_inode_bitmap(desc), block, count) ||
- in_range(block, ext4_inode_table(desc), sbi->s_itb_per_group) ||
- in_range(block + count - 1, ext4_inode_table(desc),
+ if (in_range(ext4_block_bitmap(sb, desc), block, count) ||
+ in_range(ext4_inode_bitmap(sb, desc), block, count) ||
+ in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) ||
+ in_range(block + count - 1, ext4_inode_table(sb, desc),
sbi->s_itb_per_group))
ext4_error (sb, "ext4_free_blocks",
"Freeing blocks in system zones - "
here = 0;
p = ((char *)bh->b_data) + (here >> 3);
- r = memscan(p, 0, (maxblocks - here + 7) >> 3);
+ r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3));
next = (r - ((char *)bh->b_data)) << 3;
if (next < maxblocks && next >= start && ext4_test_allocatable(next, bh))
prev = rsv;
next = rb_next(&rsv->rsv_node);
- rsv = list_entry(next,struct ext4_reserve_window_node,rsv_node);
+ rsv = rb_entry(next,struct ext4_reserve_window_node,rsv_node);
/*
* Reached the last reservation, we can just append to the
* check if the first free block is within the
* free space we just reserved
*/
- if (start_block >= my_rsv->rsv_start && start_block < my_rsv->rsv_end)
+ if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end)
return 0; /* success */
/*
* if the first free bit we found is out of the reservable space
if (!next)
my_rsv->rsv_end += size;
else {
- next_rsv = list_entry(next, struct ext4_reserve_window_node, rsv_node);
+ next_rsv = rb_entry(next, struct ext4_reserve_window_node, rsv_node);
if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size)
my_rsv->rsv_end += size;
}
/*
* grp_goal is a group relative block number (if there is a goal)
- * 0 < grp_goal < EXT4_BLOCKS_PER_GROUP(sb)
+ * 0 <= grp_goal < EXT4_BLOCKS_PER_GROUP(sb)
* first block is a filesystem wide block number
* first block is the block number of the first block in this group
*/
if (!goal_in_my_reservation(&my_rsv->rsv_window,
grp_goal, group, sb))
grp_goal = -1;
- } else if (grp_goal > 0 &&
- (my_rsv->rsv_end-grp_goal+1) < *count)
- try_to_extend_reservation(my_rsv, sb,
- *count-my_rsv->rsv_end + grp_goal - 1);
+ } else if (grp_goal >= 0) {
+ int curr = my_rsv->rsv_end -
+ (grp_goal + group_first_block) + 1;
+
+ if (curr < *count)
+ try_to_extend_reservation(my_rsv, sb,
+ *count - curr);
+ }
if ((my_rsv->rsv_start > group_last_block) ||
(my_rsv->rsv_end < group_first_block)) {
if (group_no >= ngroups)
group_no = 0;
gdp = ext4_get_group_desc(sb, group_no, &gdp_bh);
- if (!gdp) {
- *errp = -EIO;
- goto out;
- }
+ if (!gdp)
+ goto io_error;
free_blocks = le16_to_cpu(gdp->bg_free_blocks_count);
/*
* skip this group if the number of
*/
if (my_rsv) {
my_rsv = NULL;
+ windowsz = 0;
group_no = goal_group;
goto retry_alloc;
}
ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no);
- if (in_range(ext4_block_bitmap(gdp), ret_block, num) ||
- in_range(ext4_block_bitmap(gdp), ret_block, num) ||
- in_range(ret_block, ext4_inode_table(gdp),
+ if (in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
+ in_range(ext4_block_bitmap(sb, gdp), ret_block, num) ||
+ in_range(ret_block, ext4_inode_table(sb, gdp),
EXT4_SB(sb)->s_itb_per_group) ||
- in_range(ret_block + num - 1, ext4_inode_table(gdp),
+ in_range(ret_block + num - 1, ext4_inode_table(sb, gdp),
EXT4_SB(sb)->s_itb_per_group))
ext4_error(sb, "ext4_new_block",
"Allocating block in system zone - "