Lines Matching +full:wakeup +full:- +full:latency +full:- +full:us

1 // SPDX-License-Identifier: GPL-2.0
6 * - Monitor latencies in a defined window of time.
7 * - If the minimum latency in the above window exceeds some target, increment
10 * - For any window where we don't have solid data on what the latencies
12 * - If latencies look good, decrement scaling step.
13 * - If we're only doing writes, allow the scaling step to go negative. This
25 #include <linux/backing-dev.h>
28 #include "blk-wbt.h"
29 #include "blk-rq-qos.h"
36 rq->wbt_flags = 0; in wbt_clear_state()
41 return rq->wbt_flags; in wbt_flags()
46 return rq->wbt_flags & WBT_TRACKED; in wbt_is_tracked()
51 return rq->wbt_flags & WBT_READ; in wbt_is_read()
80 return rwb && rwb->wb_normal != 0; in rwb_enabled()
99 struct bdi_writeback *wb = &rwb->rqos.q->backing_dev_info->wb; in wb_recent_wait()
101 return time_before(jiffies, wb->dirty_sleep + HZ); in wb_recent_wait()
108 return &rwb->rq_wait[WBT_RWQ_KSWAPD]; in get_rq_wait()
110 return &rwb->rq_wait[WBT_RWQ_DISCARD]; in get_rq_wait()
112 return &rwb->rq_wait[WBT_RWQ_BG]; in get_rq_wait()
120 struct rq_wait *rqw = &rwb->rq_wait[i]; in rwb_wake_all()
122 if (wq_has_sleeper(&rqw->wait)) in rwb_wake_all()
123 wake_up_all(&rqw->wait); in rwb_wake_all()
132 inflight = atomic_dec_return(&rqw->inflight); in wbt_rqw_done()
149 limit = rwb->wb_background; in wbt_rqw_done()
150 else if (rwb->wc && !wb_recent_wait(rwb)) in wbt_rqw_done()
153 limit = rwb->wb_normal; in wbt_rqw_done()
161 if (wq_has_sleeper(&rqw->wait)) { in wbt_rqw_done()
162 int diff = limit - inflight; in wbt_rqw_done()
164 if (!inflight || diff >= rwb->wb_background / 2) in wbt_rqw_done()
165 wake_up_all(&rqw->wait); in wbt_rqw_done()
190 if (rwb->sync_cookie == rq) { in wbt_done()
191 rwb->sync_issue = 0; in wbt_done()
192 rwb->sync_cookie = NULL; in wbt_done()
196 wb_timestamp(rwb, &rwb->last_comp); in wbt_done()
198 WARN_ON_ONCE(rq == rwb->sync_cookie); in wbt_done()
209 * that it's writes impacting us, and not just some sole read on in stat_sample_valid()
218 u64 now, issue = READ_ONCE(rwb->sync_issue); in rwb_sync_issue_lat()
220 if (!issue || !rwb->sync_cookie) in rwb_sync_issue_lat()
224 return now - issue; in rwb_sync_issue_lat()
236 struct backing_dev_info *bdi = rwb->rqos.q->backing_dev_info; in latency_exceeded()
237 struct rq_depth *rqd = &rwb->rq_depth; in latency_exceeded()
243 * flag the latency as exceeded. wbt works off completion latencies, in latency_exceeded()
247 * window, then count that sync IO as a violation of the latency. in latency_exceeded()
250 if (thislat > rwb->cur_win_nsec || in latency_exceeded()
251 (thislat > rwb->min_lat_nsec && !stat[READ].nr_samples)) { in latency_exceeded()
263 * waited or still has writes in flights, consider us doing in latency_exceeded()
273 * If the 'min' latency exceeds our target, step down. in latency_exceeded()
275 if (stat[READ].min > rwb->min_lat_nsec) { in latency_exceeded()
281 if (rqd->scale_step) in latency_exceeded()
289 struct backing_dev_info *bdi = rwb->rqos.q->backing_dev_info; in rwb_trace_step()
290 struct rq_depth *rqd = &rwb->rq_depth; in rwb_trace_step()
292 trace_wbt_step(bdi, msg, rqd->scale_step, rwb->cur_win_nsec, in rwb_trace_step()
293 rwb->wb_background, rwb->wb_normal, rqd->max_depth); in rwb_trace_step()
298 if (rwb->min_lat_nsec == 0) { in calc_wb_limits()
299 rwb->wb_normal = rwb->wb_background = 0; in calc_wb_limits()
300 } else if (rwb->rq_depth.max_depth <= 2) { in calc_wb_limits()
301 rwb->wb_normal = rwb->rq_depth.max_depth; in calc_wb_limits()
302 rwb->wb_background = 1; in calc_wb_limits()
304 rwb->wb_normal = (rwb->rq_depth.max_depth + 1) / 2; in calc_wb_limits()
305 rwb->wb_background = (rwb->rq_depth.max_depth + 3) / 4; in calc_wb_limits()
311 if (!rq_depth_scale_up(&rwb->rq_depth)) in scale_up()
314 rwb->unknown_cnt = 0; in scale_up()
321 if (!rq_depth_scale_down(&rwb->rq_depth, hard_throttle)) in scale_down()
324 rwb->unknown_cnt = 0; in scale_down()
330 struct rq_depth *rqd = &rwb->rq_depth; in rwb_arm_timer()
332 if (rqd->scale_step > 0) { in rwb_arm_timer()
339 rwb->cur_win_nsec = div_u64(rwb->win_nsec << 4, in rwb_arm_timer()
340 int_sqrt((rqd->scale_step + 1) << 8)); in rwb_arm_timer()
346 rwb->cur_win_nsec = rwb->win_nsec; in rwb_arm_timer()
349 blk_stat_activate_nsecs(rwb->cb, rwb->cur_win_nsec); in rwb_arm_timer()
354 struct rq_wb *rwb = cb->data; in wb_timer_fn()
355 struct rq_depth *rqd = &rwb->rq_depth; in wb_timer_fn()
359 status = latency_exceeded(rwb, cb->stat); in wb_timer_fn()
361 trace_wbt_timer(rwb->rqos.q->backing_dev_info, status, rqd->scale_step, in wb_timer_fn()
365 * If we exceeded the latency target, step down. If we did not, in wb_timer_fn()
385 if (++rwb->unknown_cnt < RWB_UNKNOWN_BUMP) in wb_timer_fn()
392 if (rqd->scale_step > 0) in wb_timer_fn()
394 else if (rqd->scale_step < 0) in wb_timer_fn()
402 * Re-arm timer, if we have IO in flight in wb_timer_fn()
404 if (rqd->scale_step || inflight) in wb_timer_fn()
410 struct rq_depth *rqd = &rwb->rq_depth; in wbt_update_limits()
412 rqd->scale_step = 0; in wbt_update_limits()
413 rqd->scaled_max = false; in wbt_update_limits()
426 return RQWB(rqos)->min_lat_nsec; in wbt_get_min_lat()
434 RQWB(rqos)->min_lat_nsec = val; in wbt_set_min_lat()
435 RQWB(rqos)->enable_state = WBT_STATE_ON_MANUAL; in wbt_set_min_lat()
444 return time_before(now, rwb->last_issue + HZ / 10) || in close_io()
445 time_before(now, rwb->last_comp + HZ / 10); in close_io()
456 * we'll properly inc a new IO, and dec+wakeup at the end. in get_limit()
462 return rwb->wb_background; in get_limit()
473 limit = rwb->rq_depth.max_depth; in get_limit()
477 * limit us to half the depth for background writeback. in get_limit()
479 limit = rwb->wb_background; in get_limit()
481 limit = rwb->wb_normal; in get_limit()
495 return rq_wait_inc_below(rqw, get_limit(data->rwb, data->rw)); in wbt_inflight_cb()
501 wbt_rqw_done(data->rwb, rqw, data->wb_acct); in wbt_cleanup_cb()
528 if ((bio->bi_opf & (REQ_SYNC | REQ_IDLE)) == in wbt_should_throttle()
569 * If we do sleep, we'll release and re-grab it.
579 wb_timestamp(rwb, &rwb->last_issue); in wbt_wait()
583 __wbt_wait(rwb, flags, bio->bi_opf); in wbt_wait()
585 if (!blk_stat_is_active(rwb->cb)) in wbt_wait()
592 rq->wbt_flags |= bio_to_wbt_flags(rwb, bio); in wbt_track()
603 * Track sync issue, in case it takes a long time to complete. Allows us in wbt_issue()
609 if (wbt_is_read(rq) && !rwb->sync_issue) { in wbt_issue()
610 rwb->sync_cookie = rq; in wbt_issue()
611 rwb->sync_issue = rq->io_start_time_ns; in wbt_issue()
620 if (rq == rwb->sync_cookie) { in wbt_requeue()
621 rwb->sync_issue = 0; in wbt_requeue()
622 rwb->sync_cookie = NULL; in wbt_requeue()
630 RQWB(rqos)->wc = write_cache_on; in wbt_set_write_cache()
655 * We default to 2msec for non-rotational storage, and 75msec in wbt_default_latency_nsec()
674 return -1; in wbt_data_dir()
679 RQWB(rqos)->rq_depth.queue_depth = blk_queue_depth(rqos->q); in wbt_queue_depth_changed()
686 struct request_queue *q = rqos->q; in wbt_exit()
688 blk_stat_remove_callback(q, rwb->cb); in wbt_exit()
689 blk_stat_free_callback(rwb->cb); in wbt_exit()
703 if (rwb->enable_state == WBT_STATE_ON_DEFAULT) { in wbt_disable_default()
704 blk_stat_deactivate(rwb->cb); in wbt_disable_default()
705 rwb->wb_normal = 0; in wbt_disable_default()
716 seq_printf(m, "%llu\n", rwb->cur_win_nsec); in wbt_curr_win_nsec_show()
725 seq_printf(m, "%d\n", rwb->enable_state); in wbt_enabled_show()
733 seq_printf(m, "%u\n", rqos->id); in wbt_id_show()
745 atomic_read(&rwb->rq_wait[i].inflight)); in wbt_inflight_show()
754 seq_printf(m, "%lu\n", rwb->min_lat_nsec); in wbt_min_lat_nsec_show()
763 seq_printf(m, "%u\n", rwb->unknown_cnt); in wbt_unknown_cnt_show()
772 seq_printf(m, "%u\n", rwb->wb_normal); in wbt_normal_show()
781 seq_printf(m, "%u\n", rwb->wb_background); in wbt_background_show()
819 return -ENOMEM; in wbt_init()
821 rwb->cb = blk_stat_alloc_callback(wb_timer_fn, wbt_data_dir, 2, rwb); in wbt_init()
822 if (!rwb->cb) { in wbt_init()
824 return -ENOMEM; in wbt_init()
828 rq_wait_init(&rwb->rq_wait[i]); in wbt_init()
830 rwb->rqos.id = RQ_QOS_WBT; in wbt_init()
831 rwb->rqos.ops = &wbt_rqos_ops; in wbt_init()
832 rwb->rqos.q = q; in wbt_init()
833 rwb->last_comp = rwb->last_issue = jiffies; in wbt_init()
834 rwb->win_nsec = RWB_WINDOW_NSEC; in wbt_init()
835 rwb->enable_state = WBT_STATE_ON_DEFAULT; in wbt_init()
836 rwb->wc = 1; in wbt_init()
837 rwb->rq_depth.default_depth = RWB_DEF_DEPTH; in wbt_init()
843 rq_qos_add(q, &rwb->rqos); in wbt_init()
844 blk_stat_add_callback(q, rwb->cb); in wbt_init()
846 rwb->min_lat_nsec = wbt_default_latency_nsec(q); in wbt_init()
848 wbt_queue_depth_changed(&rwb->rqos); in wbt_init()
849 wbt_set_write_cache(q, test_bit(QUEUE_FLAG_WC, &q->queue_flags)); in wbt_init()