162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef BLK_STAT_H 362306a36Sopenharmony_ci#define BLK_STAT_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/kernel.h> 662306a36Sopenharmony_ci#include <linux/blkdev.h> 762306a36Sopenharmony_ci#include <linux/ktime.h> 862306a36Sopenharmony_ci#include <linux/rcupdate.h> 962306a36Sopenharmony_ci#include <linux/timer.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/** 1262306a36Sopenharmony_ci * struct blk_stat_callback - Block statistics callback. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * A &struct blk_stat_callback is associated with a &struct request_queue. While 1562306a36Sopenharmony_ci * @timer is active, that queue's request completion latencies are sorted into 1662306a36Sopenharmony_ci * buckets by @bucket_fn and added to a per-cpu buffer, @cpu_stat. When the 1762306a36Sopenharmony_ci * timer fires, @cpu_stat is flushed to @stat and @timer_fn is invoked. 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_cistruct blk_stat_callback { 2062306a36Sopenharmony_ci /* 2162306a36Sopenharmony_ci * @list: RCU list of callbacks for a &struct request_queue. 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci struct list_head list; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci /** 2662306a36Sopenharmony_ci * @timer: Timer for the next callback invocation. 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ci struct timer_list timer; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci /** 3162306a36Sopenharmony_ci * @cpu_stat: Per-cpu statistics buckets. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci struct blk_rq_stat __percpu *cpu_stat; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci /** 3662306a36Sopenharmony_ci * @bucket_fn: Given a request, returns which statistics bucket it 3762306a36Sopenharmony_ci * should be accounted under. Return -1 for no bucket for this 3862306a36Sopenharmony_ci * request. 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_ci int (*bucket_fn)(const struct request *); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci /** 4362306a36Sopenharmony_ci * @buckets: Number of statistics buckets. 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_ci unsigned int buckets; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci /** 4862306a36Sopenharmony_ci * @stat: Array of statistics buckets. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_ci struct blk_rq_stat *stat; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci /** 5362306a36Sopenharmony_ci * @fn: Callback function. 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_ci void (*timer_fn)(struct blk_stat_callback *); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci /** 5862306a36Sopenharmony_ci * @data: Private pointer for the user. 5962306a36Sopenharmony_ci */ 6062306a36Sopenharmony_ci void *data; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci struct rcu_head rcu; 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistruct blk_queue_stats *blk_alloc_queue_stats(void); 6662306a36Sopenharmony_civoid blk_free_queue_stats(struct blk_queue_stats *); 6762306a36Sopenharmony_cibool blk_stats_alloc_enable(struct request_queue *q); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_civoid blk_stat_add(struct request *rq, u64 now); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* record time/size info in request but not add a callback */ 7262306a36Sopenharmony_civoid blk_stat_enable_accounting(struct request_queue *q); 7362306a36Sopenharmony_civoid blk_stat_disable_accounting(struct request_queue *q); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/** 7662306a36Sopenharmony_ci * blk_stat_alloc_callback() - Allocate a block statistics callback. 7762306a36Sopenharmony_ci * @timer_fn: Timer callback function. 7862306a36Sopenharmony_ci * @bucket_fn: Bucket callback function. 7962306a36Sopenharmony_ci * @buckets: Number of statistics buckets. 8062306a36Sopenharmony_ci * @data: Value for the @data field of the &struct blk_stat_callback. 8162306a36Sopenharmony_ci * 8262306a36Sopenharmony_ci * See &struct blk_stat_callback for details on the callback functions. 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * Return: &struct blk_stat_callback on success or NULL on ENOMEM. 8562306a36Sopenharmony_ci */ 8662306a36Sopenharmony_cistruct blk_stat_callback * 8762306a36Sopenharmony_ciblk_stat_alloc_callback(void (*timer_fn)(struct blk_stat_callback *), 8862306a36Sopenharmony_ci int (*bucket_fn)(const struct request *), 8962306a36Sopenharmony_ci unsigned int buckets, void *data); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/** 9262306a36Sopenharmony_ci * blk_stat_add_callback() - Add a block statistics callback to be run on a 9362306a36Sopenharmony_ci * request queue. 9462306a36Sopenharmony_ci * @q: The request queue. 9562306a36Sopenharmony_ci * @cb: The callback. 9662306a36Sopenharmony_ci * 9762306a36Sopenharmony_ci * Note that a single &struct blk_stat_callback can only be added to a single 9862306a36Sopenharmony_ci * &struct request_queue. 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_civoid blk_stat_add_callback(struct request_queue *q, 10162306a36Sopenharmony_ci struct blk_stat_callback *cb); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci/** 10462306a36Sopenharmony_ci * blk_stat_remove_callback() - Remove a block statistics callback from a 10562306a36Sopenharmony_ci * request queue. 10662306a36Sopenharmony_ci * @q: The request queue. 10762306a36Sopenharmony_ci * @cb: The callback. 10862306a36Sopenharmony_ci * 10962306a36Sopenharmony_ci * When this returns, the callback is not running on any CPUs and will not be 11062306a36Sopenharmony_ci * called again unless readded. 11162306a36Sopenharmony_ci */ 11262306a36Sopenharmony_civoid blk_stat_remove_callback(struct request_queue *q, 11362306a36Sopenharmony_ci struct blk_stat_callback *cb); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/** 11662306a36Sopenharmony_ci * blk_stat_free_callback() - Free a block statistics callback. 11762306a36Sopenharmony_ci * @cb: The callback. 11862306a36Sopenharmony_ci * 11962306a36Sopenharmony_ci * @cb may be NULL, in which case this does nothing. If it is not NULL, @cb must 12062306a36Sopenharmony_ci * not be associated with a request queue. I.e., if it was previously added with 12162306a36Sopenharmony_ci * blk_stat_add_callback(), it must also have been removed since then with 12262306a36Sopenharmony_ci * blk_stat_remove_callback(). 12362306a36Sopenharmony_ci */ 12462306a36Sopenharmony_civoid blk_stat_free_callback(struct blk_stat_callback *cb); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci/** 12762306a36Sopenharmony_ci * blk_stat_is_active() - Check if a block statistics callback is currently 12862306a36Sopenharmony_ci * gathering statistics. 12962306a36Sopenharmony_ci * @cb: The callback. 13062306a36Sopenharmony_ci */ 13162306a36Sopenharmony_cistatic inline bool blk_stat_is_active(struct blk_stat_callback *cb) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci return timer_pending(&cb->timer); 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci/** 13762306a36Sopenharmony_ci * blk_stat_activate_nsecs() - Gather block statistics during a time window in 13862306a36Sopenharmony_ci * nanoseconds. 13962306a36Sopenharmony_ci * @cb: The callback. 14062306a36Sopenharmony_ci * @nsecs: Number of nanoseconds to gather statistics for. 14162306a36Sopenharmony_ci * 14262306a36Sopenharmony_ci * The timer callback will be called when the window expires. 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_cistatic inline void blk_stat_activate_nsecs(struct blk_stat_callback *cb, 14562306a36Sopenharmony_ci u64 nsecs) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci mod_timer(&cb->timer, jiffies + nsecs_to_jiffies(nsecs)); 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cistatic inline void blk_stat_deactivate(struct blk_stat_callback *cb) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci del_timer_sync(&cb->timer); 15362306a36Sopenharmony_ci} 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci/** 15662306a36Sopenharmony_ci * blk_stat_activate_msecs() - Gather block statistics during a time window in 15762306a36Sopenharmony_ci * milliseconds. 15862306a36Sopenharmony_ci * @cb: The callback. 15962306a36Sopenharmony_ci * @msecs: Number of milliseconds to gather statistics for. 16062306a36Sopenharmony_ci * 16162306a36Sopenharmony_ci * The timer callback will be called when the window expires. 16262306a36Sopenharmony_ci */ 16362306a36Sopenharmony_cistatic inline void blk_stat_activate_msecs(struct blk_stat_callback *cb, 16462306a36Sopenharmony_ci unsigned int msecs) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci mod_timer(&cb->timer, jiffies + msecs_to_jiffies(msecs)); 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_civoid blk_rq_stat_add(struct blk_rq_stat *, u64); 17062306a36Sopenharmony_civoid blk_rq_stat_sum(struct blk_rq_stat *, struct blk_rq_stat *); 17162306a36Sopenharmony_civoid blk_rq_stat_init(struct blk_rq_stat *); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci#endif 174