diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/backing-dev.c | 15 | ||||
-rw-r--r-- | mm/page-writeback.c | 44 | ||||
-rw-r--r-- | mm/swapfile.c | 9 |
3 files changed, 40 insertions, 28 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 707d0dc6da0f..660a87a22511 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -48,7 +48,6 @@ static struct timer_list sync_supers_timer; | |||
48 | 48 | ||
49 | static int bdi_sync_supers(void *); | 49 | static int bdi_sync_supers(void *); |
50 | static void sync_supers_timer_fn(unsigned long); | 50 | static void sync_supers_timer_fn(unsigned long); |
51 | static void arm_supers_timer(void); | ||
52 | 51 | ||
53 | static void bdi_add_default_flusher_task(struct backing_dev_info *bdi); | 52 | static void bdi_add_default_flusher_task(struct backing_dev_info *bdi); |
54 | 53 | ||
@@ -252,7 +251,7 @@ static int __init default_bdi_init(void) | |||
252 | 251 | ||
253 | init_timer(&sync_supers_timer); | 252 | init_timer(&sync_supers_timer); |
254 | setup_timer(&sync_supers_timer, sync_supers_timer_fn, 0); | 253 | setup_timer(&sync_supers_timer, sync_supers_timer_fn, 0); |
255 | arm_supers_timer(); | 254 | bdi_arm_supers_timer(); |
256 | 255 | ||
257 | err = bdi_init(&default_backing_dev_info); | 256 | err = bdi_init(&default_backing_dev_info); |
258 | if (!err) | 257 | if (!err) |
@@ -374,10 +373,13 @@ static int bdi_sync_supers(void *unused) | |||
374 | return 0; | 373 | return 0; |
375 | } | 374 | } |
376 | 375 | ||
377 | static void arm_supers_timer(void) | 376 | void bdi_arm_supers_timer(void) |
378 | { | 377 | { |
379 | unsigned long next; | 378 | unsigned long next; |
380 | 379 | ||
380 | if (!dirty_writeback_interval) | ||
381 | return; | ||
382 | |||
381 | next = msecs_to_jiffies(dirty_writeback_interval * 10) + jiffies; | 383 | next = msecs_to_jiffies(dirty_writeback_interval * 10) + jiffies; |
382 | mod_timer(&sync_supers_timer, round_jiffies_up(next)); | 384 | mod_timer(&sync_supers_timer, round_jiffies_up(next)); |
383 | } | 385 | } |
@@ -385,7 +387,7 @@ static void arm_supers_timer(void) | |||
385 | static void sync_supers_timer_fn(unsigned long unused) | 387 | static void sync_supers_timer_fn(unsigned long unused) |
386 | { | 388 | { |
387 | wake_up_process(sync_supers_tsk); | 389 | wake_up_process(sync_supers_tsk); |
388 | arm_supers_timer(); | 390 | bdi_arm_supers_timer(); |
389 | } | 391 | } |
390 | 392 | ||
391 | static int bdi_forker_task(void *ptr) | 393 | static int bdi_forker_task(void *ptr) |
@@ -428,7 +430,10 @@ static int bdi_forker_task(void *ptr) | |||
428 | 430 | ||
429 | spin_unlock_bh(&bdi_lock); | 431 | spin_unlock_bh(&bdi_lock); |
430 | wait = msecs_to_jiffies(dirty_writeback_interval * 10); | 432 | wait = msecs_to_jiffies(dirty_writeback_interval * 10); |
431 | schedule_timeout(wait); | 433 | if (wait) |
434 | schedule_timeout(wait); | ||
435 | else | ||
436 | schedule(); | ||
432 | try_to_freeze(); | 437 | try_to_freeze(); |
433 | continue; | 438 | continue; |
434 | } | 439 | } |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 0b19943ecf8b..b289310e2c89 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -597,7 +597,7 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
597 | (!laptop_mode && ((global_page_state(NR_FILE_DIRTY) | 597 | (!laptop_mode && ((global_page_state(NR_FILE_DIRTY) |
598 | + global_page_state(NR_UNSTABLE_NFS)) | 598 | + global_page_state(NR_UNSTABLE_NFS)) |
599 | > background_thresh))) | 599 | > background_thresh))) |
600 | bdi_start_writeback(bdi, NULL, 0); | 600 | bdi_start_writeback(bdi, NULL, 0, 0); |
601 | } | 601 | } |
602 | 602 | ||
603 | void set_page_dirty_balance(struct page *page, int page_mkwrite) | 603 | void set_page_dirty_balance(struct page *page, int page_mkwrite) |
@@ -683,10 +683,6 @@ void throttle_vm_writeout(gfp_t gfp_mask) | |||
683 | } | 683 | } |
684 | } | 684 | } |
685 | 685 | ||
686 | static void laptop_timer_fn(unsigned long unused); | ||
687 | |||
688 | static DEFINE_TIMER(laptop_mode_wb_timer, laptop_timer_fn, 0, 0); | ||
689 | |||
690 | /* | 686 | /* |
691 | * sysctl handler for /proc/sys/vm/dirty_writeback_centisecs | 687 | * sysctl handler for /proc/sys/vm/dirty_writeback_centisecs |
692 | */ | 688 | */ |
@@ -694,24 +690,24 @@ int dirty_writeback_centisecs_handler(ctl_table *table, int write, | |||
694 | void __user *buffer, size_t *length, loff_t *ppos) | 690 | void __user *buffer, size_t *length, loff_t *ppos) |
695 | { | 691 | { |
696 | proc_dointvec(table, write, buffer, length, ppos); | 692 | proc_dointvec(table, write, buffer, length, ppos); |
693 | bdi_arm_supers_timer(); | ||
697 | return 0; | 694 | return 0; |
698 | } | 695 | } |
699 | 696 | ||
700 | static void do_laptop_sync(struct work_struct *work) | 697 | #ifdef CONFIG_BLOCK |
698 | void laptop_mode_timer_fn(unsigned long data) | ||
701 | { | 699 | { |
702 | wakeup_flusher_threads(0); | 700 | struct request_queue *q = (struct request_queue *)data; |
703 | kfree(work); | 701 | int nr_pages = global_page_state(NR_FILE_DIRTY) + |
704 | } | 702 | global_page_state(NR_UNSTABLE_NFS); |
705 | 703 | ||
706 | static void laptop_timer_fn(unsigned long unused) | 704 | /* |
707 | { | 705 | * We want to write everything out, not just down to the dirty |
708 | struct work_struct *work; | 706 | * threshold |
707 | */ | ||
709 | 708 | ||
710 | work = kmalloc(sizeof(*work), GFP_ATOMIC); | 709 | if (bdi_has_dirty_io(&q->backing_dev_info)) |
711 | if (work) { | 710 | bdi_start_writeback(&q->backing_dev_info, NULL, nr_pages, 0); |
712 | INIT_WORK(work, do_laptop_sync); | ||
713 | schedule_work(work); | ||
714 | } | ||
715 | } | 711 | } |
716 | 712 | ||
717 | /* | 713 | /* |
@@ -719,9 +715,9 @@ static void laptop_timer_fn(unsigned long unused) | |||
719 | * of all dirty data a few seconds from now. If the flush is already scheduled | 715 | * of all dirty data a few seconds from now. If the flush is already scheduled |
720 | * then push it back - the user is still using the disk. | 716 | * then push it back - the user is still using the disk. |
721 | */ | 717 | */ |
722 | void laptop_io_completion(void) | 718 | void laptop_io_completion(struct backing_dev_info *info) |
723 | { | 719 | { |
724 | mod_timer(&laptop_mode_wb_timer, jiffies + laptop_mode); | 720 | mod_timer(&info->laptop_mode_wb_timer, jiffies + laptop_mode); |
725 | } | 721 | } |
726 | 722 | ||
727 | /* | 723 | /* |
@@ -731,8 +727,16 @@ void laptop_io_completion(void) | |||
731 | */ | 727 | */ |
732 | void laptop_sync_completion(void) | 728 | void laptop_sync_completion(void) |
733 | { | 729 | { |
734 | del_timer(&laptop_mode_wb_timer); | 730 | struct backing_dev_info *bdi; |
731 | |||
732 | rcu_read_lock(); | ||
733 | |||
734 | list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) | ||
735 | del_timer(&bdi->laptop_mode_wb_timer); | ||
736 | |||
737 | rcu_read_unlock(); | ||
735 | } | 738 | } |
739 | #endif | ||
736 | 740 | ||
737 | /* | 741 | /* |
738 | * If ratelimit_pages is too high then we can get into dirty-data overload | 742 | * If ratelimit_pages is too high then we can get into dirty-data overload |
diff --git a/mm/swapfile.c b/mm/swapfile.c index 6cd0a8f90dc7..eb086e0f4dcc 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -139,7 +139,8 @@ static int discard_swap(struct swap_info_struct *si) | |||
139 | nr_blocks = ((sector_t)se->nr_pages - 1) << (PAGE_SHIFT - 9); | 139 | nr_blocks = ((sector_t)se->nr_pages - 1) << (PAGE_SHIFT - 9); |
140 | if (nr_blocks) { | 140 | if (nr_blocks) { |
141 | err = blkdev_issue_discard(si->bdev, start_block, | 141 | err = blkdev_issue_discard(si->bdev, start_block, |
142 | nr_blocks, GFP_KERNEL, DISCARD_FL_BARRIER); | 142 | nr_blocks, GFP_KERNEL, |
143 | BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER); | ||
143 | if (err) | 144 | if (err) |
144 | return err; | 145 | return err; |
145 | cond_resched(); | 146 | cond_resched(); |
@@ -150,7 +151,8 @@ static int discard_swap(struct swap_info_struct *si) | |||
150 | nr_blocks = (sector_t)se->nr_pages << (PAGE_SHIFT - 9); | 151 | nr_blocks = (sector_t)se->nr_pages << (PAGE_SHIFT - 9); |
151 | 152 | ||
152 | err = blkdev_issue_discard(si->bdev, start_block, | 153 | err = blkdev_issue_discard(si->bdev, start_block, |
153 | nr_blocks, GFP_KERNEL, DISCARD_FL_BARRIER); | 154 | nr_blocks, GFP_KERNEL, |
155 | BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER); | ||
154 | if (err) | 156 | if (err) |
155 | break; | 157 | break; |
156 | 158 | ||
@@ -189,7 +191,8 @@ static void discard_swap_cluster(struct swap_info_struct *si, | |||
189 | start_block <<= PAGE_SHIFT - 9; | 191 | start_block <<= PAGE_SHIFT - 9; |
190 | nr_blocks <<= PAGE_SHIFT - 9; | 192 | nr_blocks <<= PAGE_SHIFT - 9; |
191 | if (blkdev_issue_discard(si->bdev, start_block, | 193 | if (blkdev_issue_discard(si->bdev, start_block, |
192 | nr_blocks, GFP_NOIO, DISCARD_FL_BARRIER)) | 194 | nr_blocks, GFP_NOIO, BLKDEV_IFL_WAIT | |
195 | BLKDEV_IFL_BARRIER)) | ||
193 | break; | 196 | break; |
194 | } | 197 | } |
195 | 198 | ||