summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarshad Shirwadkar <harshadshirwadkar@gmail.com>2019-10-05 14:59:27 -0400
committerJens Axboe <axboe@kernel.dk>2019-10-06 11:26:41 -0400
commitb84477d3ebb96294f87dc3161e53fa8fe22d9bfd (patch)
treec69d5489e1f70ed4b22a7753ac61c26660b8454a
parent0e48f51cbbfbdb79149806de14dcb8bf0f01ca94 (diff)
blk-wbt: fix performance regression in wbt scale_up/scale_down
scale_up wakes up waiters after scaling up. But after scaling max, it should not wake up more waiters as waiters will not have anything to do. This patch fixes this by making scale_up (and also scale_down) return when threshold is reached. This bug causes increased fdatasync latency when fdatasync and dd conv=sync are performed in parallel on 4.19 compared to 4.14. This bug was introduced during refactoring of blk-wbt code. Fixes: a79050434b45 ("blk-rq-qos: refactor out common elements of blk-wbt") Cc: stable@vger.kernel.org Cc: Josef Bacik <jbacik@fb.com> Signed-off-by: Harshad Shirwadkar <harshadshirwadkar@gmail.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--block/blk-rq-qos.c14
-rw-r--r--block/blk-rq-qos.h4
-rw-r--r--block/blk-wbt.c6
3 files changed, 15 insertions, 9 deletions
diff --git a/block/blk-rq-qos.c b/block/blk-rq-qos.c
index 61b635bc2a31..656460636ad3 100644
--- a/block/blk-rq-qos.c
+++ b/block/blk-rq-qos.c
@@ -160,24 +160,27 @@ bool rq_depth_calc_max_depth(struct rq_depth *rqd)
160 return ret; 160 return ret;
161} 161}
162 162
163void rq_depth_scale_up(struct rq_depth *rqd) 163/* Returns true on success and false if scaling up wasn't possible */
164bool rq_depth_scale_up(struct rq_depth *rqd)
164{ 165{
165 /* 166 /*
166 * Hit max in previous round, stop here 167 * Hit max in previous round, stop here
167 */ 168 */
168 if (rqd->scaled_max) 169 if (rqd->scaled_max)
169 return; 170 return false;
170 171
171 rqd->scale_step--; 172 rqd->scale_step--;
172 173
173 rqd->scaled_max = rq_depth_calc_max_depth(rqd); 174 rqd->scaled_max = rq_depth_calc_max_depth(rqd);
175 return true;
174} 176}
175 177
176/* 178/*
177 * Scale rwb down. If 'hard_throttle' is set, do it quicker, since we 179 * Scale rwb down. If 'hard_throttle' is set, do it quicker, since we
178 * had a latency violation. 180 * had a latency violation. Returns true on success and returns false if
181 * scaling down wasn't possible.
179 */ 182 */
180void rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle) 183bool rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle)
181{ 184{
182 /* 185 /*
183 * Stop scaling down when we've hit the limit. This also prevents 186 * Stop scaling down when we've hit the limit. This also prevents
@@ -185,7 +188,7 @@ void rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle)
185 * keep up. 188 * keep up.
186 */ 189 */
187 if (rqd->max_depth == 1) 190 if (rqd->max_depth == 1)
188 return; 191 return false;
189 192
190 if (rqd->scale_step < 0 && hard_throttle) 193 if (rqd->scale_step < 0 && hard_throttle)
191 rqd->scale_step = 0; 194 rqd->scale_step = 0;
@@ -194,6 +197,7 @@ void rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle)
194 197
195 rqd->scaled_max = false; 198 rqd->scaled_max = false;
196 rq_depth_calc_max_depth(rqd); 199 rq_depth_calc_max_depth(rqd);
200 return true;
197} 201}
198 202
199struct rq_qos_wait_data { 203struct rq_qos_wait_data {
diff --git a/block/blk-rq-qos.h b/block/blk-rq-qos.h
index 08a09dbe0f4b..e8cb68f6958a 100644
--- a/block/blk-rq-qos.h
+++ b/block/blk-rq-qos.h
@@ -130,8 +130,8 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data,
130 acquire_inflight_cb_t *acquire_inflight_cb, 130 acquire_inflight_cb_t *acquire_inflight_cb,
131 cleanup_cb_t *cleanup_cb); 131 cleanup_cb_t *cleanup_cb);
132bool rq_wait_inc_below(struct rq_wait *rq_wait, unsigned int limit); 132bool rq_wait_inc_below(struct rq_wait *rq_wait, unsigned int limit);
133void rq_depth_scale_up(struct rq_depth *rqd); 133bool rq_depth_scale_up(struct rq_depth *rqd);
134void rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle); 134bool rq_depth_scale_down(struct rq_depth *rqd, bool hard_throttle);
135bool rq_depth_calc_max_depth(struct rq_depth *rqd); 135bool rq_depth_calc_max_depth(struct rq_depth *rqd);
136 136
137void __rq_qos_cleanup(struct rq_qos *rqos, struct bio *bio); 137void __rq_qos_cleanup(struct rq_qos *rqos, struct bio *bio);
diff --git a/block/blk-wbt.c b/block/blk-wbt.c
index 8af553a0ba00..8641ba9793c5 100644
--- a/block/blk-wbt.c
+++ b/block/blk-wbt.c
@@ -308,7 +308,8 @@ static void calc_wb_limits(struct rq_wb *rwb)
308 308
309static void scale_up(struct rq_wb *rwb) 309static void scale_up(struct rq_wb *rwb)
310{ 310{
311 rq_depth_scale_up(&rwb->rq_depth); 311 if (!rq_depth_scale_up(&rwb->rq_depth))
312 return;
312 calc_wb_limits(rwb); 313 calc_wb_limits(rwb);
313 rwb->unknown_cnt = 0; 314 rwb->unknown_cnt = 0;
314 rwb_wake_all(rwb); 315 rwb_wake_all(rwb);
@@ -317,7 +318,8 @@ static void scale_up(struct rq_wb *rwb)
317 318
318static void scale_down(struct rq_wb *rwb, bool hard_throttle) 319static void scale_down(struct rq_wb *rwb, bool hard_throttle)
319{ 320{
320 rq_depth_scale_down(&rwb->rq_depth, hard_throttle); 321 if (!rq_depth_scale_down(&rwb->rq_depth, hard_throttle))
322 return;
321 calc_wb_limits(rwb); 323 calc_wb_limits(rwb);
322 rwb->unknown_cnt = 0; 324 rwb->unknown_cnt = 0;
323 rwb_trace_step(rwb, "scale down"); 325 rwb_trace_step(rwb, "scale down");