diff options
author | Tejun Heo <tj@kernel.org> | 2015-05-22 18:23:26 -0400 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2015-06-02 10:38:13 -0400 |
commit | daddfa3cb30ebfe322d50af146d830fd435ddb1f (patch) | |
tree | 4b67764441edb8e62798565e314759ce048218dd /mm/page-writeback.c | |
parent | b1cbc6d40c85639d405fee37c7bb688c3bf468d6 (diff) |
writeback: add dirty_throttle_control->pos_ratio
wb_position_ratio() is used to calculate pos_ratio, which is used for
two purposes. wb_update_dirty_ratelimit() uses it to adjust
wb->[balanced_]dirty_ratelimit gradually and balance_dirty_pages() to
immediately adjust dirty_ratelimit right before applying it to
determine pause duration.
While wb_update_dirty_ratelimit() is separately rate limited from
balance_dirty_pages(), on the run where the ratelimit is updated, we
end up calculating pos_ratio twice with the same parameters.
This patch adds dirty_throttle_control->pos_ratio.
balance_dirty_pages() calculates it once per run and
wb_update_dirty_ratelimit() uses the value stored in
dirty_throttle_control.
This removes the duplicate calculation and also will help implementing
memcg wb_domain.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Jan Kara <jack@suse.cz>
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Greg Thelen <gthelen@google.com>
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'mm/page-writeback.c')
-rw-r--r-- | mm/page-writeback.c | 36 |
1 files changed, 21 insertions, 15 deletions
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 2352c69bff12..fcebae7db874 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -135,6 +135,8 @@ struct dirty_throttle_control { | |||
135 | unsigned long wb_dirty; /* per-wb counterparts */ | 135 | unsigned long wb_dirty; /* per-wb counterparts */ |
136 | unsigned long wb_thresh; | 136 | unsigned long wb_thresh; |
137 | unsigned long wb_bg_thresh; | 137 | unsigned long wb_bg_thresh; |
138 | |||
139 | unsigned long pos_ratio; | ||
138 | }; | 140 | }; |
139 | 141 | ||
140 | #define GDTC_INIT(__wb) .wb = (__wb) | 142 | #define GDTC_INIT(__wb) .wb = (__wb) |
@@ -717,7 +719,7 @@ static long long pos_ratio_polynom(unsigned long setpoint, | |||
717 | * card's wb_dirty may rush to many times higher than wb_setpoint. | 719 | * card's wb_dirty may rush to many times higher than wb_setpoint. |
718 | * - the wb dirty thresh drops quickly due to change of JBOD workload | 720 | * - the wb dirty thresh drops quickly due to change of JBOD workload |
719 | */ | 721 | */ |
720 | static unsigned long wb_position_ratio(struct dirty_throttle_control *dtc) | 722 | static void wb_position_ratio(struct dirty_throttle_control *dtc) |
721 | { | 723 | { |
722 | struct bdi_writeback *wb = dtc->wb; | 724 | struct bdi_writeback *wb = dtc->wb; |
723 | unsigned long write_bw = wb->avg_write_bandwidth; | 725 | unsigned long write_bw = wb->avg_write_bandwidth; |
@@ -731,8 +733,10 @@ static unsigned long wb_position_ratio(struct dirty_throttle_control *dtc) | |||
731 | long long pos_ratio; /* for scaling up/down the rate limit */ | 733 | long long pos_ratio; /* for scaling up/down the rate limit */ |
732 | long x; | 734 | long x; |
733 | 735 | ||
736 | dtc->pos_ratio = 0; | ||
737 | |||
734 | if (unlikely(dtc->dirty >= limit)) | 738 | if (unlikely(dtc->dirty >= limit)) |
735 | return 0; | 739 | return; |
736 | 740 | ||
737 | /* | 741 | /* |
738 | * global setpoint | 742 | * global setpoint |
@@ -770,18 +774,20 @@ static unsigned long wb_position_ratio(struct dirty_throttle_control *dtc) | |||
770 | if (unlikely(wb->bdi->capabilities & BDI_CAP_STRICTLIMIT)) { | 774 | if (unlikely(wb->bdi->capabilities & BDI_CAP_STRICTLIMIT)) { |
771 | long long wb_pos_ratio; | 775 | long long wb_pos_ratio; |
772 | 776 | ||
773 | if (dtc->wb_dirty < 8) | 777 | if (dtc->wb_dirty < 8) { |
774 | return min_t(long long, pos_ratio * 2, | 778 | dtc->pos_ratio = min_t(long long, pos_ratio * 2, |
775 | 2 << RATELIMIT_CALC_SHIFT); | 779 | 2 << RATELIMIT_CALC_SHIFT); |
780 | return; | ||
781 | } | ||
776 | 782 | ||
777 | if (dtc->wb_dirty >= wb_thresh) | 783 | if (dtc->wb_dirty >= wb_thresh) |
778 | return 0; | 784 | return; |
779 | 785 | ||
780 | wb_setpoint = dirty_freerun_ceiling(wb_thresh, | 786 | wb_setpoint = dirty_freerun_ceiling(wb_thresh, |
781 | dtc->wb_bg_thresh); | 787 | dtc->wb_bg_thresh); |
782 | 788 | ||
783 | if (wb_setpoint == 0 || wb_setpoint == wb_thresh) | 789 | if (wb_setpoint == 0 || wb_setpoint == wb_thresh) |
784 | return 0; | 790 | return; |
785 | 791 | ||
786 | wb_pos_ratio = pos_ratio_polynom(wb_setpoint, dtc->wb_dirty, | 792 | wb_pos_ratio = pos_ratio_polynom(wb_setpoint, dtc->wb_dirty, |
787 | wb_thresh); | 793 | wb_thresh); |
@@ -807,7 +813,8 @@ static unsigned long wb_position_ratio(struct dirty_throttle_control *dtc) | |||
807 | * is 2. We might want to tweak this if we observe the control | 813 | * is 2. We might want to tweak this if we observe the control |
808 | * system is too slow to adapt. | 814 | * system is too slow to adapt. |
809 | */ | 815 | */ |
810 | return min(pos_ratio, wb_pos_ratio); | 816 | dtc->pos_ratio = min(pos_ratio, wb_pos_ratio); |
817 | return; | ||
811 | } | 818 | } |
812 | 819 | ||
813 | /* | 820 | /* |
@@ -888,7 +895,7 @@ static unsigned long wb_position_ratio(struct dirty_throttle_control *dtc) | |||
888 | pos_ratio *= 8; | 895 | pos_ratio *= 8; |
889 | } | 896 | } |
890 | 897 | ||
891 | return pos_ratio; | 898 | dtc->pos_ratio = pos_ratio; |
892 | } | 899 | } |
893 | 900 | ||
894 | static void wb_update_write_bandwidth(struct bdi_writeback *wb, | 901 | static void wb_update_write_bandwidth(struct bdi_writeback *wb, |
@@ -1009,7 +1016,6 @@ static void wb_update_dirty_ratelimit(struct dirty_throttle_control *dtc, | |||
1009 | unsigned long dirty_rate; | 1016 | unsigned long dirty_rate; |
1010 | unsigned long task_ratelimit; | 1017 | unsigned long task_ratelimit; |
1011 | unsigned long balanced_dirty_ratelimit; | 1018 | unsigned long balanced_dirty_ratelimit; |
1012 | unsigned long pos_ratio; | ||
1013 | unsigned long step; | 1019 | unsigned long step; |
1014 | unsigned long x; | 1020 | unsigned long x; |
1015 | 1021 | ||
@@ -1019,12 +1025,11 @@ static void wb_update_dirty_ratelimit(struct dirty_throttle_control *dtc, | |||
1019 | */ | 1025 | */ |
1020 | dirty_rate = (dirtied - wb->dirtied_stamp) * HZ / elapsed; | 1026 | dirty_rate = (dirtied - wb->dirtied_stamp) * HZ / elapsed; |
1021 | 1027 | ||
1022 | pos_ratio = wb_position_ratio(dtc); | ||
1023 | /* | 1028 | /* |
1024 | * task_ratelimit reflects each dd's dirty rate for the past 200ms. | 1029 | * task_ratelimit reflects each dd's dirty rate for the past 200ms. |
1025 | */ | 1030 | */ |
1026 | task_ratelimit = (u64)dirty_ratelimit * | 1031 | task_ratelimit = (u64)dirty_ratelimit * |
1027 | pos_ratio >> RATELIMIT_CALC_SHIFT; | 1032 | dtc->pos_ratio >> RATELIMIT_CALC_SHIFT; |
1028 | task_ratelimit++; /* it helps rampup dirty_ratelimit from tiny values */ | 1033 | task_ratelimit++; /* it helps rampup dirty_ratelimit from tiny values */ |
1029 | 1034 | ||
1030 | /* | 1035 | /* |
@@ -1375,7 +1380,6 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
1375 | bool dirty_exceeded = false; | 1380 | bool dirty_exceeded = false; |
1376 | unsigned long task_ratelimit; | 1381 | unsigned long task_ratelimit; |
1377 | unsigned long dirty_ratelimit; | 1382 | unsigned long dirty_ratelimit; |
1378 | unsigned long pos_ratio; | ||
1379 | struct backing_dev_info *bdi = wb->bdi; | 1383 | struct backing_dev_info *bdi = wb->bdi; |
1380 | bool strictlimit = bdi->capabilities & BDI_CAP_STRICTLIMIT; | 1384 | bool strictlimit = bdi->capabilities & BDI_CAP_STRICTLIMIT; |
1381 | unsigned long start_time = jiffies; | 1385 | unsigned long start_time = jiffies; |
@@ -1433,6 +1437,9 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
1433 | 1437 | ||
1434 | dirty_exceeded = (gdtc->wb_dirty > gdtc->wb_thresh) && | 1438 | dirty_exceeded = (gdtc->wb_dirty > gdtc->wb_thresh) && |
1435 | ((gdtc->dirty > gdtc->thresh) || strictlimit); | 1439 | ((gdtc->dirty > gdtc->thresh) || strictlimit); |
1440 | |||
1441 | wb_position_ratio(gdtc); | ||
1442 | |||
1436 | if (dirty_exceeded && !wb->dirty_exceeded) | 1443 | if (dirty_exceeded && !wb->dirty_exceeded) |
1437 | wb->dirty_exceeded = 1; | 1444 | wb->dirty_exceeded = 1; |
1438 | 1445 | ||
@@ -1444,8 +1451,7 @@ static void balance_dirty_pages(struct address_space *mapping, | |||
1444 | } | 1451 | } |
1445 | 1452 | ||
1446 | dirty_ratelimit = wb->dirty_ratelimit; | 1453 | dirty_ratelimit = wb->dirty_ratelimit; |
1447 | pos_ratio = wb_position_ratio(gdtc); | 1454 | task_ratelimit = ((u64)dirty_ratelimit * gdtc->pos_ratio) >> |
1448 | task_ratelimit = ((u64)dirty_ratelimit * pos_ratio) >> | ||
1449 | RATELIMIT_CALC_SHIFT; | 1455 | RATELIMIT_CALC_SHIFT; |
1450 | max_pause = wb_max_pause(wb, gdtc->wb_dirty); | 1456 | max_pause = wb_max_pause(wb, gdtc->wb_dirty); |
1451 | min_pause = wb_min_pause(wb, max_pause, | 1457 | min_pause = wb_min_pause(wb, max_pause, |