Skip to content

Commit

Permalink
ext4: mballoc avoid use root reserved blocks for non root allocation
Browse files Browse the repository at this point in the history
mballoc allocation missed check for blocks reserved for root users. Add
ext4_has_free_blocks() check before allocation. Also modified
ext4_has_free_blocks() to support multiple block allocation request.

Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
  • Loading branch information
Mingming Cao authored and Theodore Ts'o committed Jul 11, 2008
1 parent d755fb3 commit 0703143
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 19 deletions.
51 changes: 33 additions & 18 deletions fs/ext4/balloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1599,23 +1599,35 @@ ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,

/**
* ext4_has_free_blocks()
* @sbi: in-core super block structure.
* @sbi: in-core super block structure.
* @nblocks: number of neeed blocks
*
* Check if filesystem has at least 1 free block available for allocation.
* Check if filesystem has free blocks available for allocation.
* Return the number of blocks avaible for allocation for this request
* On success, return nblocks
*/
static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi,
ext4_fsblk_t nblocks)
{
ext4_fsblk_t free_blocks, root_blocks;
ext4_fsblk_t free_blocks;
ext4_fsblk_t root_blocks = 0;

free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
root_blocks = ext4_r_blocks_count(sbi->s_es);
if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&

if (!capable(CAP_SYS_RESOURCE) &&
sbi->s_resuid != current->fsuid &&
(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
return 0;
}
return 1;
}
(sbi->s_resgid == 0 || !in_group_p(sbi->s_resgid)))
root_blocks = ext4_r_blocks_count(sbi->s_es);
#ifdef CONFIG_SMP
if (free_blocks - root_blocks < FBC_BATCH)
free_blocks =
percpu_counter_sum_positive(&sbi->s_freeblocks_counter);
#endif
if (free_blocks - root_blocks < nblocks)
return free_blocks - root_blocks;
return nblocks;
}


/**
* ext4_should_retry_alloc()
Expand All @@ -1631,7 +1643,7 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
*/
int ext4_should_retry_alloc(struct super_block *sb, int *retries)
{
if (!ext4_has_free_blocks(EXT4_SB(sb)) || (*retries)++ > 3)
if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || (*retries)++ > 3)
return 0;

jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
Expand Down Expand Up @@ -1681,13 +1693,21 @@ ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
ext4_group_t ngroups;
unsigned long num = *count;

*errp = -ENOSPC;
sb = inode->i_sb;
if (!sb) {
*errp = -ENODEV;
printk("ext4_new_block: nonexistent device");
return 0;
}

sbi = EXT4_SB(sb);
*count = ext4_has_free_blocks(sbi, *count);
if (*count == 0) {
*errp = -ENOSPC;
return 0; /*return with ENOSPC error */
}
num = *count;

/*
* Check quota for allocation of this block.
*/
Expand All @@ -1711,11 +1731,6 @@ ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
if (block_i && ((windowsz = block_i->rsv_window_node.rsv_goal_size) > 0))
my_rsv = &block_i->rsv_window_node;

if (!ext4_has_free_blocks(sbi)) {
*errp = -ENOSPC;
goto out;
}

/*
* First, test whether the goal block is free.
*/
Expand Down
2 changes: 2 additions & 0 deletions fs/ext4/ext4.h
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,8 @@ extern ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
unsigned long *count, int *errp);
extern ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
ext4_fsblk_t goal, unsigned long *count, int *errp);
extern ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi,
ext4_fsblk_t nblocks);
extern void ext4_free_blocks (handle_t *handle, struct inode *inode,
ext4_fsblk_t block, unsigned long count, int metadata);
extern void ext4_free_blocks_sb (handle_t *handle, struct super_block *sb,
Expand Down
7 changes: 6 additions & 1 deletion fs/ext4/mballoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -4045,6 +4045,12 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
&(ar->len), errp);
return block;
}
ar->len = ext4_has_free_blocks(sbi, ar->len);

if (ar->len == 0) {
*errp = -ENOSPC;
return 0;
}

while (ar->len && DQUOT_ALLOC_BLOCK(ar->inode, ar->len)) {
ar->flags |= EXT4_MB_HINT_NOPREALLOC;
Expand Down Expand Up @@ -4073,7 +4079,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,

ac->ac_op = EXT4_MB_HISTORY_PREALLOC;
if (!ext4_mb_use_preallocated(ac)) {

ac->ac_op = EXT4_MB_HISTORY_ALLOC;
ext4_mb_normalize_request(ac, ar);
repeat:
Expand Down

0 comments on commit 0703143

Please sign in to comment.