aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorMingming Cao <cmm@us.ibm.com>2008-07-11 19:27:31 -0400
committerTheodore Ts'o <tytso@mit.edu>2008-07-11 19:27:31 -0400
commit07031431072ece801d53d2c03d5e5bb21f4f64a4 (patch)
treeb3075b21242bda4e16c35814fceeaef64a027647 /fs/ext4
parentd755fb384250d6bd7fd18a0930e71965acc8e72e (diff)
ext4: mballoc avoid use root reserved blocks for non root allocation
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>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/balloc.c51
-rw-r--r--fs/ext4/ext4.h2
-rw-r--r--fs/ext4/mballoc.c7
3 files changed, 41 insertions, 19 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 48787e86d438..25f63d8c1b3d 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -1599,23 +1599,35 @@ out:
1599 1599
1600/** 1600/**
1601 * ext4_has_free_blocks() 1601 * ext4_has_free_blocks()
1602 * @sbi: in-core super block structure. 1602 * @sbi: in-core super block structure.
1603 * @nblocks: number of neeed blocks
1603 * 1604 *
1604 * Check if filesystem has at least 1 free block available for allocation. 1605 * Check if filesystem has free blocks available for allocation.
1606 * Return the number of blocks avaible for allocation for this request
1607 * On success, return nblocks
1605 */ 1608 */
1606static int ext4_has_free_blocks(struct ext4_sb_info *sbi) 1609ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi,
1610 ext4_fsblk_t nblocks)
1607{ 1611{
1608 ext4_fsblk_t free_blocks, root_blocks; 1612 ext4_fsblk_t free_blocks;
1613 ext4_fsblk_t root_blocks = 0;
1609 1614
1610 free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter); 1615 free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
1611 root_blocks = ext4_r_blocks_count(sbi->s_es); 1616
1612 if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) && 1617 if (!capable(CAP_SYS_RESOURCE) &&
1613 sbi->s_resuid != current->fsuid && 1618 sbi->s_resuid != current->fsuid &&
1614 (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) { 1619 (sbi->s_resgid == 0 || !in_group_p(sbi->s_resgid)))
1615 return 0; 1620 root_blocks = ext4_r_blocks_count(sbi->s_es);
1616 } 1621#ifdef CONFIG_SMP
1617 return 1; 1622 if (free_blocks - root_blocks < FBC_BATCH)
1618} 1623 free_blocks =
1624 percpu_counter_sum_positive(&sbi->s_freeblocks_counter);
1625#endif
1626 if (free_blocks - root_blocks < nblocks)
1627 return free_blocks - root_blocks;
1628 return nblocks;
1629 }
1630
1619 1631
1620/** 1632/**
1621 * ext4_should_retry_alloc() 1633 * ext4_should_retry_alloc()
@@ -1631,7 +1643,7 @@ static int ext4_has_free_blocks(struct ext4_sb_info *sbi)
1631 */ 1643 */
1632int ext4_should_retry_alloc(struct super_block *sb, int *retries) 1644int ext4_should_retry_alloc(struct super_block *sb, int *retries)
1633{ 1645{
1634 if (!ext4_has_free_blocks(EXT4_SB(sb)) || (*retries)++ > 3) 1646 if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || (*retries)++ > 3)
1635 return 0; 1647 return 0;
1636 1648
1637 jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id); 1649 jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id);
@@ -1681,13 +1693,21 @@ ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
1681 ext4_group_t ngroups; 1693 ext4_group_t ngroups;
1682 unsigned long num = *count; 1694 unsigned long num = *count;
1683 1695
1684 *errp = -ENOSPC;
1685 sb = inode->i_sb; 1696 sb = inode->i_sb;
1686 if (!sb) { 1697 if (!sb) {
1698 *errp = -ENODEV;
1687 printk("ext4_new_block: nonexistent device"); 1699 printk("ext4_new_block: nonexistent device");
1688 return 0; 1700 return 0;
1689 } 1701 }
1690 1702
1703 sbi = EXT4_SB(sb);
1704 *count = ext4_has_free_blocks(sbi, *count);
1705 if (*count == 0) {
1706 *errp = -ENOSPC;
1707 return 0; /*return with ENOSPC error */
1708 }
1709 num = *count;
1710
1691 /* 1711 /*
1692 * Check quota for allocation of this block. 1712 * Check quota for allocation of this block.
1693 */ 1713 */
@@ -1711,11 +1731,6 @@ ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
1711 if (block_i && ((windowsz = block_i->rsv_window_node.rsv_goal_size) > 0)) 1731 if (block_i && ((windowsz = block_i->rsv_window_node.rsv_goal_size) > 0))
1712 my_rsv = &block_i->rsv_window_node; 1732 my_rsv = &block_i->rsv_window_node;
1713 1733
1714 if (!ext4_has_free_blocks(sbi)) {
1715 *errp = -ENOSPC;
1716 goto out;
1717 }
1718
1719 /* 1734 /*
1720 * First, test whether the goal block is free. 1735 * First, test whether the goal block is free.
1721 */ 1736 */
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index e622ade69d5c..2c4b48519c8b 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -979,6 +979,8 @@ extern ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode,
979 unsigned long *count, int *errp); 979 unsigned long *count, int *errp);
980extern ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode, 980extern ext4_fsblk_t ext4_old_new_blocks(handle_t *handle, struct inode *inode,
981 ext4_fsblk_t goal, unsigned long *count, int *errp); 981 ext4_fsblk_t goal, unsigned long *count, int *errp);
982extern ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi,
983 ext4_fsblk_t nblocks);
982extern void ext4_free_blocks (handle_t *handle, struct inode *inode, 984extern void ext4_free_blocks (handle_t *handle, struct inode *inode,
983 ext4_fsblk_t block, unsigned long count, int metadata); 985 ext4_fsblk_t block, unsigned long count, int metadata);
984extern void ext4_free_blocks_sb (handle_t *handle, struct super_block *sb, 986extern void ext4_free_blocks_sb (handle_t *handle, struct super_block *sb,
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 816ba8cce79a..1666ac184e31 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4045,6 +4045,12 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
4045 &(ar->len), errp); 4045 &(ar->len), errp);
4046 return block; 4046 return block;
4047 } 4047 }
4048 ar->len = ext4_has_free_blocks(sbi, ar->len);
4049
4050 if (ar->len == 0) {
4051 *errp = -ENOSPC;
4052 return 0;
4053 }
4048 4054
4049 while (ar->len && DQUOT_ALLOC_BLOCK(ar->inode, ar->len)) { 4055 while (ar->len && DQUOT_ALLOC_BLOCK(ar->inode, ar->len)) {
4050 ar->flags |= EXT4_MB_HINT_NOPREALLOC; 4056 ar->flags |= EXT4_MB_HINT_NOPREALLOC;
@@ -4073,7 +4079,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
4073 4079
4074 ac->ac_op = EXT4_MB_HISTORY_PREALLOC; 4080 ac->ac_op = EXT4_MB_HISTORY_PREALLOC;
4075 if (!ext4_mb_use_preallocated(ac)) { 4081 if (!ext4_mb_use_preallocated(ac)) {
4076
4077 ac->ac_op = EXT4_MB_HISTORY_ALLOC; 4082 ac->ac_op = EXT4_MB_HISTORY_ALLOC;
4078 ext4_mb_normalize_request(ac, ar); 4083 ext4_mb_normalize_request(ac, ar);
4079repeat: 4084repeat: