[PATCH 05/27] btrfs: avoid duplicate balance_dirty_pages_ratelimited() calls

From: Wu Fengguang
Date: Thu Mar 03 2011 - 03:21:13 EST


When doing 1KB sequential writes to the same page,
balance_dirty_pages_ratelimited() should be called once instead of 4
times. Failing to do so will make all tasks throttled much too heavy.

CC: Chris Mason <chris.mason@xxxxxxxxxx>
Signed-off-by: Wu Fengguang <fengguang.wu@xxxxxxxxx>
---
fs/btrfs/file.c | 11 +++++++----
fs/btrfs/ioctl.c | 6 ++++--
fs/btrfs/relocation.c | 6 ++++--
3 files changed, 15 insertions(+), 8 deletions(-)

--- linux-next.orig/fs/btrfs/file.c 2011-02-21 14:24:56.000000000 +0800
+++ linux-next/fs/btrfs/file.c 2011-02-21 14:37:34.000000000 +0800
@@ -770,7 +770,8 @@ out:
static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
struct page **pages, size_t num_pages,
loff_t pos, unsigned long first_index,
- unsigned long last_index, size_t write_bytes)
+ unsigned long last_index, size_t write_bytes,
+ int *nr_dirtied)
{
struct extent_state *cached_state = NULL;
int i;
@@ -837,7 +838,8 @@ again:
GFP_NOFS);
}
for (i = 0; i < num_pages; i++) {
- clear_page_dirty_for_io(pages[i]);
+ if (!clear_page_dirty_for_io(pages[i]))
+ (*nr_dirtied)++;
set_page_extent_mapped(pages[i]);
WARN_ON(!PageLocked(pages[i]));
}
@@ -989,6 +991,7 @@ static ssize_t btrfs_file_aio_write(stru
}

while (iov_iter_count(&i) > 0) {
+ int nr_dirtied = 0;
size_t offset = pos & (PAGE_CACHE_SIZE - 1);
size_t write_bytes = min(iov_iter_count(&i),
nrptrs * (size_t)PAGE_CACHE_SIZE -
@@ -1015,7 +1018,7 @@ static ssize_t btrfs_file_aio_write(stru

ret = prepare_pages(root, file, pages, num_pages,
pos, first_index, last_index,
- write_bytes);
+ write_bytes, &nr_dirtied);
if (ret) {
btrfs_delalloc_release_space(inode,
num_pages << PAGE_CACHE_SHIFT);
@@ -1050,7 +1053,7 @@ static ssize_t btrfs_file_aio_write(stru
} else {
balance_dirty_pages_ratelimited_nr(
inode->i_mapping,
- dirty_pages);
+ nr_dirtied);
if (dirty_pages <
(root->leafsize >> PAGE_CACHE_SHIFT) + 1)
btrfs_btree_balance_dirty(root, 1);
--- linux-next.orig/fs/btrfs/ioctl.c 2011-02-21 14:24:56.000000000 +0800
+++ linux-next/fs/btrfs/ioctl.c 2011-02-21 14:26:21.000000000 +0800
@@ -654,6 +654,7 @@ static int btrfs_defrag_file(struct file
u64 skip = 0;
u64 defrag_end = 0;
unsigned long i;
+ int dirtied;
int ret;
int compress_type = BTRFS_COMPRESS_ZLIB;

@@ -766,7 +767,7 @@ again:

btrfs_set_extent_delalloc(inode, page_start, page_end, NULL);
ClearPageChecked(page);
- set_page_dirty(page);
+ dirtied = set_page_dirty(page);
unlock_extent(io_tree, page_start, page_end, GFP_NOFS);

loop_unlock:
@@ -774,7 +775,8 @@ loop_unlock:
page_cache_release(page);
mutex_unlock(&inode->i_mutex);

- balance_dirty_pages_ratelimited_nr(inode->i_mapping, 1);
+ if (dirtied)
+ balance_dirty_pages_ratelimited_nr(inode->i_mapping, 1);
i++;
}

--- linux-next.orig/fs/btrfs/relocation.c 2011-02-21 14:24:56.000000000 +0800
+++ linux-next/fs/btrfs/relocation.c 2011-02-21 14:26:21.000000000 +0800
@@ -2902,6 +2902,7 @@ static int relocate_file_extent_cluster(
struct file_ra_state *ra;
int nr = 0;
int ret = 0;
+ int dirtied;

if (!cluster->nr)
return 0;
@@ -2978,7 +2979,7 @@ static int relocate_file_extent_cluster(
}

btrfs_set_extent_delalloc(inode, page_start, page_end, NULL);
- set_page_dirty(page);
+ dirtied = set_page_dirty(page);

unlock_extent(&BTRFS_I(inode)->io_tree,
page_start, page_end, GFP_NOFS);
@@ -2986,7 +2987,8 @@ static int relocate_file_extent_cluster(
page_cache_release(page);

index++;
- balance_dirty_pages_ratelimited(inode->i_mapping);
+ if (dirtied)
+ balance_dirty_pages_ratelimited(inode->i_mapping);
btrfs_throttle(BTRFS_I(inode)->root);
}
WARN_ON(nr != cluster->nr);


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/