diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2010-07-25 07:29:22 -0400 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2010-08-07 12:53:56 -0400 |
commit | 6467716a37673e8d47b4984eb19839bdad0a8353 (patch) | |
tree | 8b2bfd38d53e31c47654162d4ce9220c4424a31d /include | |
parent | 253c34e9b10c30d3064be654b5b78fbc1a8b1896 (diff) |
writeback: optimize periodic bdi thread wakeups
Whe the first inode for a bdi is marked dirty, we wake up the bdi thread which
should take care of the periodic background write-out. However, the write-out
will actually start only 'dirty_writeback_interval' centisecs later, so we can
delay the wake-up.
This change was requested by Nick Piggin who pointed out that if we delay the
wake-up, we weed out 2 unnecessary contex switches, which matters because
'__mark_inode_dirty()' is a hot-path function.
This patch introduces a new function - 'bdi_wakeup_thread_delayed()', which
sets up a timer to wake-up the bdi thread and returns. So the wake-up is
delayed.
We also delete the timer in bdi threads just before writing-back. And
synchronously delete it when unregistering bdi. At the unregister point the bdi
does not have any users, so no one can arm it again.
Since now we take 'bdi->wb_lock' in the timer, which can execute in softirq
context, we have to use 'spin_lock_bh()' for 'bdi->wb_lock'. This patch makes
this change as well.
This patch also moves the 'bdi_wb_init()' function down in the file to avoid
forward-declaration of 'bdi_wakeup_thread_delayed()'.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/backing-dev.h | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 71b6223e0a77..7628219e5386 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h | |||
@@ -52,6 +52,7 @@ struct bdi_writeback { | |||
52 | unsigned long last_active; /* last time bdi thread was active */ | 52 | unsigned long last_active; /* last time bdi thread was active */ |
53 | 53 | ||
54 | struct task_struct *task; /* writeback thread */ | 54 | struct task_struct *task; /* writeback thread */ |
55 | struct timer_list wakeup_timer; /* used for delayed bdi thread wakeup */ | ||
55 | struct list_head b_dirty; /* dirty inodes */ | 56 | struct list_head b_dirty; /* dirty inodes */ |
56 | struct list_head b_io; /* parked for writeback */ | 57 | struct list_head b_io; /* parked for writeback */ |
57 | struct list_head b_more_io; /* parked for more writeback */ | 58 | struct list_head b_more_io; /* parked for more writeback */ |
@@ -105,6 +106,7 @@ void bdi_start_background_writeback(struct backing_dev_info *bdi); | |||
105 | int bdi_writeback_thread(void *data); | 106 | int bdi_writeback_thread(void *data); |
106 | int bdi_has_dirty_io(struct backing_dev_info *bdi); | 107 | int bdi_has_dirty_io(struct backing_dev_info *bdi); |
107 | void bdi_arm_supers_timer(void); | 108 | void bdi_arm_supers_timer(void); |
109 | void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi); | ||
108 | 110 | ||
109 | extern spinlock_t bdi_lock; | 111 | extern spinlock_t bdi_lock; |
110 | extern struct list_head bdi_list; | 112 | extern struct list_head bdi_list; |