aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/mballoc.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-06-10 05:22:26 -0400
committerDavid S. Miller <davem@davemloft.net>2008-06-10 05:22:26 -0400
commit65b53e4cc90e59936733b3b95b9451d2ca47528d (patch)
tree29932718192962671c48c3fd1ea017a6112459e8 /fs/ext4/mballoc.c
parent788c0a53164c05c5ccdb1472474372b72ba74644 (diff)
parent2e761e0532a784816e7e822dbaaece8c5d4be14d (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: drivers/net/tg3.c drivers/net/wireless/rt2x00/rt2x00dev.c net/mac80211/ieee80211_i.h
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r--fs/ext4/mballoc.c66
1 files changed, 45 insertions, 21 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index b128bdc0f55c..873ad9b3418c 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2736,7 +2736,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
2736 struct ext4_sb_info *sbi; 2736 struct ext4_sb_info *sbi;
2737 struct super_block *sb; 2737 struct super_block *sb;
2738 ext4_fsblk_t block; 2738 ext4_fsblk_t block;
2739 int err; 2739 int err, len;
2740 2740
2741 BUG_ON(ac->ac_status != AC_STATUS_FOUND); 2741 BUG_ON(ac->ac_status != AC_STATUS_FOUND);
2742 BUG_ON(ac->ac_b_ex.fe_len <= 0); 2742 BUG_ON(ac->ac_b_ex.fe_len <= 0);
@@ -2770,14 +2770,27 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
2770 + ac->ac_b_ex.fe_start 2770 + ac->ac_b_ex.fe_start
2771 + le32_to_cpu(es->s_first_data_block); 2771 + le32_to_cpu(es->s_first_data_block);
2772 2772
2773 if (block == ext4_block_bitmap(sb, gdp) || 2773 len = ac->ac_b_ex.fe_len;
2774 block == ext4_inode_bitmap(sb, gdp) || 2774 if (in_range(ext4_block_bitmap(sb, gdp), block, len) ||
2775 in_range(block, ext4_inode_table(sb, gdp), 2775 in_range(ext4_inode_bitmap(sb, gdp), block, len) ||
2776 EXT4_SB(sb)->s_itb_per_group)) { 2776 in_range(block, ext4_inode_table(sb, gdp),
2777 2777 EXT4_SB(sb)->s_itb_per_group) ||
2778 in_range(block + len - 1, ext4_inode_table(sb, gdp),
2779 EXT4_SB(sb)->s_itb_per_group)) {
2778 ext4_error(sb, __func__, 2780 ext4_error(sb, __func__,
2779 "Allocating block in system zone - block = %llu", 2781 "Allocating block in system zone - block = %llu",
2780 block); 2782 block);
2783 /* File system mounted not to panic on error
2784 * Fix the bitmap and repeat the block allocation
2785 * We leak some of the blocks here.
2786 */
2787 mb_set_bits(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group),
2788 bitmap_bh->b_data, ac->ac_b_ex.fe_start,
2789 ac->ac_b_ex.fe_len);
2790 err = ext4_journal_dirty_metadata(handle, bitmap_bh);
2791 if (!err)
2792 err = -EAGAIN;
2793 goto out_err;
2781 } 2794 }
2782#ifdef AGGRESSIVE_CHECK 2795#ifdef AGGRESSIVE_CHECK
2783 { 2796 {
@@ -2880,12 +2893,11 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
2880 if (size < i_size_read(ac->ac_inode)) 2893 if (size < i_size_read(ac->ac_inode))
2881 size = i_size_read(ac->ac_inode); 2894 size = i_size_read(ac->ac_inode);
2882 2895
2883 /* max available blocks in a free group */ 2896 /* max size of free chunks */
2884 max = EXT4_BLOCKS_PER_GROUP(ac->ac_sb) - 1 - 1 - 2897 max = 2 << bsbits;
2885 EXT4_SB(ac->ac_sb)->s_itb_per_group;
2886 2898
2887#define NRL_CHECK_SIZE(req, size, max,bits) \ 2899#define NRL_CHECK_SIZE(req, size, max, chunk_size) \
2888 (req <= (size) || max <= ((size) >> bits)) 2900 (req <= (size) || max <= (chunk_size))
2889 2901
2890 /* first, try to predict filesize */ 2902 /* first, try to predict filesize */
2891 /* XXX: should this table be tunable? */ 2903 /* XXX: should this table be tunable? */
@@ -2904,16 +2916,16 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac,
2904 size = 512 * 1024; 2916 size = 512 * 1024;
2905 } else if (size <= 1024 * 1024) { 2917 } else if (size <= 1024 * 1024) {
2906 size = 1024 * 1024; 2918 size = 1024 * 1024;
2907 } else if (NRL_CHECK_SIZE(size, 4 * 1024 * 1024, max, bsbits)) { 2919 } else if (NRL_CHECK_SIZE(size, 4 * 1024 * 1024, max, 2 * 1024)) {
2908 start_off = ((loff_t)ac->ac_o_ex.fe_logical >> 2920 start_off = ((loff_t)ac->ac_o_ex.fe_logical >>
2909 (20 - bsbits)) << 20; 2921 (21 - bsbits)) << 21;
2910 size = 1024 * 1024; 2922 size = 2 * 1024 * 1024;
2911 } else if (NRL_CHECK_SIZE(size, 8 * 1024 * 1024, max, bsbits)) { 2923 } else if (NRL_CHECK_SIZE(size, 8 * 1024 * 1024, max, 4 * 1024)) {
2912 start_off = ((loff_t)ac->ac_o_ex.fe_logical >> 2924 start_off = ((loff_t)ac->ac_o_ex.fe_logical >>
2913 (22 - bsbits)) << 22; 2925 (22 - bsbits)) << 22;
2914 size = 4 * 1024 * 1024; 2926 size = 4 * 1024 * 1024;
2915 } else if (NRL_CHECK_SIZE(ac->ac_o_ex.fe_len, 2927 } else if (NRL_CHECK_SIZE(ac->ac_o_ex.fe_len,
2916 (8<<20)>>bsbits, max, bsbits)) { 2928 (8<<20)>>bsbits, max, 8 * 1024)) {
2917 start_off = ((loff_t)ac->ac_o_ex.fe_logical >> 2929 start_off = ((loff_t)ac->ac_o_ex.fe_logical >>
2918 (23 - bsbits)) << 23; 2930 (23 - bsbits)) << 23;
2919 size = 8 * 1024 * 1024; 2931 size = 8 * 1024 * 1024;
@@ -4033,7 +4045,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
4033 4045
4034 ac->ac_op = EXT4_MB_HISTORY_ALLOC; 4046 ac->ac_op = EXT4_MB_HISTORY_ALLOC;
4035 ext4_mb_normalize_request(ac, ar); 4047 ext4_mb_normalize_request(ac, ar);
4036
4037repeat: 4048repeat:
4038 /* allocate space in core */ 4049 /* allocate space in core */
4039 ext4_mb_regular_allocator(ac); 4050 ext4_mb_regular_allocator(ac);
@@ -4047,10 +4058,21 @@ repeat:
4047 } 4058 }
4048 4059
4049 if (likely(ac->ac_status == AC_STATUS_FOUND)) { 4060 if (likely(ac->ac_status == AC_STATUS_FOUND)) {
4050 ext4_mb_mark_diskspace_used(ac, handle); 4061 *errp = ext4_mb_mark_diskspace_used(ac, handle);
4051 *errp = 0; 4062 if (*errp == -EAGAIN) {
4052 block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); 4063 ac->ac_b_ex.fe_group = 0;
4053 ar->len = ac->ac_b_ex.fe_len; 4064 ac->ac_b_ex.fe_start = 0;
4065 ac->ac_b_ex.fe_len = 0;
4066 ac->ac_status = AC_STATUS_CONTINUE;
4067 goto repeat;
4068 } else if (*errp) {
4069 ac->ac_b_ex.fe_len = 0;
4070 ar->len = 0;
4071 ext4_mb_show_ac(ac);
4072 } else {
4073 block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex);
4074 ar->len = ac->ac_b_ex.fe_len;
4075 }
4054 } else { 4076 } else {
4055 freed = ext4_mb_discard_preallocations(sb, ac->ac_o_ex.fe_len); 4077 freed = ext4_mb_discard_preallocations(sb, ac->ac_o_ex.fe_len);
4056 if (freed) 4078 if (freed)
@@ -4237,6 +4259,8 @@ do_more:
4237 ext4_error(sb, __func__, 4259 ext4_error(sb, __func__,
4238 "Freeing blocks in system zone - " 4260 "Freeing blocks in system zone - "
4239 "Block = %lu, count = %lu", block, count); 4261 "Block = %lu, count = %lu", block, count);
4262 /* err = 0. ext4_std_error should be a no op */
4263 goto error_return;
4240 } 4264 }
4241 4265
4242 BUFFER_TRACE(bitmap_bh, "getting write access"); 4266 BUFFER_TRACE(bitmap_bh, "getting write access");