[PATCH 36/47] btrfs: dont call balance_dirty_pages_ratelimited() on already dirty pages

From: Wu Fengguang
Date: Mon Dec 13 2010 - 01:54:35 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 2010-12-09 12:21:03.000000000 +0800
+++ linux-next/fs/btrfs/file.c 2010-12-09 12:24:59.000000000 +0800
@@ -762,7 +762,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;
@@ -825,7 +826,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]));
}
@@ -966,6 +968,7 @@ static ssize_t btrfs_file_aio_write(stru
offset);
size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >>
PAGE_CACHE_SHIFT;
+ int nr_dirtied = 0;

WARN_ON(num_pages > nrptrs);
memset(pages, 0, sizeof(struct page *) * nrptrs);
@@ -976,7 +979,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, write_bytes);
goto out;
@@ -1000,7 +1003,7 @@ static ssize_t btrfs_file_aio_write(stru
pos + write_bytes - 1);
} else {
balance_dirty_pages_ratelimited_nr(inode->i_mapping,
- num_pages);
+ nr_dirtied);
if (num_pages <
(root->leafsize >> PAGE_CACHE_SHIFT) + 1)
btrfs_btree_balance_dirty(root, 1);
--- linux-next.orig/fs/btrfs/ioctl.c 2010-12-09 12:21:03.000000000 +0800
+++ linux-next/fs/btrfs/ioctl.c 2010-12-09 12:24:59.000000000 +0800
@@ -647,6 +647,7 @@ static int btrfs_defrag_file(struct file
u64 skip = 0;
u64 defrag_end = 0;
unsigned long i;
+ int dirtied;
int ret;

if (inode->i_size == 0)
@@ -751,7 +752,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:
@@ -759,7 +760,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 2010-12-09 12:21:03.000000000 +0800
+++ linux-next/fs/btrfs/relocation.c 2010-12-09 12:24:59.000000000 +0800
@@ -2894,6 +2894,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;
@@ -2970,7 +2971,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);
@@ -2978,7 +2979,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/