xref: /linux/tools/testing/selftests/ublk/kublk.h (revision 6d8854216ebb60959ddb6f4ea4123bd449ba6cf6)
16aecda00SMing Lei /* SPDX-License-Identifier: GPL-2.0 */
26aecda00SMing Lei #ifndef KUBLK_INTERNAL_H
36aecda00SMing Lei #define KUBLK_INTERNAL_H
46aecda00SMing Lei 
56aecda00SMing Lei #include <unistd.h>
66aecda00SMing Lei #include <stdlib.h>
76aecda00SMing Lei #include <assert.h>
86aecda00SMing Lei #include <stdio.h>
96aecda00SMing Lei #include <stdarg.h>
106aecda00SMing Lei #include <string.h>
116aecda00SMing Lei #include <pthread.h>
126aecda00SMing Lei #include <getopt.h>
136aecda00SMing Lei #include <limits.h>
146aecda00SMing Lei #include <poll.h>
159d80f48cSMing Lei #include <fcntl.h>
166aecda00SMing Lei #include <sys/syscall.h>
176aecda00SMing Lei #include <sys/mman.h>
186aecda00SMing Lei #include <sys/ioctl.h>
196aecda00SMing Lei #include <sys/inotify.h>
206aecda00SMing Lei #include <sys/wait.h>
216aecda00SMing Lei #include <sys/eventfd.h>
222f0a692aSMing Lei #include <sys/ipc.h>
232f0a692aSMing Lei #include <sys/shm.h>
249cad26d6SMing Lei #include <linux/io_uring.h>
256aecda00SMing Lei #include <liburing.h>
262f0a692aSMing Lei #include <semaphore.h>
272f0a692aSMing Lei 
282f0a692aSMing Lei /* allow ublk_dep.h to override ublk_cmd.h */
298764c1a7SMing Lei #include "ublk_dep.h"
302f0a692aSMing Lei #include <linux/ublk_cmd.h>
316aecda00SMing Lei 
326aecda00SMing Lei #define __maybe_unused __attribute__((unused))
336aecda00SMing Lei #define MAX_BACK_FILES   4
346aecda00SMing Lei #ifndef min
356aecda00SMing Lei #define min(a, b) ((a) < (b) ? (a) : (b))
366aecda00SMing Lei #endif
376aecda00SMing Lei 
38ec120093SMing Lei #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
39ec120093SMing Lei 
406aecda00SMing Lei /****************** part 1: libublk ********************/
416aecda00SMing Lei 
426aecda00SMing Lei #define CTRL_DEV		"/dev/ublk-control"
436aecda00SMing Lei #define UBLKC_DEV		"/dev/ublkc"
446aecda00SMing Lei #define UBLKB_DEV		"/dev/ublkb"
456aecda00SMing Lei #define UBLK_CTRL_RING_DEPTH            32
466aecda00SMing Lei #define ERROR_EVTFD_DEVID 	-2
476aecda00SMing Lei 
486aecda00SMing Lei /* queue idle timeout */
496aecda00SMing Lei #define UBLKSRV_IO_IDLE_SECS		20
506aecda00SMing Lei 
519413c0caSMing Lei #define UBLK_IO_MAX_BYTES               (1 << 20)
52bf098d72SUday Shankar #define UBLK_MAX_QUEUES_SHIFT		5
53bf098d72SUday Shankar #define UBLK_MAX_QUEUES                 (1 << UBLK_MAX_QUEUES_SHIFT)
54b9848ca7SUday Shankar #define UBLK_MAX_THREADS_SHIFT		5
55b9848ca7SUday Shankar #define UBLK_MAX_THREADS		(1 << UBLK_MAX_THREADS_SHIFT)
566c62fd04SMing Lei #define UBLK_QUEUE_DEPTH                1024
576aecda00SMing Lei 
586aecda00SMing Lei #define UBLK_DBG_DEV            (1U << 0)
59b9848ca7SUday Shankar #define UBLK_DBG_THREAD         (1U << 1)
606aecda00SMing Lei #define UBLK_DBG_IO_CMD         (1U << 2)
616aecda00SMing Lei #define UBLK_DBG_IO             (1U << 3)
626aecda00SMing Lei #define UBLK_DBG_CTRL_CMD       (1U << 4)
636aecda00SMing Lei #define UBLK_LOG                (1U << 5)
646aecda00SMing Lei 
656aecda00SMing Lei struct ublk_dev;
666aecda00SMing Lei struct ublk_queue;
67b9848ca7SUday Shankar struct ublk_thread;
686aecda00SMing Lei 
69810b88f3SMing Lei struct stripe_ctx {
70810b88f3SMing Lei 	/* stripe */
71810b88f3SMing Lei 	unsigned int    chunk_size;
72810b88f3SMing Lei };
73810b88f3SMing Lei 
7481586652SUday Shankar struct fault_inject_ctx {
7581586652SUday Shankar 	/* fault_inject */
7681586652SUday Shankar 	unsigned long   delay_us;
7781586652SUday Shankar };
7881586652SUday Shankar 
796aecda00SMing Lei struct dev_ctx {
806aecda00SMing Lei 	char tgt_type[16];
816aecda00SMing Lei 	unsigned long flags;
826aecda00SMing Lei 	unsigned nr_hw_queues;
83*abe54c16SUday Shankar 	unsigned short nthreads;
846aecda00SMing Lei 	unsigned queue_depth;
856aecda00SMing Lei 	int dev_id;
866aecda00SMing Lei 	int nr_files;
876aecda00SMing Lei 	char *files[MAX_BACK_FILES];
886aecda00SMing Lei 	unsigned int	logging:1;
896aecda00SMing Lei 	unsigned int	all:1;
902ecdcdfeSMing Lei 	unsigned int	fg:1;
9157e13a2eSMing Lei 	unsigned int	recovery:1;
926f1a182aSMing Lei 	unsigned int	auto_zc_fallback:1;
93*abe54c16SUday Shankar 	unsigned int	per_io_tasks:1;
946aecda00SMing Lei 
956aecda00SMing Lei 	int _evtfd;
962f0a692aSMing Lei 	int _shmid;
972f0a692aSMing Lei 
982f0a692aSMing Lei 	/* built from shmem, only for ublk_dump_dev() */
992f0a692aSMing Lei 	struct ublk_dev *shadow_dev;
100810b88f3SMing Lei 
101f40b1f26SMing Lei 	/* for 'update_size' command */
102f40b1f26SMing Lei 	unsigned long long size;
103f40b1f26SMing Lei 
104810b88f3SMing Lei 	union {
105810b88f3SMing Lei 		struct stripe_ctx 	stripe;
10681586652SUday Shankar 		struct fault_inject_ctx fault_inject;
107810b88f3SMing Lei 	};
1086aecda00SMing Lei };
1096aecda00SMing Lei 
1106aecda00SMing Lei struct ublk_ctrl_cmd_data {
1116aecda00SMing Lei 	__u32 cmd_op;
1126aecda00SMing Lei #define CTRL_CMD_HAS_DATA	1
1136aecda00SMing Lei #define CTRL_CMD_HAS_BUF	2
1146aecda00SMing Lei 	__u32 flags;
1156aecda00SMing Lei 
1166aecda00SMing Lei 	__u64 data[2];
1176aecda00SMing Lei 	__u64 addr;
1186aecda00SMing Lei 	__u32 len;
1196aecda00SMing Lei };
1206aecda00SMing Lei 
1216aecda00SMing Lei struct ublk_io {
1226aecda00SMing Lei 	char *buf_addr;
1236aecda00SMing Lei 
1246aecda00SMing Lei #define UBLKSRV_NEED_FETCH_RQ		(1UL << 0)
1256aecda00SMing Lei #define UBLKSRV_NEED_COMMIT_RQ_COMP	(1UL << 1)
1266aecda00SMing Lei #define UBLKSRV_IO_FREE			(1UL << 2)
127730d8379SMing Lei #define UBLKSRV_NEED_GET_DATA           (1UL << 3)
1288ccebc19SMing Lei #define UBLKSRV_NEED_REG_BUF            (1UL << 4)
1296aecda00SMing Lei 	unsigned short flags;
1306aecda00SMing Lei 	unsigned short refs;		/* used by target code only */
1316aecda00SMing Lei 
13297737097SUday Shankar 	int tag;
13397737097SUday Shankar 
1346aecda00SMing Lei 	int result;
1358842b72aSMing Lei 
136*abe54c16SUday Shankar 	unsigned short buf_index;
1378842b72aSMing Lei 	unsigned short tgt_ios;
1388842b72aSMing Lei 	void *private_data;
139b9848ca7SUday Shankar 	struct ublk_thread *t;
1406aecda00SMing Lei };
1416aecda00SMing Lei 
1426aecda00SMing Lei struct ublk_tgt_ops {
1436aecda00SMing Lei 	const char *name;
1448842b72aSMing Lei 	int (*init_tgt)(const struct dev_ctx *ctx, struct ublk_dev *);
1456aecda00SMing Lei 	void (*deinit_tgt)(struct ublk_dev *);
1466aecda00SMing Lei 
1476aecda00SMing Lei 	int (*queue_io)(struct ublk_queue *, int tag);
1486aecda00SMing Lei 	void (*tgt_io_done)(struct ublk_queue *,
1496aecda00SMing Lei 			int tag, const struct io_uring_cqe *);
150810b88f3SMing Lei 
151810b88f3SMing Lei 	/*
152810b88f3SMing Lei 	 * Target specific command line handling
153810b88f3SMing Lei 	 *
154810b88f3SMing Lei 	 * each option requires argument for target command line
155810b88f3SMing Lei 	 */
156810b88f3SMing Lei 	void (*parse_cmd_line)(struct dev_ctx *ctx, int argc, char *argv[]);
157810b88f3SMing Lei 	void (*usage)(const struct ublk_tgt_ops *ops);
1586f1a182aSMing Lei 
1596f1a182aSMing Lei 	/* return buffer index for UBLK_F_AUTO_BUF_REG */
1606f1a182aSMing Lei 	unsigned short (*buf_index)(const struct ublk_queue *, int tag);
1616aecda00SMing Lei };
1626aecda00SMing Lei 
1636aecda00SMing Lei struct ublk_tgt {
1646aecda00SMing Lei 	unsigned long dev_size;
1656aecda00SMing Lei 	unsigned int  sq_depth;
1666aecda00SMing Lei 	unsigned int  cq_depth;
1676aecda00SMing Lei 	const struct ublk_tgt_ops *ops;
1686aecda00SMing Lei 	struct ublk_params params;
1695d95bfb5SMing Lei 
1705d95bfb5SMing Lei 	int nr_backing_files;
1715d95bfb5SMing Lei 	unsigned long backing_file_size[MAX_BACK_FILES];
1725d95bfb5SMing Lei 	char backing_file[MAX_BACK_FILES][PATH_MAX];
1736aecda00SMing Lei };
1746aecda00SMing Lei 
1756aecda00SMing Lei struct ublk_queue {
1766aecda00SMing Lei 	int q_id;
1776aecda00SMing Lei 	int q_depth;
1786aecda00SMing Lei 	struct ublk_dev *dev;
1796aecda00SMing Lei 	const struct ublk_tgt_ops *tgt_ops;
18025aaa813SCaleb Sander Mateos 	struct ublksrv_io_desc *io_cmd_buf;
181b9848ca7SUday Shankar 
1826aecda00SMing Lei 	struct ublk_io ios[UBLK_QUEUE_DEPTH];
1836aecda00SMing Lei #define UBLKSRV_NO_BUF		(1U << 2)
184bedc9cbcSMing Lei #define UBLKSRV_ZC		(1U << 3)
1858ccebc19SMing Lei #define UBLKSRV_AUTO_BUF_REG		(1U << 4)
1866f1a182aSMing Lei #define UBLKSRV_AUTO_BUF_REG_FALLBACK	(1U << 5)
1876aecda00SMing Lei 	unsigned state;
188b9848ca7SUday Shankar };
189b9848ca7SUday Shankar 
190b9848ca7SUday Shankar struct ublk_thread {
191b9848ca7SUday Shankar 	struct ublk_dev *dev;
192b9848ca7SUday Shankar 	struct io_uring ring;
193b9848ca7SUday Shankar 	unsigned int cmd_inflight;
194b9848ca7SUday Shankar 	unsigned int io_inflight;
195b9848ca7SUday Shankar 
1966aecda00SMing Lei 	pthread_t thread;
197b9848ca7SUday Shankar 	unsigned idx;
198b9848ca7SUday Shankar 
199b9848ca7SUday Shankar #define UBLKSRV_THREAD_STOPPING	(1U << 0)
200b9848ca7SUday Shankar #define UBLKSRV_THREAD_IDLE	(1U << 1)
201b9848ca7SUday Shankar 	unsigned state;
2026aecda00SMing Lei };
2036aecda00SMing Lei 
2046aecda00SMing Lei struct ublk_dev {
2056aecda00SMing Lei 	struct ublk_tgt tgt;
2066aecda00SMing Lei 	struct ublksrv_ctrl_dev_info  dev_info;
2076aecda00SMing Lei 	struct ublk_queue q[UBLK_MAX_QUEUES];
208b9848ca7SUday Shankar 	struct ublk_thread threads[UBLK_MAX_THREADS];
209*abe54c16SUday Shankar 	unsigned nthreads;
210*abe54c16SUday Shankar 	unsigned per_io_tasks;
2116aecda00SMing Lei 
2125d95bfb5SMing Lei 	int fds[MAX_BACK_FILES + 1];	/* fds[0] points to /dev/ublkcN */
2136aecda00SMing Lei 	int nr_fds;
2146aecda00SMing Lei 	int ctrl_fd;
2156aecda00SMing Lei 	struct io_uring ring;
2168842b72aSMing Lei 
2178842b72aSMing Lei 	void *private_data;
2186aecda00SMing Lei };
2196aecda00SMing Lei 
2206aecda00SMing Lei #ifndef offsetof
2216aecda00SMing Lei #define offsetof(TYPE, MEMBER)  ((size_t)&((TYPE *)0)->MEMBER)
2226aecda00SMing Lei #endif
2236aecda00SMing Lei 
2246aecda00SMing Lei #ifndef container_of
2256aecda00SMing Lei #define container_of(ptr, type, member) ({                              \
2266aecda00SMing Lei 	unsigned long __mptr = (unsigned long)(ptr);                    \
2276aecda00SMing Lei 	((type *)(__mptr - offsetof(type, member))); })
2286aecda00SMing Lei #endif
2296aecda00SMing Lei 
2306aecda00SMing Lei #define round_up(val, rnd) \
2316aecda00SMing Lei 	(((val) + ((rnd) - 1)) & ~((rnd) - 1))
2326aecda00SMing Lei 
2336aecda00SMing Lei 
2346aecda00SMing Lei extern unsigned int ublk_dbg_mask;
235b9848ca7SUday Shankar extern int ublk_queue_io_cmd(struct ublk_io *io);
2366aecda00SMing Lei 
2376f1a182aSMing Lei 
ublk_io_auto_zc_fallback(const struct ublksrv_io_desc * iod)2386f1a182aSMing Lei static inline int ublk_io_auto_zc_fallback(const struct ublksrv_io_desc *iod)
2396f1a182aSMing Lei {
2406f1a182aSMing Lei 	return !!(iod->op_flags & UBLK_IO_F_NEED_REG_BUF);
2416f1a182aSMing Lei }
2426f1a182aSMing Lei 
is_target_io(__u64 user_data)2436aecda00SMing Lei static inline int is_target_io(__u64 user_data)
2446aecda00SMing Lei {
2456aecda00SMing Lei 	return (user_data & (1ULL << 63)) != 0;
2466aecda00SMing Lei }
2476aecda00SMing Lei 
build_user_data(unsigned tag,unsigned op,unsigned tgt_data,unsigned q_id,unsigned is_target_io)2486aecda00SMing Lei static inline __u64 build_user_data(unsigned tag, unsigned op,
249bf098d72SUday Shankar 		unsigned tgt_data, unsigned q_id, unsigned is_target_io)
2506aecda00SMing Lei {
251bf098d72SUday Shankar 	/* we only have 7 bits to encode q_id */
252bf098d72SUday Shankar 	_Static_assert(UBLK_MAX_QUEUES_SHIFT <= 7);
253bf098d72SUday Shankar 	assert(!(tag >> 16) && !(op >> 8) && !(tgt_data >> 16) && !(q_id >> 7));
2546aecda00SMing Lei 
255bf098d72SUday Shankar 	return tag | (op << 16) | (tgt_data << 24) |
256bf098d72SUday Shankar 		(__u64)q_id << 56 | (__u64)is_target_io << 63;
2576aecda00SMing Lei }
2586aecda00SMing Lei 
user_data_to_tag(__u64 user_data)2596aecda00SMing Lei static inline unsigned int user_data_to_tag(__u64 user_data)
2606aecda00SMing Lei {
2616aecda00SMing Lei 	return user_data & 0xffff;
2626aecda00SMing Lei }
2636aecda00SMing Lei 
user_data_to_op(__u64 user_data)2646aecda00SMing Lei static inline unsigned int user_data_to_op(__u64 user_data)
2656aecda00SMing Lei {
2666aecda00SMing Lei 	return (user_data >> 16) & 0xff;
2676aecda00SMing Lei }
2686aecda00SMing Lei 
user_data_to_tgt_data(__u64 user_data)269bedc9cbcSMing Lei static inline unsigned int user_data_to_tgt_data(__u64 user_data)
270bedc9cbcSMing Lei {
271bedc9cbcSMing Lei 	return (user_data >> 24) & 0xffff;
272bedc9cbcSMing Lei }
273bedc9cbcSMing Lei 
user_data_to_q_id(__u64 user_data)274bf098d72SUday Shankar static inline unsigned int user_data_to_q_id(__u64 user_data)
275bf098d72SUday Shankar {
276bf098d72SUday Shankar 	return (user_data >> 56) & 0x7f;
277bf098d72SUday Shankar }
278bf098d72SUday Shankar 
ublk_cmd_op_nr(unsigned int op)2798cb9b971SMing Lei static inline unsigned short ublk_cmd_op_nr(unsigned int op)
2808cb9b971SMing Lei {
2818cb9b971SMing Lei 	return _IOC_NR(op);
2828cb9b971SMing Lei }
2838cb9b971SMing Lei 
ublk_err(const char * fmt,...)2846aecda00SMing Lei static inline void ublk_err(const char *fmt, ...)
2856aecda00SMing Lei {
2866aecda00SMing Lei 	va_list ap;
2876aecda00SMing Lei 
2886aecda00SMing Lei 	va_start(ap, fmt);
2896aecda00SMing Lei 	vfprintf(stderr, fmt, ap);
2906aecda00SMing Lei }
2916aecda00SMing Lei 
ublk_log(const char * fmt,...)2926aecda00SMing Lei static inline void ublk_log(const char *fmt, ...)
2936aecda00SMing Lei {
2946aecda00SMing Lei 	if (ublk_dbg_mask & UBLK_LOG) {
2956aecda00SMing Lei 		va_list ap;
2966aecda00SMing Lei 
2976aecda00SMing Lei 		va_start(ap, fmt);
2986aecda00SMing Lei 		vfprintf(stdout, fmt, ap);
2996aecda00SMing Lei 	}
3006aecda00SMing Lei }
3016aecda00SMing Lei 
ublk_dbg(int level,const char * fmt,...)3026aecda00SMing Lei static inline void ublk_dbg(int level, const char *fmt, ...)
3036aecda00SMing Lei {
3046aecda00SMing Lei 	if (level & ublk_dbg_mask) {
3056aecda00SMing Lei 		va_list ap;
3066aecda00SMing Lei 
3076aecda00SMing Lei 		va_start(ap, fmt);
3086aecda00SMing Lei 		vfprintf(stdout, fmt, ap);
3096aecda00SMing Lei 	}
3106aecda00SMing Lei }
3116aecda00SMing Lei 
ublk_io_to_queue(const struct ublk_io * io)31297737097SUday Shankar static inline struct ublk_queue *ublk_io_to_queue(const struct ublk_io *io)
31397737097SUday Shankar {
31497737097SUday Shankar 	return container_of(io, struct ublk_queue, ios[io->tag]);
31597737097SUday Shankar }
31697737097SUday Shankar 
ublk_io_alloc_sqes(struct ublk_io * io,struct io_uring_sqe * sqes[],int nr_sqes)31797737097SUday Shankar static inline int ublk_io_alloc_sqes(struct ublk_io *io,
318f2639ed1SMing Lei 		struct io_uring_sqe *sqes[], int nr_sqes)
3196aecda00SMing Lei {
320b9848ca7SUday Shankar 	struct io_uring *ring = &io->t->ring;
32197737097SUday Shankar 	unsigned left = io_uring_sq_space_left(ring);
322f2639ed1SMing Lei 	int i;
3236aecda00SMing Lei 
324f2639ed1SMing Lei 	if (left < nr_sqes)
32597737097SUday Shankar 		io_uring_submit(ring);
326f2639ed1SMing Lei 
327f2639ed1SMing Lei 	for (i = 0; i < nr_sqes; i++) {
32897737097SUday Shankar 		sqes[i] = io_uring_get_sqe(ring);
329f2639ed1SMing Lei 		if (!sqes[i])
330f2639ed1SMing Lei 			return i;
3316aecda00SMing Lei 	}
3326aecda00SMing Lei 
333f2639ed1SMing Lei 	return nr_sqes;
334bedc9cbcSMing Lei }
335bedc9cbcSMing Lei 
io_uring_prep_buf_register(struct io_uring_sqe * sqe,int dev_fd,int tag,int q_id,__u64 index)336bedc9cbcSMing Lei static inline void io_uring_prep_buf_register(struct io_uring_sqe *sqe,
337bedc9cbcSMing Lei 		int dev_fd, int tag, int q_id, __u64 index)
338bedc9cbcSMing Lei {
339bedc9cbcSMing Lei 	struct ublksrv_io_cmd *cmd = (struct ublksrv_io_cmd *)sqe->cmd;
340bedc9cbcSMing Lei 
341bedc9cbcSMing Lei 	io_uring_prep_read(sqe, dev_fd, 0, 0, 0);
342bedc9cbcSMing Lei 	sqe->opcode		= IORING_OP_URING_CMD;
343bedc9cbcSMing Lei 	sqe->flags		|= IOSQE_FIXED_FILE;
344bedc9cbcSMing Lei 	sqe->cmd_op		= UBLK_U_IO_REGISTER_IO_BUF;
345bedc9cbcSMing Lei 
346bedc9cbcSMing Lei 	cmd->tag		= tag;
347bedc9cbcSMing Lei 	cmd->addr		= index;
348bedc9cbcSMing Lei 	cmd->q_id		= q_id;
349bedc9cbcSMing Lei }
350bedc9cbcSMing Lei 
io_uring_prep_buf_unregister(struct io_uring_sqe * sqe,int dev_fd,int tag,int q_id,__u64 index)351bedc9cbcSMing Lei static inline void io_uring_prep_buf_unregister(struct io_uring_sqe *sqe,
352bedc9cbcSMing Lei 		int dev_fd, int tag, int q_id, __u64 index)
353bedc9cbcSMing Lei {
354bedc9cbcSMing Lei 	struct ublksrv_io_cmd *cmd = (struct ublksrv_io_cmd *)sqe->cmd;
355bedc9cbcSMing Lei 
356bedc9cbcSMing Lei 	io_uring_prep_read(sqe, dev_fd, 0, 0, 0);
357bedc9cbcSMing Lei 	sqe->opcode		= IORING_OP_URING_CMD;
358bedc9cbcSMing Lei 	sqe->flags		|= IOSQE_FIXED_FILE;
359bedc9cbcSMing Lei 	sqe->cmd_op		= UBLK_U_IO_UNREGISTER_IO_BUF;
360bedc9cbcSMing Lei 
361bedc9cbcSMing Lei 	cmd->tag		= tag;
362bedc9cbcSMing Lei 	cmd->addr		= index;
363bedc9cbcSMing Lei 	cmd->q_id		= q_id;
364bedc9cbcSMing Lei }
365bedc9cbcSMing Lei 
ublk_get_sqe_cmd(const struct io_uring_sqe * sqe)3666aecda00SMing Lei static inline void *ublk_get_sqe_cmd(const struct io_uring_sqe *sqe)
3676aecda00SMing Lei {
3686aecda00SMing Lei 	return (void *)&sqe->cmd;
3696aecda00SMing Lei }
3706aecda00SMing Lei 
ublk_set_io_res(struct ublk_queue * q,int tag,int res)371bedc9cbcSMing Lei static inline void ublk_set_io_res(struct ublk_queue *q, int tag, int res)
372bedc9cbcSMing Lei {
373bedc9cbcSMing Lei 	q->ios[tag].result = res;
374bedc9cbcSMing Lei }
375bedc9cbcSMing Lei 
ublk_get_io_res(const struct ublk_queue * q,unsigned tag)376bedc9cbcSMing Lei static inline int ublk_get_io_res(const struct ublk_queue *q, unsigned tag)
377bedc9cbcSMing Lei {
378bedc9cbcSMing Lei 	return q->ios[tag].result;
379bedc9cbcSMing Lei }
380bedc9cbcSMing Lei 
ublk_mark_io_done(struct ublk_io * io,int res)3816aecda00SMing Lei static inline void ublk_mark_io_done(struct ublk_io *io, int res)
3826aecda00SMing Lei {
3836aecda00SMing Lei 	io->flags |= (UBLKSRV_NEED_COMMIT_RQ_COMP | UBLKSRV_IO_FREE);
3846aecda00SMing Lei 	io->result = res;
3856aecda00SMing Lei }
3866aecda00SMing Lei 
ublk_get_iod(const struct ublk_queue * q,int tag)3876aecda00SMing Lei static inline const struct ublksrv_io_desc *ublk_get_iod(const struct ublk_queue *q, int tag)
3886aecda00SMing Lei {
38925aaa813SCaleb Sander Mateos 	return &q->io_cmd_buf[tag];
3906aecda00SMing Lei }
3916aecda00SMing Lei 
ublk_set_sqe_cmd_op(struct io_uring_sqe * sqe,__u32 cmd_op)3926aecda00SMing Lei static inline void ublk_set_sqe_cmd_op(struct io_uring_sqe *sqe, __u32 cmd_op)
3936aecda00SMing Lei {
3946aecda00SMing Lei 	__u32 *addr = (__u32 *)&sqe->off;
3956aecda00SMing Lei 
3966aecda00SMing Lei 	addr[0] = cmd_op;
3976aecda00SMing Lei 	addr[1] = 0;
3986aecda00SMing Lei }
3996aecda00SMing Lei 
ublk_get_io(struct ublk_queue * q,unsigned tag)4008842b72aSMing Lei static inline struct ublk_io *ublk_get_io(struct ublk_queue *q, unsigned tag)
4018842b72aSMing Lei {
4028842b72aSMing Lei 	return &q->ios[tag];
4038842b72aSMing Lei }
4048842b72aSMing Lei 
ublk_complete_io(struct ublk_queue * q,unsigned tag,int res)4056aecda00SMing Lei static inline int ublk_complete_io(struct ublk_queue *q, unsigned tag, int res)
4066aecda00SMing Lei {
4076aecda00SMing Lei 	struct ublk_io *io = &q->ios[tag];
4086aecda00SMing Lei 
4096aecda00SMing Lei 	ublk_mark_io_done(io, res);
4106aecda00SMing Lei 
411b9848ca7SUday Shankar 	return ublk_queue_io_cmd(io);
4126aecda00SMing Lei }
4136aecda00SMing Lei 
ublk_queued_tgt_io(struct ublk_queue * q,unsigned tag,int queued)4148842b72aSMing Lei static inline void ublk_queued_tgt_io(struct ublk_queue *q, unsigned tag, int queued)
4158842b72aSMing Lei {
4168842b72aSMing Lei 	if (queued < 0)
4178842b72aSMing Lei 		ublk_complete_io(q, tag, queued);
4188842b72aSMing Lei 	else {
4198842b72aSMing Lei 		struct ublk_io *io = ublk_get_io(q, tag);
4208842b72aSMing Lei 
421b9848ca7SUday Shankar 		io->t->io_inflight += queued;
4228842b72aSMing Lei 		io->tgt_ios = queued;
4238842b72aSMing Lei 		io->result = 0;
4248842b72aSMing Lei 	}
4258842b72aSMing Lei }
4268842b72aSMing Lei 
ublk_completed_tgt_io(struct ublk_queue * q,unsigned tag)4278842b72aSMing Lei static inline int ublk_completed_tgt_io(struct ublk_queue *q, unsigned tag)
4288842b72aSMing Lei {
4298842b72aSMing Lei 	struct ublk_io *io = ublk_get_io(q, tag);
4308842b72aSMing Lei 
431b9848ca7SUday Shankar 	io->t->io_inflight--;
4328842b72aSMing Lei 
4338842b72aSMing Lei 	return --io->tgt_ios == 0;
4348842b72aSMing Lei }
4358842b72aSMing Lei 
ublk_queue_use_zc(const struct ublk_queue * q)436bedc9cbcSMing Lei static inline int ublk_queue_use_zc(const struct ublk_queue *q)
437bedc9cbcSMing Lei {
438bedc9cbcSMing Lei 	return q->state & UBLKSRV_ZC;
439bedc9cbcSMing Lei }
440bedc9cbcSMing Lei 
ublk_queue_use_auto_zc(const struct ublk_queue * q)4418ccebc19SMing Lei static inline int ublk_queue_use_auto_zc(const struct ublk_queue *q)
4428ccebc19SMing Lei {
4438ccebc19SMing Lei 	return q->state & UBLKSRV_AUTO_BUF_REG;
4448ccebc19SMing Lei }
4458ccebc19SMing Lei 
4466aecda00SMing Lei extern const struct ublk_tgt_ops null_tgt_ops;
4475d95bfb5SMing Lei extern const struct ublk_tgt_ops loop_tgt_ops;
4480f3ebf2dSMing Lei extern const struct ublk_tgt_ops stripe_tgt_ops;
44981586652SUday Shankar extern const struct ublk_tgt_ops fault_inject_tgt_ops;
4506aecda00SMing Lei 
45110d962daSMing Lei void backing_file_tgt_deinit(struct ublk_dev *dev);
45210d962daSMing Lei int backing_file_tgt_init(struct ublk_dev *dev);
4530f3ebf2dSMing Lei 
ilog2(unsigned int x)4540f3ebf2dSMing Lei static inline unsigned int ilog2(unsigned int x)
4550f3ebf2dSMing Lei {
4560f3ebf2dSMing Lei 	if (x == 0)
4570f3ebf2dSMing Lei 		return 0;
4580f3ebf2dSMing Lei 	return (sizeof(x) * 8 - 1) - __builtin_clz(x);
4590f3ebf2dSMing Lei }
4606aecda00SMing Lei #endif
461