aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2013-08-17 09:36:54 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-08-17 09:36:54 -0400
commit7d7345322d60edb0fa49a64a89b31360f01d09cb (patch)
treeb17292b63ba00c3208dd17d7e9793f2af9da8814 /fs/ext4
parent1c8924eb106c1ac755d5d35ce9b3ff42e89e2511 (diff)
ext4: fix warning in ext4_da_update_reserve_space()
reaim workfile.dbase test easily triggers warning in ext4_da_update_reserve_space(): EXT4-fs warning (device ram0): ext4_da_update_reserve_space:365: ino 12, allocated 1 with only 0 reserved metadata blocks (releasing 1 blocks with reserved 9 data blocks) The problem is that (one of) tests creates file and then randomly writes to it with O_SYNC. That results in writing back pages of the file in random order so we create extents for written blocks say 0, 2, 4, 6, 8 - this last allocation also allocates new block for extents. Then we writeout block 1 so we have extents 0-2, 4, 6, 8 and we release indirect extent block because extents fit in the inode again. Then we writeout block 10 and we need to allocate indirect extent block again which triggers the warning because we don't have the reservation anymore. Fix the problem by giving back freed metadata blocks resulting from extent merging into inode's reservation pool. Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/ext4.h1
-rw-r--r--fs/ext4/extents.c3
-rw-r--r--fs/ext4/mballoc.c21
3 files changed, 20 insertions, 5 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 635135e6148e..58dede76f75f 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -581,6 +581,7 @@ enum {
581#define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE 0x0008 581#define EXT4_FREE_BLOCKS_NO_QUOT_UPDATE 0x0008
582#define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER 0x0010 582#define EXT4_FREE_BLOCKS_NOFREE_FIRST_CLUSTER 0x0010
583#define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER 0x0020 583#define EXT4_FREE_BLOCKS_NOFREE_LAST_CLUSTER 0x0020
584#define EXT4_FREE_BLOCKS_RESERVE 0x0040
584 585
585/* 586/*
586 * ioctl commands 587 * ioctl commands
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 01838875fcaf..62b21ccea882 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1793,7 +1793,8 @@ static void ext4_ext_try_to_merge_up(handle_t *handle,
1793 1793
1794 brelse(path[1].p_bh); 1794 brelse(path[1].p_bh);
1795 ext4_free_blocks(handle, inode, NULL, blk, 1, 1795 ext4_free_blocks(handle, inode, NULL, blk, 1,
1796 EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); 1796 EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET |
1797 EXT4_FREE_BLOCKS_RESERVE);
1797} 1798}
1798 1799
1799/* 1800/*
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 4bbbf13bd743..aa7d058e9e48 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4585,6 +4585,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
4585 struct buffer_head *gd_bh; 4585 struct buffer_head *gd_bh;
4586 ext4_group_t block_group; 4586 ext4_group_t block_group;
4587 struct ext4_sb_info *sbi; 4587 struct ext4_sb_info *sbi;
4588 struct ext4_inode_info *ei = EXT4_I(inode);
4588 struct ext4_buddy e4b; 4589 struct ext4_buddy e4b;
4589 unsigned int count_clusters; 4590 unsigned int count_clusters;
4590 int err = 0; 4591 int err = 0;
@@ -4784,7 +4785,6 @@ do_more:
4784 ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh); 4785 ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh);
4785 ext4_group_desc_csum_set(sb, block_group, gdp); 4786 ext4_group_desc_csum_set(sb, block_group, gdp);
4786 ext4_unlock_group(sb, block_group); 4787 ext4_unlock_group(sb, block_group);
4787 percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
4788 4788
4789 if (sbi->s_log_groups_per_flex) { 4789 if (sbi->s_log_groups_per_flex) {
4790 ext4_group_t flex_group = ext4_flex_group(sbi, block_group); 4790 ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
@@ -4792,10 +4792,23 @@ do_more:
4792 &sbi->s_flex_groups[flex_group].free_clusters); 4792 &sbi->s_flex_groups[flex_group].free_clusters);
4793 } 4793 }
4794 4794
4795 ext4_mb_unload_buddy(&e4b); 4795 if (flags & EXT4_FREE_BLOCKS_RESERVE && ei->i_reserved_data_blocks) {
4796 4796 percpu_counter_add(&sbi->s_dirtyclusters_counter,
4797 if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE)) 4797 count_clusters);
4798 spin_lock(&ei->i_block_reservation_lock);
4799 if (flags & EXT4_FREE_BLOCKS_METADATA)
4800 ei->i_reserved_meta_blocks += count_clusters;
4801 else
4802 ei->i_reserved_data_blocks += count_clusters;
4803 spin_unlock(&ei->i_block_reservation_lock);
4804 if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
4805 dquot_reclaim_block(inode,
4806 EXT4_C2B(sbi, count_clusters));
4807 } else if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
4798 dquot_free_block(inode, EXT4_C2B(sbi, count_clusters)); 4808 dquot_free_block(inode, EXT4_C2B(sbi, count_clusters));
4809 percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
4810
4811 ext4_mb_unload_buddy(&e4b);
4799 4812
4800 /* We dirtied the bitmap block */ 4813 /* We dirtied the bitmap block */
4801 BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); 4814 BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");