1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2cf43e6beSJens Axboe #ifndef BLK_STAT_H 3cf43e6beSJens Axboe #define BLK_STAT_H 4cf43e6beSJens Axboe 534dbad5dSOmar Sandoval #include <linux/kernel.h> 634dbad5dSOmar Sandoval #include <linux/blkdev.h> 734dbad5dSOmar Sandoval #include <linux/ktime.h> 834dbad5dSOmar Sandoval #include <linux/rcupdate.h> 934dbad5dSOmar Sandoval #include <linux/timer.h> 10cf43e6beSJens Axboe 1134dbad5dSOmar Sandoval /** 1234dbad5dSOmar Sandoval * struct blk_stat_callback - Block statistics callback. 1334dbad5dSOmar Sandoval * 1434dbad5dSOmar Sandoval * A &struct blk_stat_callback is associated with a &struct request_queue. While 1534dbad5dSOmar Sandoval * @timer is active, that queue's request completion latencies are sorted into 1634dbad5dSOmar Sandoval * buckets by @bucket_fn and added to a per-cpu buffer, @cpu_stat. When the 1734dbad5dSOmar Sandoval * timer fires, @cpu_stat is flushed to @stat and @timer_fn is invoked. 1834dbad5dSOmar Sandoval */ 1934dbad5dSOmar Sandoval struct blk_stat_callback { 2034dbad5dSOmar Sandoval /* 2134dbad5dSOmar Sandoval * @list: RCU list of callbacks for a &struct request_queue. 2234dbad5dSOmar Sandoval */ 2334dbad5dSOmar Sandoval struct list_head list; 2434dbad5dSOmar Sandoval 2534dbad5dSOmar Sandoval /** 2634dbad5dSOmar Sandoval * @timer: Timer for the next callback invocation. 2734dbad5dSOmar Sandoval */ 2834dbad5dSOmar Sandoval struct timer_list timer; 2934dbad5dSOmar Sandoval 3034dbad5dSOmar Sandoval /** 3134dbad5dSOmar Sandoval * @cpu_stat: Per-cpu statistics buckets. 3234dbad5dSOmar Sandoval */ 3334dbad5dSOmar Sandoval struct blk_rq_stat __percpu *cpu_stat; 3434dbad5dSOmar Sandoval 3534dbad5dSOmar Sandoval /** 3634dbad5dSOmar Sandoval * @bucket_fn: Given a request, returns which statistics bucket it 37a37244e4SStephen Bates * should be accounted under. Return -1 for no bucket for this 38a37244e4SStephen Bates * request. 3934dbad5dSOmar Sandoval */ 40a37244e4SStephen Bates int (*bucket_fn)(const struct request *); 4134dbad5dSOmar Sandoval 4234dbad5dSOmar Sandoval /** 4334dbad5dSOmar Sandoval * @buckets: Number of statistics buckets. 4434dbad5dSOmar Sandoval */ 4534dbad5dSOmar Sandoval unsigned int buckets; 4634dbad5dSOmar Sandoval 4734dbad5dSOmar Sandoval /** 4834dbad5dSOmar Sandoval * @stat: Array of statistics buckets. 4934dbad5dSOmar Sandoval */ 5034dbad5dSOmar Sandoval struct blk_rq_stat *stat; 5134dbad5dSOmar Sandoval 5234dbad5dSOmar Sandoval /** 5334dbad5dSOmar Sandoval * @fn: Callback function. 5434dbad5dSOmar Sandoval */ 5534dbad5dSOmar Sandoval void (*timer_fn)(struct blk_stat_callback *); 5634dbad5dSOmar Sandoval 5734dbad5dSOmar Sandoval /** 5834dbad5dSOmar Sandoval * @data: Private pointer for the user. 5934dbad5dSOmar Sandoval */ 6034dbad5dSOmar Sandoval void *data; 6134dbad5dSOmar Sandoval 6234dbad5dSOmar Sandoval struct rcu_head rcu; 6334dbad5dSOmar Sandoval }; 6434dbad5dSOmar Sandoval 6534dbad5dSOmar Sandoval struct blk_queue_stats *blk_alloc_queue_stats(void); 6634dbad5dSOmar Sandoval void blk_free_queue_stats(struct blk_queue_stats *); 67*48b5c1fbSJens Axboe bool blk_stats_alloc_enable(struct request_queue *q); 6834dbad5dSOmar Sandoval 69522a7775SOmar Sandoval void blk_stat_add(struct request *rq, u64 now); 7034dbad5dSOmar Sandoval 71b9147dd1SShaohua Li /* record time/size info in request but not add a callback */ 72b9147dd1SShaohua Li void blk_stat_enable_accounting(struct request_queue *q); 73b9147dd1SShaohua Li 7434dbad5dSOmar Sandoval /** 7534dbad5dSOmar Sandoval * blk_stat_alloc_callback() - Allocate a block statistics callback. 7634dbad5dSOmar Sandoval * @timer_fn: Timer callback function. 7734dbad5dSOmar Sandoval * @bucket_fn: Bucket callback function. 7834dbad5dSOmar Sandoval * @buckets: Number of statistics buckets. 7934dbad5dSOmar Sandoval * @data: Value for the @data field of the &struct blk_stat_callback. 8034dbad5dSOmar Sandoval * 8134dbad5dSOmar Sandoval * See &struct blk_stat_callback for details on the callback functions. 8234dbad5dSOmar Sandoval * 8334dbad5dSOmar Sandoval * Return: &struct blk_stat_callback on success or NULL on ENOMEM. 8434dbad5dSOmar Sandoval */ 8534dbad5dSOmar Sandoval struct blk_stat_callback * 8634dbad5dSOmar Sandoval blk_stat_alloc_callback(void (*timer_fn)(struct blk_stat_callback *), 87a37244e4SStephen Bates int (*bucket_fn)(const struct request *), 8834dbad5dSOmar Sandoval unsigned int buckets, void *data); 8934dbad5dSOmar Sandoval 9034dbad5dSOmar Sandoval /** 9134dbad5dSOmar Sandoval * blk_stat_add_callback() - Add a block statistics callback to be run on a 9234dbad5dSOmar Sandoval * request queue. 9334dbad5dSOmar Sandoval * @q: The request queue. 9434dbad5dSOmar Sandoval * @cb: The callback. 9534dbad5dSOmar Sandoval * 9634dbad5dSOmar Sandoval * Note that a single &struct blk_stat_callback can only be added to a single 9734dbad5dSOmar Sandoval * &struct request_queue. 9834dbad5dSOmar Sandoval */ 9934dbad5dSOmar Sandoval void blk_stat_add_callback(struct request_queue *q, 10034dbad5dSOmar Sandoval struct blk_stat_callback *cb); 10134dbad5dSOmar Sandoval 10234dbad5dSOmar Sandoval /** 10334dbad5dSOmar Sandoval * blk_stat_remove_callback() - Remove a block statistics callback from a 10434dbad5dSOmar Sandoval * request queue. 10534dbad5dSOmar Sandoval * @q: The request queue. 10634dbad5dSOmar Sandoval * @cb: The callback. 10734dbad5dSOmar Sandoval * 10834dbad5dSOmar Sandoval * When this returns, the callback is not running on any CPUs and will not be 10934dbad5dSOmar Sandoval * called again unless readded. 11034dbad5dSOmar Sandoval */ 11134dbad5dSOmar Sandoval void blk_stat_remove_callback(struct request_queue *q, 11234dbad5dSOmar Sandoval struct blk_stat_callback *cb); 11334dbad5dSOmar Sandoval 11434dbad5dSOmar Sandoval /** 11534dbad5dSOmar Sandoval * blk_stat_free_callback() - Free a block statistics callback. 11634dbad5dSOmar Sandoval * @cb: The callback. 11734dbad5dSOmar Sandoval * 11834dbad5dSOmar Sandoval * @cb may be NULL, in which case this does nothing. If it is not NULL, @cb must 11934dbad5dSOmar Sandoval * not be associated with a request queue. I.e., if it was previously added with 12034dbad5dSOmar Sandoval * blk_stat_add_callback(), it must also have been removed since then with 12134dbad5dSOmar Sandoval * blk_stat_remove_callback(). 12234dbad5dSOmar Sandoval */ 12334dbad5dSOmar Sandoval void blk_stat_free_callback(struct blk_stat_callback *cb); 12434dbad5dSOmar Sandoval 12534dbad5dSOmar Sandoval /** 12634dbad5dSOmar Sandoval * blk_stat_is_active() - Check if a block statistics callback is currently 12734dbad5dSOmar Sandoval * gathering statistics. 12834dbad5dSOmar Sandoval * @cb: The callback. 12934dbad5dSOmar Sandoval */ 13034dbad5dSOmar Sandoval static inline bool blk_stat_is_active(struct blk_stat_callback *cb) 13134dbad5dSOmar Sandoval { 13234dbad5dSOmar Sandoval return timer_pending(&cb->timer); 13334dbad5dSOmar Sandoval } 13434dbad5dSOmar Sandoval 13534dbad5dSOmar Sandoval /** 13634dbad5dSOmar Sandoval * blk_stat_activate_nsecs() - Gather block statistics during a time window in 13734dbad5dSOmar Sandoval * nanoseconds. 13834dbad5dSOmar Sandoval * @cb: The callback. 13934dbad5dSOmar Sandoval * @nsecs: Number of nanoseconds to gather statistics for. 14034dbad5dSOmar Sandoval * 14134dbad5dSOmar Sandoval * The timer callback will be called when the window expires. 14234dbad5dSOmar Sandoval */ 14334dbad5dSOmar Sandoval static inline void blk_stat_activate_nsecs(struct blk_stat_callback *cb, 14434dbad5dSOmar Sandoval u64 nsecs) 14534dbad5dSOmar Sandoval { 14634dbad5dSOmar Sandoval mod_timer(&cb->timer, jiffies + nsecs_to_jiffies(nsecs)); 14734dbad5dSOmar Sandoval } 14834dbad5dSOmar Sandoval 149544fbd16SMing Lei static inline void blk_stat_deactivate(struct blk_stat_callback *cb) 150544fbd16SMing Lei { 151544fbd16SMing Lei del_timer_sync(&cb->timer); 152544fbd16SMing Lei } 153544fbd16SMing Lei 15434dbad5dSOmar Sandoval /** 15534dbad5dSOmar Sandoval * blk_stat_activate_msecs() - Gather block statistics during a time window in 15634dbad5dSOmar Sandoval * milliseconds. 15734dbad5dSOmar Sandoval * @cb: The callback. 15834dbad5dSOmar Sandoval * @msecs: Number of milliseconds to gather statistics for. 15934dbad5dSOmar Sandoval * 16034dbad5dSOmar Sandoval * The timer callback will be called when the window expires. 16134dbad5dSOmar Sandoval */ 16234dbad5dSOmar Sandoval static inline void blk_stat_activate_msecs(struct blk_stat_callback *cb, 16334dbad5dSOmar Sandoval unsigned int msecs) 16434dbad5dSOmar Sandoval { 16534dbad5dSOmar Sandoval mod_timer(&cb->timer, jiffies + msecs_to_jiffies(msecs)); 16634dbad5dSOmar Sandoval } 16734dbad5dSOmar Sandoval 1682ecbf456SJosef Bacik void blk_rq_stat_add(struct blk_rq_stat *, u64); 1692ecbf456SJosef Bacik void blk_rq_stat_sum(struct blk_rq_stat *, struct blk_rq_stat *); 1702ecbf456SJosef Bacik void blk_rq_stat_init(struct blk_rq_stat *); 1712ecbf456SJosef Bacik 172cf43e6beSJens Axboe #endif 173