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