ext4: a couple writeback path fixes
cover ext4: a couple writeback path fixes
I've found a couple small problems in the ext4_da_writepages path;
1) ext4_num_dirty_pages() can continue looping after max_pages is reached
- this leads to wasted cpu cycles during writeback
2) bumping nr_to_write can wrap if we started with LONG_MAX
- Not sure of all ramifications, but nr_to_write = -8 can't be good
-Eric
PATCH 1/2] ext4: stop looping in ext4_num_dirty_pages when max_pages reached
Today we simply break out of the inner loop when we have accumulated max_pages; this keeps scanning forwad and doing pagevec_lookup_tag() in the while (!done) loop, this does potentially a lot of work with no net effect.
When we have accumulated max_pages, just clean up and return.
---
fs/ext4/inode.c +4 -2
@@ -1207,8 +1207,10 @@ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,break ; idx++; num++; -if (num >= max_pages) -break ; +if (num >= max_pages) { +pagevec_release (&pvec); +return num; + } }pagevec_release (&pvec); }
PATCH 2/2 ext4: don't bump nr_to_write if LONG_MAX
In reply to Eric SandeenIn some cases we can reach ext4_da_writepages with wbc->nr_to_write == LONG_MAX, !range_cyclic, and range_whole=1; in this case we will try to bump it up by a factor of 8, which leads to a nr_to_write value of -8.
I think we still get through the logic without changing wbc->nr_to_write because the other tests which would change it don't trip, but it seems dangerous to overflow desired_nr_to_write in the interim, it's not obvious.
---
fs/ext4/inode.c +5 -3
@@ -3004,9 +3004,11 @@ static int ext4_da_writepages(struct address_space *mapping,* sbi->max_writeback_mb_bump whichever is smaller. */ max_pages = sbi->s_max_writeback_mb_bump << (20 -PAGE_CACHE_SHIFT ); -if (!range_cyclic && range_whole) - desired_nr_to_write = wbc->nr_to_write *8 ; -else +if (!range_cyclic && range_whole) { + desired_nr_to_write = wbc->nr_to_write; +if (desired_nr_to_write !=LONG_MAX ) + desired_nr_to_write *=8 ; + }else desired_nr_to_write =ext4_num_dirty_pages (inode, index, max_pages);if (desired_nr_to_write > max_pages)
PATCH v2 2/2 ext4: don't bump nr_to_write if LONG_MAX
In some cases we can reach ext4_da_writepages() with wbc->nr_to_write == LONG_MAX, !range_cyclic, and range_whole=1; in this case we will try to bump it up by a factor of 8, which leads to a desired_nr_to_write value of -8.
We still get through the logic without actually changing wbc->nr_to_write because the other tests which would change it don't trip due to the negative value, but it seems dangerous to overflow desired_nr_to_write in the interim, it's not an obvious situation.
---
(V2 minor commit message edits)
fs/ext4/inode.c +5 -3
@@ -3004,9 +3004,11 @@ static int ext4_da_writepages(struct address_space *mapping,* sbi->max_writeback_mb_bump whichever is smaller. */ max_pages = sbi->s_max_writeback_mb_bump << (20 -PAGE_CACHE_SHIFT ); -if (!range_cyclic && range_whole) - desired_nr_to_write = wbc->nr_to_write *8 ; -else +if (!range_cyclic && range_whole) { + desired_nr_to_write = wbc->nr_to_write; +if (desired_nr_to_write !=LONG_MAX ) + desired_nr_to_write *=8 ; + }else desired_nr_to_write =ext4_num_dirty_pages (inode, index, max_pages);if (desired_nr_to_write > max_pages)
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2 V2] ext4: don't bump nr_to_write if LONG_MAX
Quoted 4 lines · Eric Sandeen
In some cases we can reach
ext4_da_writepages()withwbc->nr_to_write==LONG_MAX, !range_cyclic, and range_whole=1; in this case we will try to bump it up by a factor of 8, which leads to adesired_nr_to_writevalue of -8.
Sorry Ted, hold off on this, it should have been LLONG_MAX of course, and I'm still looking for one other bit of brokennes I see.
The 1/2 patch should be good though.
-Eric
Quoted 41 lines
We still get through the logic without actually changing
wbc->nr_to_writebecause the other tests which would change it don't trip due to the negative value, but it seems dangerous to overflowdesired_nr_to_writein the interim, it's not an obvious situation.Signed-off-by Eric Sandeen <[email protected]>---
(V2 minor commit message edits)
fs/ext4/inode.c +5
-4@@ -3004,9 +3004,11 @@ static int ext4_da_writepages(struct address_space *mapping,* sbi->max_writeback_mb_bump whichever is smaller. */ max_pages = sbi->s_max_writeback_mb_bump << (20 -PAGE_CACHE_SHIFT ); -if (!range_cyclic && range_whole) - desired_nr_to_write = wbc->nr_to_write *8 ; -else +if (!range_cyclic && range_whole) { + desired_nr_to_write = wbc->nr_to_write; +if (desired_nr_to_write !=LONG_MAX ) + desired_nr_to_write *=8 ; + }else desired_nr_to_write =ext4_num_dirty_pages (inode, index, max_pages);if (desired_nr_to_write > max_pages) --To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 9 lines · Eric Sandeen
I've found a couple small problems in the
ext4_da_writepagespath;1)
ext4_num_dirty_pages()can continue looping aftermax_pagesis reached
- this leads to wasted cpu cycles during writeback2) bumping
nr_to_writecan wrap if we started withLONG_MAX
- Not sure of all ramifications, butnr_to_write= -8 can't be good-Eric
sigh just nak this whole thing for now, too many errors.
Will resubmit after more careful reading, patching, and testing.
Sorry for the noise.
-Eric