diff options
author | Wu Fengguang <fengguang.wu@intel.com> | 2010-08-29 13:22:30 -0400 |
---|---|---|
committer | Wu Fengguang <fengguang.wu@intel.com> | 2011-07-10 01:09:01 -0400 |
commit | e98be2d599207c6b31e9bb340d52a231b2f3662d (patch) | |
tree | 3ae28e7d621a6e2ddf8e7462f8d282901c113d5c /include/linux | |
parent | f7d2b1ecd0c714adefc7d3a942ef87beb828a763 (diff) |
writeback: bdi write bandwidth estimation
The estimation value will start from 100MB/s and adapt to the real
bandwidth in seconds.
It tries to update the bandwidth only when disk is fully utilized.
Any inactive period of more than one second will be skipped.
The estimated bandwidth will be reflecting how fast the device can
writeout when _fully utilized_, and won't drop to 0 when it goes idle.
The value will remain constant at disk idle time. At busy write time, if
not considering fluctuations, it will also remain high unless be knocked
down by possible concurrent reads that compete for the disk time and
bandwidth with async writes.
The estimation is not done purely in the flusher because there is no
guarantee for write_cache_pages() to return timely to update bandwidth.
The bdi->avg_write_bandwidth smoothing is very effective for filtering
out sudden spikes, however may be a little biased in long term.
The overheads are low because the bdi bandwidth update only occurs at
200ms intervals.
The 200ms update interval is suitable, because it's not possible to get
the real bandwidth for the instance at all, due to large fluctuations.
The NFS commits can be as large as seconds worth of data. One XFS
completion may be as large as half second worth of data if we are going
to increase the write chunk to half second worth of data. In ext4,
fluctuations with time period of around 5 seconds is observed. And there
is another pattern of irregular periods of up to 20 seconds on SSD tests.
That's why we are not only doing the estimation at 200ms intervals, but
also averaging them over a period of 3 seconds and then go further to do
another level of smoothing in avg_write_bandwidth.
CC: Li Shaohua <shaohua.li@intel.com>
CC: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/backing-dev.h | 5 | ||||
-rw-r--r-- | include/linux/writeback.h | 3 |
2 files changed, 8 insertions, 0 deletions
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index 469d56443c63..a008982e7c08 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h | |||
@@ -73,6 +73,11 @@ struct backing_dev_info { | |||
73 | 73 | ||
74 | struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS]; | 74 | struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS]; |
75 | 75 | ||
76 | unsigned long bw_time_stamp; /* last time write bw is updated */ | ||
77 | unsigned long written_stamp; /* pages written at bw_time_stamp */ | ||
78 | unsigned long write_bandwidth; /* the estimated write bandwidth */ | ||
79 | unsigned long avg_write_bandwidth; /* further smoothed write bw */ | ||
80 | |||
76 | struct prop_local_percpu completions; | 81 | struct prop_local_percpu completions; |
77 | int dirty_exceeded; | 82 | int dirty_exceeded; |
78 | 83 | ||
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index df1b7f18f100..66862f2d90c8 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
@@ -118,6 +118,9 @@ void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty); | |||
118 | unsigned long bdi_dirty_limit(struct backing_dev_info *bdi, | 118 | unsigned long bdi_dirty_limit(struct backing_dev_info *bdi, |
119 | unsigned long dirty); | 119 | unsigned long dirty); |
120 | 120 | ||
121 | void __bdi_update_bandwidth(struct backing_dev_info *bdi, | ||
122 | unsigned long start_time); | ||
123 | |||
121 | void page_writeback_init(void); | 124 | void page_writeback_init(void); |
122 | void balance_dirty_pages_ratelimited_nr(struct address_space *mapping, | 125 | void balance_dirty_pages_ratelimited_nr(struct address_space *mapping, |
123 | unsigned long nr_pages_dirtied); | 126 | unsigned long nr_pages_dirtied); |