fs: fix performance regression in clean_bdev_aliases()
Commite64855c6cf
("fs: Add helper to clean bdev aliases under a bh and use it") added a wrapper for clean_bdev_aliases() that invalidates bdev aliases underlying a single buffer head. However this has caused a performance regression for bonnie++ benchmark on ext4 filesystem when delayed allocation is turned off (ext3 mode) - average of 3 runs: Hmean SeqOut Char 164787.55 ( 0.00%) 107189.06 (-34.95%) Hmean SeqOut Block 219883.89 ( 0.00%) 168870.32 (-23.20%) The reason for this regression is that clean_bdev_aliases() is slower when called for a single block because pagevec_lookup() it uses will end up iterating through the radix tree until it finds a page (which may take a while) but we are only interested whether there's a page at a particular index. Fix the problem by using pagevec_lookup_range() instead which avoids the needless iteration. Fixes:e64855c6cf
("fs: Add helper to clean bdev aliases under a bh and use it") Link: http://lkml.kernel.org/r/20170726114704.7626-5-jack@suse.cz Signed-off-by: Jan Kara <jack@suse.cz> Cc: Jens Axboe <axboe@fb.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
b947cee4b9
commit
c10f778ddf
14
fs/buffer.c
14
fs/buffer.c
@ -1627,19 +1627,18 @@ void clean_bdev_aliases(struct block_device *bdev, sector_t block, sector_t len)
|
||||
struct pagevec pvec;
|
||||
pgoff_t index = block >> (PAGE_SHIFT - bd_inode->i_blkbits);
|
||||
pgoff_t end;
|
||||
int i;
|
||||
int i, count;
|
||||
struct buffer_head *bh;
|
||||
struct buffer_head *head;
|
||||
|
||||
end = (block + len - 1) >> (PAGE_SHIFT - bd_inode->i_blkbits);
|
||||
pagevec_init(&pvec, 0);
|
||||
while (index <= end && pagevec_lookup(&pvec, bd_mapping, &index,
|
||||
min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
|
||||
for (i = 0; i < pagevec_count(&pvec); i++) {
|
||||
while (pagevec_lookup_range(&pvec, bd_mapping, &index, end,
|
||||
PAGEVEC_SIZE)) {
|
||||
count = pagevec_count(&pvec);
|
||||
for (i = 0; i < count; i++) {
|
||||
struct page *page = pvec.pages[i];
|
||||
|
||||
if (page->index > end)
|
||||
break;
|
||||
if (!page_has_buffers(page))
|
||||
continue;
|
||||
/*
|
||||
@ -1669,6 +1668,9 @@ unlock_page:
|
||||
}
|
||||
pagevec_release(&pvec);
|
||||
cond_resched();
|
||||
/* End of range already reached? */
|
||||
if (index > end || !index)
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(clean_bdev_aliases);
|
||||
|
Loading…
Reference in New Issue
Block a user