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