Commit 5c1ff336 authored by Eric Whitney's avatar Eric Whitney Committed by Theodore Ts'o

ext4: fix free space estimate in ext4_nonda_switch()

Values stored in s_freeclusters_counter and s_dirtyclusters_counter
are both in cluster units.  Remove the cluster to block conversion
applied to s_freeclusters_counter causing an inflated estimate of
free space because s_dirtyclusters_counter is not similarly
converted.  Rename free_blocks and dirty_blocks to better reflect
the units these variables contain to avoid future confusion.  This
fix corrects ENOSPC failures for xfstests 127 and 231 on bigalloc
file systems.
Signed-off-by: default avatarEric Whitney <enwlinux@gmail.com>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent bcb13850
...@@ -2609,7 +2609,7 @@ static int ext4_da_writepages(struct address_space *mapping, ...@@ -2609,7 +2609,7 @@ static int ext4_da_writepages(struct address_space *mapping,
static int ext4_nonda_switch(struct super_block *sb) static int ext4_nonda_switch(struct super_block *sb)
{ {
s64 free_blocks, dirty_blocks; s64 free_clusters, dirty_clusters;
struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_sb_info *sbi = EXT4_SB(sb);
/* /*
...@@ -2620,17 +2620,18 @@ static int ext4_nonda_switch(struct super_block *sb) ...@@ -2620,17 +2620,18 @@ static int ext4_nonda_switch(struct super_block *sb)
* Delalloc need an accurate free block accounting. So switch * Delalloc need an accurate free block accounting. So switch
* to non delalloc when we are near to error range. * to non delalloc when we are near to error range.
*/ */
free_blocks = EXT4_C2B(sbi, free_clusters =
percpu_counter_read_positive(&sbi->s_freeclusters_counter)); percpu_counter_read_positive(&sbi->s_freeclusters_counter);
dirty_blocks = percpu_counter_read_positive(&sbi->s_dirtyclusters_counter); dirty_clusters =
percpu_counter_read_positive(&sbi->s_dirtyclusters_counter);
/* /*
* Start pushing delalloc when 1/2 of free blocks are dirty. * Start pushing delalloc when 1/2 of free blocks are dirty.
*/ */
if (dirty_blocks && (free_blocks < 2 * dirty_blocks)) if (dirty_clusters && (free_clusters < 2 * dirty_clusters))
try_to_writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE); try_to_writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE);
if (2 * free_blocks < 3 * dirty_blocks || if (2 * free_clusters < 3 * dirty_clusters ||
free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) { free_clusters < (dirty_clusters + EXT4_FREECLUSTERS_WATERMARK)) {
/* /*
* free block count is less than 150% of dirty blocks * free block count is less than 150% of dirty blocks
* or free blocks is less than watermark * or free blocks is less than watermark
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment