diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-28 16:21:44 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-28 16:21:44 -0500 |
commit | de1a2262b006220dae2561a299a6ea128c46f4fe (patch) | |
tree | 0df7b3686f09a77a000fb63a333237facad3482c | |
parent | f042fea0da78d9dc077a9c736b33b60eb8f35195 (diff) | |
parent | ed84825b785ceb932af7dd5aa08614801721320b (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.c | 20 | ||||
-rw-r--r-- | fs/ext4/inode.c | 8 | ||||
-rw-r--r-- | fs/fs-writeback.c | 44 | ||||
-rw-r--r-- | include/linux/writeback.h | 6 | ||||
-rw-r--r-- | mm/page-writeback.c | 2 |
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 | ||
3692 | static 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) | |||
1344 | EXPORT_SYMBOL(writeback_inodes_sb); | 1344 | EXPORT_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 | */ |
1354 | int writeback_inodes_sb_if_idle(struct super_block *sb, enum wb_reason reason) | 1355 | int 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 | } |
1364 | EXPORT_SYMBOL(writeback_inodes_sb_if_idle); | 1369 | EXPORT_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 | */ |
1375 | int writeback_inodes_sb_nr_if_idle(struct super_block *sb, | 1379 | int 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 | } |
1387 | EXPORT_SYMBOL(writeback_inodes_sb_nr_if_idle); | 1383 | EXPORT_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 *); | |||
87 | void writeback_inodes_sb(struct super_block *, enum wb_reason reason); | 87 | void writeback_inodes_sb(struct super_block *, enum wb_reason reason); |
88 | void writeback_inodes_sb_nr(struct super_block *, unsigned long nr, | 88 | void writeback_inodes_sb_nr(struct super_block *, unsigned long nr, |
89 | enum wb_reason reason); | 89 | enum wb_reason reason); |
90 | int writeback_inodes_sb_if_idle(struct super_block *, enum wb_reason reason); | 90 | int try_to_writeback_inodes_sb(struct super_block *, enum wb_reason reason); |
91 | int writeback_inodes_sb_nr_if_idle(struct super_block *, unsigned long nr, | 91 | int try_to_writeback_inodes_sb_nr(struct super_block *, unsigned long nr, |
92 | enum wb_reason reason); | 92 | enum wb_reason reason); |
93 | void sync_inodes_sb(struct super_block *); | 93 | void sync_inodes_sb(struct super_block *); |
94 | long writeback_inodes_wb(struct bdi_writeback *wb, long nr_pages, | 94 | long 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; |