aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-28 16:21:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-28 16:21:44 -0500
commitde1a2262b006220dae2561a299a6ea128c46f4fe (patch)
tree0df7b3686f09a77a000fb63a333237facad3482c
parentf042fea0da78d9dc077a9c736b33b60eb8f35195 (diff)
parented84825b785ceb932af7dd5aa08614801721320b (diff)
Merge tag 'writeback-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/wfg/linux
Pull writeback fixes from Wu Fengguang: "Two writeback fixes - fix negative (setpoint - dirty) in 32bit archs - use down_read_trylock() in writeback_inodes_sb(_nr)_if_idle()" * tag 'writeback-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/wfg/linux: Negative (setpoint-dirty) in bdi_position_ratio() vfs: re-implement writeback_inodes_sb(_nr)_if_idle() and rename them
-rw-r--r--fs/btrfs/extent-tree.c20
-rw-r--r--fs/ext4/inode.c8
-rw-r--r--fs/fs-writeback.c44
-rw-r--r--include/linux/writeback.h6
-rw-r--r--mm/page-writeback.c2
5 files changed, 29 insertions, 51 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 1e59ed575cc9..cf54bdfee334 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3689,20 +3689,6 @@ static int can_overcommit(struct btrfs_root *root,
3689 return 0; 3689 return 0;
3690} 3690}
3691 3691
3692static int writeback_inodes_sb_nr_if_idle_safe(struct super_block *sb,
3693 unsigned long nr_pages,
3694 enum wb_reason reason)
3695{
3696 if (!writeback_in_progress(sb->s_bdi) &&
3697 down_read_trylock(&sb->s_umount)) {
3698 writeback_inodes_sb_nr(sb, nr_pages, reason);
3699 up_read(&sb->s_umount);
3700 return 1;
3701 }
3702
3703 return 0;
3704}
3705
3706/* 3692/*
3707 * shrink metadata reservation for delalloc 3693 * shrink metadata reservation for delalloc
3708 */ 3694 */
@@ -3735,9 +3721,9 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
3735 while (delalloc_bytes && loops < 3) { 3721 while (delalloc_bytes && loops < 3) {
3736 max_reclaim = min(delalloc_bytes, to_reclaim); 3722 max_reclaim = min(delalloc_bytes, to_reclaim);
3737 nr_pages = max_reclaim >> PAGE_CACHE_SHIFT; 3723 nr_pages = max_reclaim >> PAGE_CACHE_SHIFT;
3738 writeback_inodes_sb_nr_if_idle_safe(root->fs_info->sb, 3724 try_to_writeback_inodes_sb_nr(root->fs_info->sb,
3739 nr_pages, 3725 nr_pages,
3740 WB_REASON_FS_FREE_SPACE); 3726 WB_REASON_FS_FREE_SPACE);
3741 3727
3742 /* 3728 /*
3743 * We need to wait for the async pages to actually start before 3729 * We need to wait for the async pages to actually start before
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 9c4f4b1c97f8..9ea0cde3fa9e 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2512,12 +2512,8 @@ static int ext4_nonda_switch(struct super_block *sb)
2512 /* 2512 /*
2513 * Start pushing delalloc when 1/2 of free blocks are dirty. 2513 * Start pushing delalloc when 1/2 of free blocks are dirty.
2514 */ 2514 */
2515 if (dirty_blocks && (free_blocks < 2 * dirty_blocks) && 2515 if (dirty_blocks && (free_blocks < 2 * dirty_blocks))
2516 !writeback_in_progress(sb->s_bdi) && 2516 try_to_writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE);
2517 down_read_trylock(&sb->s_umount)) {
2518 writeback_inodes_sb(sb, WB_REASON_FS_FREE_SPACE);
2519 up_read(&sb->s_umount);
2520 }
2521 2517
2522 if (2 * free_blocks < 3 * dirty_blocks || 2518 if (2 * free_blocks < 3 * dirty_blocks ||
2523 free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) { 2519 free_blocks < (dirty_blocks + EXT4_FREECLUSTERS_WATERMARK)) {
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 359494ea1bde..21f46fb3a101 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -1344,47 +1344,43 @@ void writeback_inodes_sb(struct super_block *sb, enum wb_reason reason)
1344EXPORT_SYMBOL(writeback_inodes_sb); 1344EXPORT_SYMBOL(writeback_inodes_sb);
1345 1345
1346/** 1346/**
1347 * writeback_inodes_sb_if_idle - start writeback if none underway 1347 * try_to_writeback_inodes_sb_nr - try to start writeback if none underway
1348 * @sb: the superblock 1348 * @sb: the superblock
1349 * @reason: reason why some writeback work was initiated 1349 * @nr: the number of pages to write
1350 * @reason: the reason of writeback
1350 * 1351 *
1351 * Invoke writeback_inodes_sb if no writeback is currently underway. 1352 * Invoke writeback_inodes_sb_nr if no writeback is currently underway.
1352 * Returns 1 if writeback was started, 0 if not. 1353 * Returns 1 if writeback was started, 0 if not.
1353 */ 1354 */
1354int writeback_inodes_sb_if_idle(struct super_block *sb, enum wb_reason reason) 1355int try_to_writeback_inodes_sb_nr(struct super_block *sb,
1356 unsigned long nr,
1357 enum wb_reason reason)
1355{ 1358{
1356 if (!writeback_in_progress(sb->s_bdi)) { 1359 if (writeback_in_progress(sb->s_bdi))
1357 down_read(&sb->s_umount);
1358 writeback_inodes_sb(sb, reason);
1359 up_read(&sb->s_umount);
1360 return 1; 1360 return 1;
1361 } else 1361
1362 if (!down_read_trylock(&sb->s_umount))
1362 return 0; 1363 return 0;
1364
1365 writeback_inodes_sb_nr(sb, nr, reason);
1366 up_read(&sb->s_umount);
1367 return 1;
1363} 1368}
1364EXPORT_SYMBOL(writeback_inodes_sb_if_idle); 1369EXPORT_SYMBOL(try_to_writeback_inodes_sb_nr);
1365 1370
1366/** 1371/**
1367 * writeback_inodes_sb_nr_if_idle - start writeback if none underway 1372 * try_to_writeback_inodes_sb - try to start writeback if none underway
1368 * @sb: the superblock 1373 * @sb: the superblock
1369 * @nr: the number of pages to write
1370 * @reason: reason why some writeback work was initiated 1374 * @reason: reason why some writeback work was initiated
1371 * 1375 *
1372 * Invoke writeback_inodes_sb if no writeback is currently underway. 1376 * Implement by try_to_writeback_inodes_sb_nr()
1373 * Returns 1 if writeback was started, 0 if not. 1377 * Returns 1 if writeback was started, 0 if not.
1374 */ 1378 */
1375int writeback_inodes_sb_nr_if_idle(struct super_block *sb, 1379int try_to_writeback_inodes_sb(struct super_block *sb, enum wb_reason reason)
1376 unsigned long nr,
1377 enum wb_reason reason)
1378{ 1380{
1379 if (!writeback_in_progress(sb->s_bdi)) { 1381 return try_to_writeback_inodes_sb_nr(sb, get_nr_dirty_pages(), reason);
1380 down_read(&sb->s_umount);
1381 writeback_inodes_sb_nr(sb, nr, reason);
1382 up_read(&sb->s_umount);
1383 return 1;
1384 } else
1385 return 0;
1386} 1382}
1387EXPORT_SYMBOL(writeback_inodes_sb_nr_if_idle); 1383EXPORT_SYMBOL(try_to_writeback_inodes_sb);
1388 1384
1389/** 1385/**
1390 * sync_inodes_sb - sync sb inode pages 1386 * sync_inodes_sb - sync sb inode pages
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index b82a83aba311..9a9367c0c076 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -87,9 +87,9 @@ int inode_wait(void *);
87void writeback_inodes_sb(struct super_block *, enum wb_reason reason); 87void writeback_inodes_sb(struct super_block *, enum wb_reason reason);
88void writeback_inodes_sb_nr(struct super_block *, unsigned long nr, 88void writeback_inodes_sb_nr(struct super_block *, unsigned long nr,
89 enum wb_reason reason); 89 enum wb_reason reason);
90int writeback_inodes_sb_if_idle(struct super_block *, enum wb_reason reason); 90int try_to_writeback_inodes_sb(struct super_block *, enum wb_reason reason);
91int writeback_inodes_sb_nr_if_idle(struct super_block *, unsigned long nr, 91int try_to_writeback_inodes_sb_nr(struct super_block *, unsigned long nr,
92 enum wb_reason reason); 92 enum wb_reason reason);
93void sync_inodes_sb(struct super_block *); 93void sync_inodes_sb(struct super_block *);
94long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages, 94long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages,
95 enum wb_reason reason); 95 enum wb_reason reason);
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 742c40583159..efe68148f621 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -696,7 +696,7 @@ static unsigned long bdi_position_ratio(struct backing_dev_info *bdi,
696 * => fast response on large errors; small oscillation near setpoint 696 * => fast response on large errors; small oscillation near setpoint
697 */ 697 */
698 setpoint = (freerun + limit) / 2; 698 setpoint = (freerun + limit) / 2;
699 x = div_s64((setpoint - dirty) << RATELIMIT_CALC_SHIFT, 699 x = div_s64(((s64)setpoint - (s64)dirty) << RATELIMIT_CALC_SHIFT,
700 limit - setpoint + 1); 700 limit - setpoint + 1);
701 pos_ratio = x; 701 pos_ratio = x;
702 pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT; 702 pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT;