aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/mballoc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r--fs/ext4/mballoc.c72
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
4039repeat: 4048repeat:
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");