Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0 */ 2 : #ifndef BLK_STAT_H 3 : #define BLK_STAT_H 4 : 5 : #include <linux/kernel.h> 6 : #include <linux/blkdev.h> 7 : #include <linux/ktime.h> 8 : #include <linux/rcupdate.h> 9 : #include <linux/timer.h> 10 : 11 : /** 12 : * struct blk_stat_callback - Block statistics callback. 13 : * 14 : * A &struct blk_stat_callback is associated with a &struct request_queue. While 15 : * @timer is active, that queue's request completion latencies are sorted into 16 : * buckets by @bucket_fn and added to a per-cpu buffer, @cpu_stat. When the 17 : * timer fires, @cpu_stat is flushed to @stat and @timer_fn is invoked. 18 : */ 19 : struct blk_stat_callback { 20 : /* 21 : * @list: RCU list of callbacks for a &struct request_queue. 22 : */ 23 : struct list_head list; 24 : 25 : /** 26 : * @timer: Timer for the next callback invocation. 27 : */ 28 : struct timer_list timer; 29 : 30 : /** 31 : * @cpu_stat: Per-cpu statistics buckets. 32 : */ 33 : struct blk_rq_stat __percpu *cpu_stat; 34 : 35 : /** 36 : * @bucket_fn: Given a request, returns which statistics bucket it 37 : * should be accounted under. Return -1 for no bucket for this 38 : * request. 39 : */ 40 : int (*bucket_fn)(const struct request *); 41 : 42 : /** 43 : * @buckets: Number of statistics buckets. 44 : */ 45 : unsigned int buckets; 46 : 47 : /** 48 : * @stat: Array of statistics buckets. 49 : */ 50 : struct blk_rq_stat *stat; 51 : 52 : /** 53 : * @fn: Callback function. 54 : */ 55 : void (*timer_fn)(struct blk_stat_callback *); 56 : 57 : /** 58 : * @data: Private pointer for the user. 59 : */ 60 : void *data; 61 : 62 : struct rcu_head rcu; 63 : }; 64 : 65 : struct blk_queue_stats *blk_alloc_queue_stats(void); 66 : void blk_free_queue_stats(struct blk_queue_stats *); 67 : 68 : void blk_stat_add(struct request *rq, u64 now); 69 : 70 : /* record time/size info in request but not add a callback */ 71 : void blk_stat_enable_accounting(struct request_queue *q); 72 : 73 : /** 74 : * blk_stat_alloc_callback() - Allocate a block statistics callback. 75 : * @timer_fn: Timer callback function. 76 : * @bucket_fn: Bucket callback function. 77 : * @buckets: Number of statistics buckets. 78 : * @data: Value for the @data field of the &struct blk_stat_callback. 79 : * 80 : * See &struct blk_stat_callback for details on the callback functions. 81 : * 82 : * Return: &struct blk_stat_callback on success or NULL on ENOMEM. 83 : */ 84 : struct blk_stat_callback * 85 : blk_stat_alloc_callback(void (*timer_fn)(struct blk_stat_callback *), 86 : int (*bucket_fn)(const struct request *), 87 : unsigned int buckets, void *data); 88 : 89 : /** 90 : * blk_stat_add_callback() - Add a block statistics callback to be run on a 91 : * request queue. 92 : * @q: The request queue. 93 : * @cb: The callback. 94 : * 95 : * Note that a single &struct blk_stat_callback can only be added to a single 96 : * &struct request_queue. 97 : */ 98 : void blk_stat_add_callback(struct request_queue *q, 99 : struct blk_stat_callback *cb); 100 : 101 : /** 102 : * blk_stat_remove_callback() - Remove a block statistics callback from a 103 : * request queue. 104 : * @q: The request queue. 105 : * @cb: The callback. 106 : * 107 : * When this returns, the callback is not running on any CPUs and will not be 108 : * called again unless readded. 109 : */ 110 : void blk_stat_remove_callback(struct request_queue *q, 111 : struct blk_stat_callback *cb); 112 : 113 : /** 114 : * blk_stat_free_callback() - Free a block statistics callback. 115 : * @cb: The callback. 116 : * 117 : * @cb may be NULL, in which case this does nothing. If it is not NULL, @cb must 118 : * not be associated with a request queue. I.e., if it was previously added with 119 : * blk_stat_add_callback(), it must also have been removed since then with 120 : * blk_stat_remove_callback(). 121 : */ 122 : void blk_stat_free_callback(struct blk_stat_callback *cb); 123 : 124 : /** 125 : * blk_stat_is_active() - Check if a block statistics callback is currently 126 : * gathering statistics. 127 : * @cb: The callback. 128 : */ 129 0 : static inline bool blk_stat_is_active(struct blk_stat_callback *cb) 130 : { 131 0 : return timer_pending(&cb->timer); 132 : } 133 : 134 : /** 135 : * blk_stat_activate_nsecs() - Gather block statistics during a time window in 136 : * nanoseconds. 137 : * @cb: The callback. 138 : * @nsecs: Number of nanoseconds to gather statistics for. 139 : * 140 : * The timer callback will be called when the window expires. 141 : */ 142 : static inline void blk_stat_activate_nsecs(struct blk_stat_callback *cb, 143 : u64 nsecs) 144 : { 145 : mod_timer(&cb->timer, jiffies + nsecs_to_jiffies(nsecs)); 146 : } 147 : 148 : static inline void blk_stat_deactivate(struct blk_stat_callback *cb) 149 : { 150 : del_timer_sync(&cb->timer); 151 : } 152 : 153 : /** 154 : * blk_stat_activate_msecs() - Gather block statistics during a time window in 155 : * milliseconds. 156 : * @cb: The callback. 157 : * @msecs: Number of milliseconds to gather statistics for. 158 : * 159 : * The timer callback will be called when the window expires. 160 : */ 161 0 : static inline void blk_stat_activate_msecs(struct blk_stat_callback *cb, 162 : unsigned int msecs) 163 : { 164 0 : mod_timer(&cb->timer, jiffies + msecs_to_jiffies(msecs)); 165 0 : } 166 : 167 : void blk_rq_stat_add(struct blk_rq_stat *, u64); 168 : void blk_rq_stat_sum(struct blk_rq_stat *, struct blk_rq_stat *); 169 : void blk_rq_stat_init(struct blk_rq_stat *); 170 : 171 : #endif