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 13 enum wbt_flags { 14 WBT_TRACKED = 1, /* write, tracked for throttling */ 15 WBT_READ = 2, /* read */ 16 WBT_KSWAPD = 4, /* write, from kswapd */ 17 WBT_DISCARD = 8, /* discard */ 18 19 WBT_NR_BITS = 4, /* number of bits */ 20 }; 21 22 enum { 23 WBT_RWQ_BG = 0, 24 WBT_RWQ_KSWAPD, 25 WBT_RWQ_DISCARD, 26 WBT_NUM_RWQ, 27 }; 28 29 /* 30 * Enable states. Either off, or on by default (done at init time), 31 * or on through manual setup in sysfs. 32 */ 33 enum { 34 WBT_STATE_ON_DEFAULT = 1, 35 WBT_STATE_ON_MANUAL = 2, 36 }; 37 38 struct rq_wait { 39 wait_queue_head_t wait; 40 atomic_t inflight; 41 }; 42 43 struct rq_wb { 44 /* 45 * Settings that govern how we throttle 46 */ 47 unsigned int wb_background; /* background writeback */ 48 unsigned int wb_normal; /* normal writeback */ 49 unsigned int wb_max; /* max throughput writeback */ 50 int scale_step; 51 bool scaled_max; 52 53 short enable_state; /* WBT_STATE_* */ 54 55 /* 56 * Number of consecutive periods where we don't have enough 57 * information to make a firm scale up/down decision. 58 */ 59 unsigned int unknown_cnt; 60 61 u64 win_nsec; /* default window size */ 62 u64 cur_win_nsec; /* current window size */ 63 64 struct blk_stat_callback *cb; 65 66 u64 sync_issue; 67 void *sync_cookie; 68 69 unsigned int wc; 70 unsigned int queue_depth; 71 72 unsigned long last_issue; /* last non-throttled issue */ 73 unsigned long last_comp; /* last non-throttled comp */ 74 unsigned long min_lat_nsec; 75 struct request_queue *queue; 76 struct rq_wait rq_wait[WBT_NUM_RWQ]; 77 }; 78 79 static inline unsigned int wbt_inflight(struct rq_wb *rwb) 80 { 81 unsigned int i, ret = 0; 82 83 for (i = 0; i < WBT_NUM_RWQ; i++) 84 ret += atomic_read(&rwb->rq_wait[i].inflight); 85 86 return ret; 87 } 88 89 #ifdef CONFIG_BLK_WBT 90 91 static inline void wbt_track(struct request *rq, enum wbt_flags flags) 92 { 93 rq->wbt_flags |= flags; 94 } 95 96 void __wbt_done(struct rq_wb *, enum wbt_flags); 97 void wbt_done(struct rq_wb *, struct request *); 98 enum wbt_flags wbt_wait(struct rq_wb *, struct bio *, spinlock_t *); 99 int wbt_init(struct request_queue *); 100 void wbt_exit(struct request_queue *); 101 void wbt_update_limits(struct rq_wb *); 102 void wbt_requeue(struct rq_wb *, struct request *); 103 void wbt_issue(struct rq_wb *, struct request *); 104 void wbt_disable_default(struct request_queue *); 105 void wbt_enable_default(struct request_queue *); 106 107 void wbt_set_queue_depth(struct rq_wb *, unsigned int); 108 void wbt_set_write_cache(struct rq_wb *, bool); 109 110 u64 wbt_default_latency_nsec(struct request_queue *); 111 112 #else 113 114 static inline void wbt_track(struct request *rq, enum wbt_flags flags) 115 { 116 } 117 static inline void __wbt_done(struct rq_wb *rwb, enum wbt_flags flags) 118 { 119 } 120 static inline void wbt_done(struct rq_wb *rwb, struct request *rq) 121 { 122 } 123 static inline enum wbt_flags wbt_wait(struct rq_wb *rwb, struct bio *bio, 124 spinlock_t *lock) 125 { 126 return 0; 127 } 128 static inline int wbt_init(struct request_queue *q) 129 { 130 return -EINVAL; 131 } 132 static inline void wbt_exit(struct request_queue *q) 133 { 134 } 135 static inline void wbt_update_limits(struct rq_wb *rwb) 136 { 137 } 138 static inline void wbt_requeue(struct rq_wb *rwb, struct request *rq) 139 { 140 } 141 static inline void wbt_issue(struct rq_wb *rwb, struct request *rq) 142 { 143 } 144 static inline void wbt_disable_default(struct request_queue *q) 145 { 146 } 147 static inline void wbt_enable_default(struct request_queue *q) 148 { 149 } 150 static inline void wbt_set_queue_depth(struct rq_wb *rwb, unsigned int depth) 151 { 152 } 153 static inline void wbt_set_write_cache(struct rq_wb *rwb, bool wc) 154 { 155 } 156 static inline u64 wbt_default_latency_nsec(struct request_queue *q) 157 { 158 return 0; 159 } 160 161 #endif /* CONFIG_BLK_WBT */ 162 163 #endif 164