diff options
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r-- | fs/ext4/mballoc.c | 72 |
1 files changed, 47 insertions, 25 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index fbec2ef93797..873ad9b3418c 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -2639,8 +2639,7 @@ static int ext4_mb_init_per_dev_proc(struct super_block *sb) | |||
2639 | struct proc_dir_entry *proc; | 2639 | struct proc_dir_entry *proc; |
2640 | char devname[64]; | 2640 | char devname[64]; |
2641 | 2641 | ||
2642 | snprintf(devname, sizeof(devname) - 1, "%s", | 2642 | bdevname(sb->s_bdev, devname); |
2643 | bdevname(sb->s_bdev, devname)); | ||
2644 | sbi->s_mb_proc = proc_mkdir(devname, proc_root_ext4); | 2643 | sbi->s_mb_proc = proc_mkdir(devname, proc_root_ext4); |
2645 | 2644 | ||
2646 | MB_PROC_HANDLER(EXT4_MB_STATS_NAME, stats); | 2645 | MB_PROC_HANDLER(EXT4_MB_STATS_NAME, stats); |
@@ -2674,8 +2673,7 @@ static int ext4_mb_destroy_per_dev_proc(struct super_block *sb) | |||
2674 | if (sbi->s_mb_proc == NULL) | 2673 | if (sbi->s_mb_proc == NULL) |
2675 | return -EINVAL; | 2674 | return -EINVAL; |
2676 | 2675 | ||
2677 | snprintf(devname, sizeof(devname) - 1, "%s", | 2676 | bdevname(sb->s_bdev, devname); |
2678 | bdevname(sb->s_bdev, devname)); | ||
2679 | remove_proc_entry(EXT4_MB_GROUP_PREALLOC, sbi->s_mb_proc); | 2677 | remove_proc_entry(EXT4_MB_GROUP_PREALLOC, sbi->s_mb_proc); |
2680 | remove_proc_entry(EXT4_MB_STREAM_REQ, sbi->s_mb_proc); | 2678 | remove_proc_entry(EXT4_MB_STREAM_REQ, sbi->s_mb_proc); |
2681 | remove_proc_entry(EXT4_MB_ORDER2_REQ, sbi->s_mb_proc); | 2679 | remove_proc_entry(EXT4_MB_ORDER2_REQ, sbi->s_mb_proc); |
@@ -2738,7 +2736,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | |||
2738 | struct ext4_sb_info *sbi; | 2736 | struct ext4_sb_info *sbi; |
2739 | struct super_block *sb; | 2737 | struct super_block *sb; |
2740 | ext4_fsblk_t block; | 2738 | ext4_fsblk_t block; |
2741 | int err; | 2739 | int err, len; |
2742 | 2740 | ||
2743 | BUG_ON(ac->ac_status != AC_STATUS_FOUND); | 2741 | BUG_ON(ac->ac_status != AC_STATUS_FOUND); |
2744 | BUG_ON(ac->ac_b_ex.fe_len <= 0); | 2742 | BUG_ON(ac->ac_b_ex.fe_len <= 0); |
@@ -2772,14 +2770,27 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | |||
2772 | + ac->ac_b_ex.fe_start | 2770 | + ac->ac_b_ex.fe_start |
2773 | + le32_to_cpu(es->s_first_data_block); | 2771 | + le32_to_cpu(es->s_first_data_block); |
2774 | 2772 | ||
2775 | if (block == ext4_block_bitmap(sb, gdp) || | 2773 | len = ac->ac_b_ex.fe_len; |
2776 | block == ext4_inode_bitmap(sb, gdp) || | 2774 | if (in_range(ext4_block_bitmap(sb, gdp), block, len) || |
2777 | in_range(block, ext4_inode_table(sb, gdp), | 2775 | in_range(ext4_inode_bitmap(sb, gdp), block, len) || |
2778 | EXT4_SB(sb)->s_itb_per_group)) { | 2776 | in_range(block, ext4_inode_table(sb, gdp), |
2779 | 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)) { | ||
2780 | ext4_error(sb, __func__, | 2780 | ext4_error(sb, __func__, |
2781 | "Allocating block in system zone - block = %llu", | 2781 | "Allocating block in system zone - block = %llu", |
2782 | 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; | ||
2783 | } | 2794 | } |
2784 | #ifdef AGGRESSIVE_CHECK | 2795 | #ifdef AGGRESSIVE_CHECK |
2785 | { | 2796 | { |
@@ -2882,12 +2893,11 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, | |||
2882 | if (size < i_size_read(ac->ac_inode)) | 2893 | if (size < i_size_read(ac->ac_inode)) |
2883 | size = i_size_read(ac->ac_inode); | 2894 | size = i_size_read(ac->ac_inode); |
2884 | 2895 | ||
2885 | /* max available blocks in a free group */ | 2896 | /* max size of free chunks */ |
2886 | max = EXT4_BLOCKS_PER_GROUP(ac->ac_sb) - 1 - 1 - | 2897 | max = 2 << bsbits; |
2887 | EXT4_SB(ac->ac_sb)->s_itb_per_group; | ||
2888 | 2898 | ||
2889 | #define NRL_CHECK_SIZE(req, size, max,bits) \ | 2899 | #define NRL_CHECK_SIZE(req, size, max, chunk_size) \ |
2890 | (req <= (size) || max <= ((size) >> bits)) | 2900 | (req <= (size) || max <= (chunk_size)) |
2891 | 2901 | ||
2892 | /* first, try to predict filesize */ | 2902 | /* first, try to predict filesize */ |
2893 | /* XXX: should this table be tunable? */ | 2903 | /* XXX: should this table be tunable? */ |
@@ -2906,16 +2916,16 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, | |||
2906 | size = 512 * 1024; | 2916 | size = 512 * 1024; |
2907 | } else if (size <= 1024 * 1024) { | 2917 | } else if (size <= 1024 * 1024) { |
2908 | size = 1024 * 1024; | 2918 | size = 1024 * 1024; |
2909 | } else if (NRL_CHECK_SIZE(size, 4 * 1024 * 1024, max, bsbits)) { | 2919 | } else if (NRL_CHECK_SIZE(size, 4 * 1024 * 1024, max, 2 * 1024)) { |
2910 | start_off = ((loff_t)ac->ac_o_ex.fe_logical >> | 2920 | start_off = ((loff_t)ac->ac_o_ex.fe_logical >> |
2911 | (20 - bsbits)) << 20; | 2921 | (21 - bsbits)) << 21; |
2912 | size = 1024 * 1024; | 2922 | size = 2 * 1024 * 1024; |
2913 | } else if (NRL_CHECK_SIZE(size, 8 * 1024 * 1024, max, bsbits)) { | 2923 | } else if (NRL_CHECK_SIZE(size, 8 * 1024 * 1024, max, 4 * 1024)) { |
2914 | start_off = ((loff_t)ac->ac_o_ex.fe_logical >> | 2924 | start_off = ((loff_t)ac->ac_o_ex.fe_logical >> |
2915 | (22 - bsbits)) << 22; | 2925 | (22 - bsbits)) << 22; |
2916 | size = 4 * 1024 * 1024; | 2926 | size = 4 * 1024 * 1024; |
2917 | } else if (NRL_CHECK_SIZE(ac->ac_o_ex.fe_len, | 2927 | } else if (NRL_CHECK_SIZE(ac->ac_o_ex.fe_len, |
2918 | (8<<20)>>bsbits, max, bsbits)) { | 2928 | (8<<20)>>bsbits, max, 8 * 1024)) { |
2919 | start_off = ((loff_t)ac->ac_o_ex.fe_logical >> | 2929 | start_off = ((loff_t)ac->ac_o_ex.fe_logical >> |
2920 | (23 - bsbits)) << 23; | 2930 | (23 - bsbits)) << 23; |
2921 | size = 8 * 1024 * 1024; | 2931 | size = 8 * 1024 * 1024; |
@@ -4035,7 +4045,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, | |||
4035 | 4045 | ||
4036 | ac->ac_op = EXT4_MB_HISTORY_ALLOC; | 4046 | ac->ac_op = EXT4_MB_HISTORY_ALLOC; |
4037 | ext4_mb_normalize_request(ac, ar); | 4047 | ext4_mb_normalize_request(ac, ar); |
4038 | |||
4039 | repeat: | 4048 | repeat: |
4040 | /* allocate space in core */ | 4049 | /* allocate space in core */ |
4041 | ext4_mb_regular_allocator(ac); | 4050 | ext4_mb_regular_allocator(ac); |
@@ -4049,10 +4058,21 @@ repeat: | |||
4049 | } | 4058 | } |
4050 | 4059 | ||
4051 | if (likely(ac->ac_status == AC_STATUS_FOUND)) { | 4060 | if (likely(ac->ac_status == AC_STATUS_FOUND)) { |
4052 | ext4_mb_mark_diskspace_used(ac, handle); | 4061 | *errp = ext4_mb_mark_diskspace_used(ac, handle); |
4053 | *errp = 0; | 4062 | if (*errp == -EAGAIN) { |
4054 | block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); | 4063 | ac->ac_b_ex.fe_group = 0; |
4055 | 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 | } | ||
4056 | } else { | 4076 | } else { |
4057 | 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); |
4058 | if (freed) | 4078 | if (freed) |
@@ -4239,6 +4259,8 @@ do_more: | |||
4239 | ext4_error(sb, __func__, | 4259 | ext4_error(sb, __func__, |
4240 | "Freeing blocks in system zone - " | 4260 | "Freeing blocks in system zone - " |
4241 | "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; | ||
4242 | } | 4264 | } |
4243 | 4265 | ||
4244 | BUFFER_TRACE(bitmap_bh, "getting write access"); | 4266 | BUFFER_TRACE(bitmap_bh, "getting write access"); |