^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef WB_THROTTLE_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define WB_THROTTLE_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/ktime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "blk-stat.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "blk-rq-qos.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) enum wbt_flags {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) WBT_TRACKED = 1, /* write, tracked for throttling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) WBT_READ = 2, /* read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) WBT_KSWAPD = 4, /* write, from kswapd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) WBT_DISCARD = 8, /* discard */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) WBT_NR_BITS = 4, /* number of bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) WBT_RWQ_BG = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) WBT_RWQ_KSWAPD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) WBT_RWQ_DISCARD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) WBT_NUM_RWQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Enable states. Either off, or on by default (done at init time),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * or on through manual setup in sysfs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) WBT_STATE_ON_DEFAULT = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) WBT_STATE_ON_MANUAL = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) WBT_STATE_OFF_DEFAULT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct rq_wb {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * Settings that govern how we throttle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) unsigned int wb_background; /* background writeback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) unsigned int wb_normal; /* normal writeback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) short enable_state; /* WBT_STATE_* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * Number of consecutive periods where we don't have enough
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * information to make a firm scale up/down decision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned int unknown_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) u64 win_nsec; /* default window size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) u64 cur_win_nsec; /* current window size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct blk_stat_callback *cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u64 sync_issue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) void *sync_cookie;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int wc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned long last_issue; /* last non-throttled issue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned long last_comp; /* last non-throttled comp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned long min_lat_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct rq_qos rqos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct rq_wait rq_wait[WBT_NUM_RWQ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct rq_depth rq_depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static inline struct rq_wb *RQWB(struct rq_qos *rqos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return container_of(rqos, struct rq_wb, rqos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static inline unsigned int wbt_inflight(struct rq_wb *rwb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) unsigned int i, ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) for (i = 0; i < WBT_NUM_RWQ; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ret += atomic_read(&rwb->rq_wait[i].inflight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #ifdef CONFIG_BLK_WBT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int wbt_init(struct request_queue *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) void wbt_disable_default(struct request_queue *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) void wbt_enable_default(struct request_queue *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u64 wbt_get_min_lat(struct request_queue *q);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) void wbt_set_min_lat(struct request_queue *q, u64 val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) void wbt_set_write_cache(struct request_queue *, bool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) u64 wbt_default_latency_nsec(struct request_queue *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static inline void wbt_track(struct request *rq, enum wbt_flags flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static inline int wbt_init(struct request_queue *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static inline void wbt_disable_default(struct request_queue *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static inline void wbt_enable_default(struct request_queue *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static inline void wbt_set_write_cache(struct request_queue *q, bool wc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static inline u64 wbt_get_min_lat(struct request_queue *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static inline void wbt_set_min_lat(struct request_queue *q, u64 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) static inline u64 wbt_default_latency_nsec(struct request_queue *q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #endif /* CONFIG_BLK_WBT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #endif