162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef BLKTRACE_H 362306a36Sopenharmony_ci#define BLKTRACE_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/blk-mq.h> 662306a36Sopenharmony_ci#include <linux/relay.h> 762306a36Sopenharmony_ci#include <linux/compat.h> 862306a36Sopenharmony_ci#include <uapi/linux/blktrace_api.h> 962306a36Sopenharmony_ci#include <linux/list.h> 1062306a36Sopenharmony_ci#include <linux/blk_types.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#if defined(CONFIG_BLK_DEV_IO_TRACE) 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/sysfs.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistruct blk_trace { 1762306a36Sopenharmony_ci int trace_state; 1862306a36Sopenharmony_ci struct rchan *rchan; 1962306a36Sopenharmony_ci unsigned long __percpu *sequence; 2062306a36Sopenharmony_ci unsigned char __percpu *msg_data; 2162306a36Sopenharmony_ci u16 act_mask; 2262306a36Sopenharmony_ci u64 start_lba; 2362306a36Sopenharmony_ci u64 end_lba; 2462306a36Sopenharmony_ci u32 pid; 2562306a36Sopenharmony_ci u32 dev; 2662306a36Sopenharmony_ci struct dentry *dir; 2762306a36Sopenharmony_ci struct list_head running_list; 2862306a36Sopenharmony_ci atomic_t dropped; 2962306a36Sopenharmony_ci}; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ciextern int blk_trace_ioctl(struct block_device *, unsigned, char __user *); 3262306a36Sopenharmony_ciextern void blk_trace_shutdown(struct request_queue *); 3362306a36Sopenharmony_ci__printf(3, 4) void __blk_trace_note_message(struct blk_trace *bt, 3462306a36Sopenharmony_ci struct cgroup_subsys_state *css, const char *fmt, ...); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/** 3762306a36Sopenharmony_ci * blk_add_trace_msg - Add a (simple) message to the blktrace stream 3862306a36Sopenharmony_ci * @q: queue the io is for 3962306a36Sopenharmony_ci * @fmt: format to print message in 4062306a36Sopenharmony_ci * args... Variable argument list for format 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci * Description: 4362306a36Sopenharmony_ci * Records a (simple) message onto the blktrace stream. 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci * NOTE: BLK_TN_MAX_MSG characters are output at most. 4662306a36Sopenharmony_ci * NOTE: Can not use 'static inline' due to presence of var args... 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci **/ 4962306a36Sopenharmony_ci#define blk_add_cgroup_trace_msg(q, css, fmt, ...) \ 5062306a36Sopenharmony_ci do { \ 5162306a36Sopenharmony_ci struct blk_trace *bt; \ 5262306a36Sopenharmony_ci \ 5362306a36Sopenharmony_ci rcu_read_lock(); \ 5462306a36Sopenharmony_ci bt = rcu_dereference((q)->blk_trace); \ 5562306a36Sopenharmony_ci if (unlikely(bt)) \ 5662306a36Sopenharmony_ci __blk_trace_note_message(bt, css, fmt, ##__VA_ARGS__);\ 5762306a36Sopenharmony_ci rcu_read_unlock(); \ 5862306a36Sopenharmony_ci } while (0) 5962306a36Sopenharmony_ci#define blk_add_trace_msg(q, fmt, ...) \ 6062306a36Sopenharmony_ci blk_add_cgroup_trace_msg(q, NULL, fmt, ##__VA_ARGS__) 6162306a36Sopenharmony_ci#define BLK_TN_MAX_MSG 128 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic inline bool blk_trace_note_message_enabled(struct request_queue *q) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci struct blk_trace *bt; 6662306a36Sopenharmony_ci bool ret; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci rcu_read_lock(); 6962306a36Sopenharmony_ci bt = rcu_dereference(q->blk_trace); 7062306a36Sopenharmony_ci ret = bt && (bt->act_mask & BLK_TC_NOTIFY); 7162306a36Sopenharmony_ci rcu_read_unlock(); 7262306a36Sopenharmony_ci return ret; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ciextern void blk_add_driver_data(struct request *rq, void *data, size_t len); 7662306a36Sopenharmony_ciextern int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, 7762306a36Sopenharmony_ci struct block_device *bdev, 7862306a36Sopenharmony_ci char __user *arg); 7962306a36Sopenharmony_ciextern int blk_trace_startstop(struct request_queue *q, int start); 8062306a36Sopenharmony_ciextern int blk_trace_remove(struct request_queue *q); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#else /* !CONFIG_BLK_DEV_IO_TRACE */ 8362306a36Sopenharmony_ci# define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY) 8462306a36Sopenharmony_ci# define blk_trace_shutdown(q) do { } while (0) 8562306a36Sopenharmony_ci# define blk_add_driver_data(rq, data, len) do {} while (0) 8662306a36Sopenharmony_ci# define blk_trace_setup(q, name, dev, bdev, arg) (-ENOTTY) 8762306a36Sopenharmony_ci# define blk_trace_startstop(q, start) (-ENOTTY) 8862306a36Sopenharmony_ci# define blk_add_trace_msg(q, fmt, ...) do { } while (0) 8962306a36Sopenharmony_ci# define blk_add_cgroup_trace_msg(q, cg, fmt, ...) do { } while (0) 9062306a36Sopenharmony_ci# define blk_trace_note_message_enabled(q) (false) 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic inline int blk_trace_remove(struct request_queue *q) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci return -ENOTTY; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci#endif /* CONFIG_BLK_DEV_IO_TRACE */ 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistruct compat_blk_user_trace_setup { 10162306a36Sopenharmony_ci char name[BLKTRACE_BDEV_SIZE]; 10262306a36Sopenharmony_ci u16 act_mask; 10362306a36Sopenharmony_ci u32 buf_size; 10462306a36Sopenharmony_ci u32 buf_nr; 10562306a36Sopenharmony_ci compat_u64 start_lba; 10662306a36Sopenharmony_ci compat_u64 end_lba; 10762306a36Sopenharmony_ci u32 pid; 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ci#define BLKTRACESETUP32 _IOWR(0x12, 115, struct compat_blk_user_trace_setup) 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci#endif 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_civoid blk_fill_rwbs(char *rwbs, blk_opf_t opf); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic inline sector_t blk_rq_trace_sector(struct request *rq) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci /* 11862306a36Sopenharmony_ci * Tracing should ignore starting sector for passthrough requests and 11962306a36Sopenharmony_ci * requests where starting sector didn't get set. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ci if (blk_rq_is_passthrough(rq) || blk_rq_pos(rq) == (sector_t)-1) 12262306a36Sopenharmony_ci return 0; 12362306a36Sopenharmony_ci return blk_rq_pos(rq); 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic inline unsigned int blk_rq_trace_nr_sectors(struct request *rq) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci return blk_rq_is_passthrough(rq) ? 0 : blk_rq_sectors(rq); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci#endif 132