Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 112934
b: refs/heads/master
c: a30d542
h: refs/heads/master
v: v3
  • Loading branch information
Aneesh Kumar K.V authored and Theodore Ts'o committed Oct 9, 2008
1 parent 1af14f3 commit 6f38e83
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 31 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c4a0c46ec92c194c873232b88debce4e1a448483
refs/heads/master: a30d542a0035b886ffaafd0057ced0a2b28c3a4f
58 changes: 42 additions & 16 deletions trunk/fs/ext4/balloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,32 @@ ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
return ret;
}

int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
ext4_fsblk_t nblocks)
{
s64 free_blocks;
ext4_fsblk_t root_blocks = 0;
struct percpu_counter *fbc = &sbi->s_freeblocks_counter;

free_blocks = percpu_counter_read(fbc);

if (!capable(CAP_SYS_RESOURCE) &&
sbi->s_resuid != current->fsuid &&
(sbi->s_resgid == 0 || !in_group_p(sbi->s_resgid)))
root_blocks = ext4_r_blocks_count(sbi->s_es);

if (free_blocks - (nblocks + root_blocks) < EXT4_FREEBLOCKS_WATERMARK)
free_blocks = percpu_counter_sum(&sbi->s_freeblocks_counter);

if (free_blocks < (root_blocks + nblocks))
/* we don't have free space */
return -ENOSPC;

/* reduce fs free blocks counter */
percpu_counter_sub(fbc, nblocks);
return 0;
}

/**
* ext4_has_free_blocks()
* @sbi: in-core super block structure.
Expand All @@ -1623,18 +1649,17 @@ ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi,
sbi->s_resuid != current->fsuid &&
(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(&sbi->s_freeblocks_counter);
#endif

if (free_blocks - (nblocks + root_blocks) < EXT4_FREEBLOCKS_WATERMARK)
free_blocks = percpu_counter_sum_positive(&sbi->s_freeblocks_counter);

if (free_blocks <= root_blocks)
/* we don't have free space */
return 0;
if (free_blocks - root_blocks < nblocks)
return free_blocks - root_blocks;
return nblocks;
}
}


/**
Expand Down Expand Up @@ -1713,14 +1738,11 @@ ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
/*
* With delalloc we already reserved the blocks
*/
*count = ext4_has_free_blocks(sbi, *count);
}
if (*count == 0) {
*errp = -ENOSPC;
return 0; /*return with ENOSPC error */
if (ext4_claim_free_blocks(sbi, *count)) {
*errp = -ENOSPC;
return 0; /*return with ENOSPC error */
}
}
num = *count;

/*
* Check quota for allocation of this block.
*/
Expand Down Expand Up @@ -1915,9 +1937,13 @@ ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
le16_add_cpu(&gdp->bg_free_blocks_count, -num);
gdp->bg_checksum = ext4_group_desc_csum(sbi, group_no, gdp);
spin_unlock(sb_bgl_lock(sbi, group_no));
if (!EXT4_I(inode)->i_delalloc_reserved_flag)
percpu_counter_sub(&sbi->s_freeblocks_counter, num);

if (!EXT4_I(inode)->i_delalloc_reserved_flag && (*count != num)) {
/*
* we allocated less blocks than we
* claimed. Add the difference back.
*/
percpu_counter_add(&sbi->s_freeblocks_counter, *count - num);
}
if (sbi->s_log_groups_per_flex) {
ext4_group_t flex_group = ext4_flex_group(sbi, group_no);
spin_lock(sb_bgl_lock(sbi, flex_group));
Expand Down
13 changes: 13 additions & 0 deletions trunk/fs/ext4/ext4.h
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,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 int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
ext4_fsblk_t nblocks);
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,
Expand Down Expand Up @@ -1207,6 +1209,17 @@ do { \
__ext4_std_error((sb), __func__, (errno)); \
} while (0)

#ifdef CONFIG_SMP
/* Each CPU can accumulate FBC_BATCH blocks in their local
* counters. So we need to make sure we have free blocks more
* than FBC_BATCH * nr_cpu_ids. Also add a window of 4 times.
*/
#define EXT4_FREEBLOCKS_WATERMARK (4 * (FBC_BATCH * nr_cpu_ids))
#else
#define EXT4_FREEBLOCKS_WATERMARK 0
#endif


/*
* Inodes and files operations
*/
Expand Down
5 changes: 1 addition & 4 deletions trunk/fs/ext4/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1537,13 +1537,10 @@ static int ext4_da_reserve_space(struct inode *inode, int nrblocks)
md_needed = mdblocks - EXT4_I(inode)->i_reserved_meta_blocks;
total = md_needed + nrblocks;

if (ext4_has_free_blocks(sbi, total) < total) {
if (ext4_claim_free_blocks(sbi, total)) {
spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
return -ENOSPC;
}
/* reduce fs free blocks counter */
percpu_counter_sub(&sbi->s_freeblocks_counter, total);

EXT4_I(inode)->i_reserved_data_blocks += nrblocks;
EXT4_I(inode)->i_reserved_meta_blocks = mdblocks;

Expand Down
23 changes: 13 additions & 10 deletions trunk/fs/ext4/mballoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2975,9 +2975,15 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
* at write_begin() time for delayed allocation
* do not double accounting
*/
if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED))
percpu_counter_sub(&sbi->s_freeblocks_counter,
ac->ac_b_ex.fe_len);
if (!(ac->ac_flags & EXT4_MB_DELALLOC_RESERVED) &&
ac->ac_o_ex.fe_len != ac->ac_b_ex.fe_len) {
/*
* we allocated less blocks than we calimed
* Add the difference back
*/
percpu_counter_add(&sbi->s_freeblocks_counter,
ac->ac_o_ex.fe_len - ac->ac_b_ex.fe_len);
}

if (sbi->s_log_groups_per_flex) {
ext4_group_t flex_group = ext4_flex_group(sbi,
Expand Down Expand Up @@ -4389,14 +4395,11 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
/*
* With delalloc we already reserved the blocks
*/
ar->len = ext4_has_free_blocks(sbi, ar->len);
}

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

while (ar->len && DQUOT_ALLOC_BLOCK(ar->inode, ar->len)) {
ar->flags |= EXT4_MB_HINT_NOPREALLOC;
ar->len--;
Expand Down

0 comments on commit 6f38e83

Please sign in to comment.