diff options
-rw-r--r-- | block/blk-core.c | 5 | ||||
-rw-r--r-- | include/linux/backing-dev.h | 3 | ||||
-rw-r--r-- | include/linux/writeback.h | 4 | ||||
-rw-r--r-- | mm/page-writeback.c | 39 |
4 files changed, 30 insertions, 21 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 1d94f15d7f0d..4b1b29ef2cb0 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -451,6 +451,7 @@ void blk_cleanup_queue(struct request_queue *q) | |||
451 | */ | 451 | */ |
452 | blk_sync_queue(q); | 452 | blk_sync_queue(q); |
453 | 453 | ||
454 | del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer); | ||
454 | mutex_lock(&q->sysfs_lock); | 455 | mutex_lock(&q->sysfs_lock); |
455 | queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q); | 456 | queue_flag_set_unlocked(QUEUE_FLAG_DEAD, q); |
456 | mutex_unlock(&q->sysfs_lock); | 457 | mutex_unlock(&q->sysfs_lock); |
@@ -511,6 +512,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) | |||
511 | return NULL; | 512 | return NULL; |
512 | } | 513 | } |
513 | 514 | ||
515 | setup_timer(&q->backing_dev_info.laptop_mode_wb_timer, | ||
516 | laptop_mode_timer_fn, (unsigned long) q); | ||
514 | init_timer(&q->unplug_timer); | 517 | init_timer(&q->unplug_timer); |
515 | setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); | 518 | setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); |
516 | INIT_LIST_HEAD(&q->timeout_list); | 519 | INIT_LIST_HEAD(&q->timeout_list); |
@@ -2101,7 +2104,7 @@ static void blk_finish_request(struct request *req, int error) | |||
2101 | BUG_ON(blk_queued_rq(req)); | 2104 | BUG_ON(blk_queued_rq(req)); |
2102 | 2105 | ||
2103 | if (unlikely(laptop_mode) && blk_fs_request(req)) | 2106 | if (unlikely(laptop_mode) && blk_fs_request(req)) |
2104 | laptop_io_completion(); | 2107 | laptop_io_completion(&req->q->backing_dev_info); |
2105 | 2108 | ||
2106 | blk_delete_timer(req); | 2109 | blk_delete_timer(req); |
2107 | 2110 | ||
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index fcbc26af00e4..2742e1adfc30 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/fs.h> | 15 | #include <linux/fs.h> |
16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
17 | #include <linux/timer.h> | ||
17 | #include <linux/writeback.h> | 18 | #include <linux/writeback.h> |
18 | #include <asm/atomic.h> | 19 | #include <asm/atomic.h> |
19 | 20 | ||
@@ -88,6 +89,8 @@ struct backing_dev_info { | |||
88 | 89 | ||
89 | struct device *dev; | 90 | struct device *dev; |
90 | 91 | ||
92 | struct timer_list laptop_mode_wb_timer; | ||
93 | |||
91 | #ifdef CONFIG_DEBUG_FS | 94 | #ifdef CONFIG_DEBUG_FS |
92 | struct dentry *debug_dir; | 95 | struct dentry *debug_dir; |
93 | struct dentry *debug_stats; | 96 | struct dentry *debug_stats; |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 36520ded3e06..eb38a2c645f6 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
@@ -96,8 +96,10 @@ static inline void inode_sync_wait(struct inode *inode) | |||
96 | /* | 96 | /* |
97 | * mm/page-writeback.c | 97 | * mm/page-writeback.c |
98 | */ | 98 | */ |
99 | void laptop_io_completion(void); | 99 | void laptop_io_completion(struct backing_dev_info *info); |
100 | void laptop_sync_completion(void); | 100 | void laptop_sync_completion(void); |
101 | void laptop_mode_sync(struct work_struct *work); | ||
102 | void laptop_mode_timer_fn(unsigned long data); | ||
101 | void throttle_vm_writeout(gfp_t gfp_mask); | 103 | void throttle_vm_writeout(gfp_t gfp_mask); |
102 | 104 | ||
103 | /* These are exported to sysctl. */ | 105 | /* These are exported to sysctl. */ |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 0b19943ecf8b..d0f2b3765f8d 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -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 | */ |
@@ -697,21 +693,19 @@ int dirty_writeback_centisecs_handler(ctl_table *table, int write, | |||
697 | return 0; | 693 | return 0; |
698 | } | 694 | } |
699 | 695 | ||
700 | static void do_laptop_sync(struct work_struct *work) | 696 | void laptop_mode_timer_fn(unsigned long data) |
701 | { | 697 | { |
702 | wakeup_flusher_threads(0); | 698 | struct request_queue *q = (struct request_queue *)data; |
703 | kfree(work); | 699 | int nr_pages = global_page_state(NR_FILE_DIRTY) + |
704 | } | 700 | global_page_state(NR_UNSTABLE_NFS); |
705 | 701 | ||
706 | static void laptop_timer_fn(unsigned long unused) | 702 | /* |
707 | { | 703 | * We want to write everything out, not just down to the dirty |
708 | struct work_struct *work; | 704 | * threshold |
705 | */ | ||
709 | 706 | ||
710 | work = kmalloc(sizeof(*work), GFP_ATOMIC); | 707 | if (bdi_has_dirty_io(&q->backing_dev_info)) |
711 | if (work) { | 708 | bdi_start_writeback(&q->backing_dev_info, NULL, nr_pages); |
712 | INIT_WORK(work, do_laptop_sync); | ||
713 | schedule_work(work); | ||
714 | } | ||
715 | } | 709 | } |
716 | 710 | ||
717 | /* | 711 | /* |
@@ -719,9 +713,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 | 713 | * 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. | 714 | * then push it back - the user is still using the disk. |
721 | */ | 715 | */ |
722 | void laptop_io_completion(void) | 716 | void laptop_io_completion(struct backing_dev_info *info) |
723 | { | 717 | { |
724 | mod_timer(&laptop_mode_wb_timer, jiffies + laptop_mode); | 718 | mod_timer(&info->laptop_mode_wb_timer, jiffies + laptop_mode); |
725 | } | 719 | } |
726 | 720 | ||
727 | /* | 721 | /* |
@@ -731,7 +725,14 @@ void laptop_io_completion(void) | |||
731 | */ | 725 | */ |
732 | void laptop_sync_completion(void) | 726 | void laptop_sync_completion(void) |
733 | { | 727 | { |
734 | del_timer(&laptop_mode_wb_timer); | 728 | struct backing_dev_info *bdi; |
729 | |||
730 | rcu_read_lock(); | ||
731 | |||
732 | list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) | ||
733 | del_timer(&bdi->laptop_mode_wb_timer); | ||
734 | |||
735 | rcu_read_unlock(); | ||
735 | } | 736 | } |
736 | 737 | ||
737 | /* | 738 | /* |