xref: /aosp_15_r20/external/ublksrv/include/ublksrv.h (revision 94c4a1e103eb1715230460aab379dff275992c20)
1*94c4a1e1SFrank Piva // SPDX-License-Identifier: MIT or LGPL-2.1-only
2*94c4a1e1SFrank Piva 
3*94c4a1e1SFrank Piva /**
4*94c4a1e1SFrank Piva  * @file ublksrv.h
5*94c4a1e1SFrank Piva  *
6*94c4a1e1SFrank Piva  * libublksrv APIs
7*94c4a1e1SFrank Piva  *
8*94c4a1e1SFrank Piva  * This header define the interfaces of libublksrv
9*94c4a1e1SFrank Piva  */
10*94c4a1e1SFrank Piva 
11*94c4a1e1SFrank Piva #ifndef UBLKSRV_INC_H
12*94c4a1e1SFrank Piva #define UBLKSRV_INC_H
13*94c4a1e1SFrank Piva 
14*94c4a1e1SFrank Piva #include <stdbool.h>
15*94c4a1e1SFrank Piva #include <assert.h>
16*94c4a1e1SFrank Piva 
17*94c4a1e1SFrank Piva #include "liburing.h"
18*94c4a1e1SFrank Piva 
19*94c4a1e1SFrank Piva #ifdef __cplusplus
20*94c4a1e1SFrank Piva extern "C" {
21*94c4a1e1SFrank Piva #endif
22*94c4a1e1SFrank Piva 
23*94c4a1e1SFrank Piva #include "ublk_cmd.h"
24*94c4a1e1SFrank Piva 
25*94c4a1e1SFrank Piva #define	MAX_NR_HW_QUEUES 32
26*94c4a1e1SFrank Piva #define	MAX_QD		UBLK_MAX_QUEUE_DEPTH
27*94c4a1e1SFrank Piva #define	MAX_BUF_SIZE    (32U << 20)
28*94c4a1e1SFrank Piva 
29*94c4a1e1SFrank Piva #define	DEF_NR_HW_QUEUES 1
30*94c4a1e1SFrank Piva #define	DEF_QD		128
31*94c4a1e1SFrank Piva #define	DEF_BUF_SIZE	(512 << 10)
32*94c4a1e1SFrank Piva 
33*94c4a1e1SFrank Piva /************ stored in ublksrv_ctrl_dev_info->ublksrv_flags *******/
34*94c4a1e1SFrank Piva /*
35*94c4a1e1SFrank Piva  * target may not use io_uring for handling io, so eventfd is required
36*94c4a1e1SFrank Piva  * for wakeup io command io_uring context
37*94c4a1e1SFrank Piva  */
38*94c4a1e1SFrank Piva #define UBLKSRV_F_NEED_EVENTFD		(1UL << 1)
39*94c4a1e1SFrank Piva 
40*94c4a1e1SFrank Piva struct io_uring;
41*94c4a1e1SFrank Piva struct io_uring_cqe;
42*94c4a1e1SFrank Piva struct ublksrv_aio_ctx;
43*94c4a1e1SFrank Piva struct ublksrv_ctrl_dev;
44*94c4a1e1SFrank Piva 
45*94c4a1e1SFrank Piva /**
46*94c4a1e1SFrank Piva  * Generic data for creating one ublk control device, which is used for
47*94c4a1e1SFrank Piva  * sending control commands to /dev/ublk-control.
48*94c4a1e1SFrank Piva  *
49*94c4a1e1SFrank Piva  * Control commands(UBLK_CMD_*) are defined in ublk_cmd.h.
50*94c4a1e1SFrank Piva  */
51*94c4a1e1SFrank Piva struct ublksrv_dev_data {
52*94c4a1e1SFrank Piva 	int		dev_id;
53*94c4a1e1SFrank Piva 	unsigned	max_io_buf_bytes;
54*94c4a1e1SFrank Piva 	unsigned short	nr_hw_queues;
55*94c4a1e1SFrank Piva 	unsigned short	queue_depth;
56*94c4a1e1SFrank Piva 	const char	*tgt_type;
57*94c4a1e1SFrank Piva 	const struct ublksrv_tgt_type *tgt_ops;
58*94c4a1e1SFrank Piva 	int		tgt_argc;
59*94c4a1e1SFrank Piva 	char		**tgt_argv;
60*94c4a1e1SFrank Piva 	const char	*run_dir;
61*94c4a1e1SFrank Piva 	unsigned long	flags;
62*94c4a1e1SFrank Piva 	unsigned long	ublksrv_flags;
63*94c4a1e1SFrank Piva 	unsigned long   reserved[7];
64*94c4a1e1SFrank Piva };
65*94c4a1e1SFrank Piva 
66*94c4a1e1SFrank Piva /**
67*94c4a1e1SFrank Piva  * IO data passed to target io handling callbacks, such as
68*94c4a1e1SFrank Piva  * ->handle_io_async() and ->tgt_io_done().
69*94c4a1e1SFrank Piva  */
70*94c4a1e1SFrank Piva struct ublk_io_data {
71*94c4a1e1SFrank Piva 	/** tag of this io data, unique in queue wide */
72*94c4a1e1SFrank Piva 	int tag;
73*94c4a1e1SFrank Piva 	unsigned int pad;
74*94c4a1e1SFrank Piva 
75*94c4a1e1SFrank Piva 	/** io description from ublk driver */
76*94c4a1e1SFrank Piva 	const struct ublksrv_io_desc *iod;
77*94c4a1e1SFrank Piva 
78*94c4a1e1SFrank Piva 	/**
79*94c4a1e1SFrank Piva 	 * IO private data, created in ublksrv_queue_init(),
80*94c4a1e1SFrank Piva 	 * data size is specified in ublksrv_tgt_info.io_data_size
81*94c4a1e1SFrank Piva 	 */
82*94c4a1e1SFrank Piva 	void *private_data;
83*94c4a1e1SFrank Piva };
84*94c4a1e1SFrank Piva 
85*94c4a1e1SFrank Piva /* queue state is only retrieved via ublksrv_queue_state() API */
86*94c4a1e1SFrank Piva #define UBLKSRV_QUEUE_STOPPING	(1U << 0)
87*94c4a1e1SFrank Piva #define UBLKSRV_QUEUE_IDLE	(1U << 1)
88*94c4a1e1SFrank Piva #define UBLKSRV_QUEUE_IOCTL_OP	(1U << 2)
89*94c4a1e1SFrank Piva #define UBLKSRV_USER_COPY	(1U << 3)
90*94c4a1e1SFrank Piva 
91*94c4a1e1SFrank Piva /**
92*94c4a1e1SFrank Piva  * ublksrv_queue is 1:1 mapping with ublk driver's blk-mq queue, and
93*94c4a1e1SFrank Piva  * has same queue depth with ublk driver's blk-mq queue.
94*94c4a1e1SFrank Piva  */
95*94c4a1e1SFrank Piva struct ublksrv_queue {
96*94c4a1e1SFrank Piva 	/** queue id */
97*94c4a1e1SFrank Piva 	int q_id;
98*94c4a1e1SFrank Piva 
99*94c4a1e1SFrank Piva 	/** So far, all queues in same device has same depth */
100*94c4a1e1SFrank Piva 	int q_depth;
101*94c4a1e1SFrank Piva 
102*94c4a1e1SFrank Piva 	/** io uring for handling io commands() from ublk driver */
103*94c4a1e1SFrank Piva 	struct io_uring *ring_ptr;
104*94c4a1e1SFrank Piva 
105*94c4a1e1SFrank Piva 	/** which device this queue belongs to */
106*94c4a1e1SFrank Piva 	const struct ublksrv_dev *dev;
107*94c4a1e1SFrank Piva 
108*94c4a1e1SFrank Piva 	/** queue's private data, passed from ublksrv_queue_init() */
109*94c4a1e1SFrank Piva 	void *private_data;
110*94c4a1e1SFrank Piva };
111*94c4a1e1SFrank Piva 
112*94c4a1e1SFrank Piva struct ublksrv_tgt_type;
113*94c4a1e1SFrank Piva 
114*94c4a1e1SFrank Piva #define  UBLKSRV_TGT_MAX_FDS	32
115*94c4a1e1SFrank Piva 
116*94c4a1e1SFrank Piva /**
117*94c4a1e1SFrank Piva  *
118*94c4a1e1SFrank Piva  * ublksrv_tgt_info: target data
119*94c4a1e1SFrank Piva  *
120*94c4a1e1SFrank Piva  */
121*94c4a1e1SFrank Piva struct ublksrv_tgt_info {
122*94c4a1e1SFrank Piva 	/** device size */
123*94c4a1e1SFrank Piva 	unsigned long long dev_size;
124*94c4a1e1SFrank Piva 
125*94c4a1e1SFrank Piva 	/**
126*94c4a1e1SFrank Piva 	 * target ring depth, for handling target IOs
127*94c4a1e1SFrank Piva 	 */
128*94c4a1e1SFrank Piva 	unsigned int tgt_ring_depth;
129*94c4a1e1SFrank Piva 
130*94c4a1e1SFrank Piva 	/** how many FDs regisgered */
131*94c4a1e1SFrank Piva 	unsigned int nr_fds;
132*94c4a1e1SFrank Piva 
133*94c4a1e1SFrank Piva 	/** file descriptor table */
134*94c4a1e1SFrank Piva 	int fds[UBLKSRV_TGT_MAX_FDS];
135*94c4a1e1SFrank Piva 
136*94c4a1e1SFrank Piva 	/** target private data */
137*94c4a1e1SFrank Piva 	void *tgt_data;
138*94c4a1e1SFrank Piva 
139*94c4a1e1SFrank Piva 	/**
140*94c4a1e1SFrank Piva 	 * Extra IO slots for each queue, target code can reserve some
141*94c4a1e1SFrank Piva 	 * slots for handling internal IO, such as meta data IO, then
142*94c4a1e1SFrank Piva 	 * ublk_io instances can be assigned for these extra IOs.
143*94c4a1e1SFrank Piva 	 *
144*94c4a1e1SFrank Piva 	 * IO slot is useful for storing coroutine data which is for
145*94c4a1e1SFrank Piva 	 * handling this (meta) IO.
146*94c4a1e1SFrank Piva 	 */
147*94c4a1e1SFrank Piva 	unsigned int extra_ios;
148*94c4a1e1SFrank Piva 
149*94c4a1e1SFrank Piva 	/** size of io private data */
150*94c4a1e1SFrank Piva 	unsigned int io_data_size;
151*94c4a1e1SFrank Piva 
152*94c4a1e1SFrank Piva 	/**
153*94c4a1e1SFrank Piva 	 * target io handling type, target main job is to implement
154*94c4a1e1SFrank Piva 	 * callbacks defined in this type
155*94c4a1e1SFrank Piva 	 */
156*94c4a1e1SFrank Piva 	const struct ublksrv_tgt_type *ops;
157*94c4a1e1SFrank Piva 
158*94c4a1e1SFrank Piva 	/**
159*94c4a1e1SFrank Piva 	 * If target needs to override default max workers for io_uring,
160*94c4a1e1SFrank Piva 	 * initialize io_wq_max_workers with proper value, otherwise
161*94c4a1e1SFrank Piva 	 * keep them as zero
162*94c4a1e1SFrank Piva 	 */
163*94c4a1e1SFrank Piva 	unsigned int iowq_max_workers[2];
164*94c4a1e1SFrank Piva 
165*94c4a1e1SFrank Piva 	unsigned long reserved[4];
166*94c4a1e1SFrank Piva };
167*94c4a1e1SFrank Piva 
168*94c4a1e1SFrank Piva /**
169*94c4a1e1SFrank Piva  * ublksrv device
170*94c4a1e1SFrank Piva  */
171*94c4a1e1SFrank Piva struct ublksrv_dev {
172*94c4a1e1SFrank Piva 	/** device data */
173*94c4a1e1SFrank Piva 	struct ublksrv_tgt_info tgt;
174*94c4a1e1SFrank Piva };
175*94c4a1e1SFrank Piva 
176*94c4a1e1SFrank Piva /**
177*94c4a1e1SFrank Piva  *
178*94c4a1e1SFrank Piva  * ublksrv_tgt_type: target type
179*94c4a1e1SFrank Piva  *
180*94c4a1e1SFrank Piva  */
181*94c4a1e1SFrank Piva struct ublksrv_tgt_type {
182*94c4a1e1SFrank Piva 	/**
183*94c4a1e1SFrank Piva 	 * One IO request comes from /dev/ublkbN, so notify target code
184*94c4a1e1SFrank Piva 	 * for handling the IO. Inside target code, the IO can be handled
185*94c4a1e1SFrank Piva 	 * with our io_uring too, if this is true, ->tgt_io_done callback
186*94c4a1e1SFrank Piva 	 * has to be implemented. Otherwise, target can implement
187*94c4a1e1SFrank Piva 	 * ->handle_event() for processing io completion there.
188*94c4a1e1SFrank Piva 	 *
189*94c4a1e1SFrank Piva 	 *  Required.
190*94c4a1e1SFrank Piva 	 */
191*94c4a1e1SFrank Piva 	int (*handle_io_async)(const struct ublksrv_queue *,
192*94c4a1e1SFrank Piva 			const struct ublk_io_data *io);
193*94c4a1e1SFrank Piva 
194*94c4a1e1SFrank Piva 	/**
195*94c4a1e1SFrank Piva 	 * target io is handled by our io_uring, and once the target io
196*94c4a1e1SFrank Piva 	 * is completed, this callback is called.
197*94c4a1e1SFrank Piva 	 *
198*94c4a1e1SFrank Piva 	 * Optional, only required iff this target io is handled by ublksrv's
199*94c4a1e1SFrank Piva 	 * io_uring.
200*94c4a1e1SFrank Piva 	 */
201*94c4a1e1SFrank Piva 	void (*tgt_io_done)(const struct ublksrv_queue *,
202*94c4a1e1SFrank Piva 			const struct ublk_io_data *io,
203*94c4a1e1SFrank Piva 			const struct io_uring_cqe *);
204*94c4a1e1SFrank Piva 
205*94c4a1e1SFrank Piva 	/**
206*94c4a1e1SFrank Piva 	 * Someone has written to our eventfd, so let target handle the
207*94c4a1e1SFrank Piva 	 * event, most of times, it is for handling io completion by
208*94c4a1e1SFrank Piva 	 * calling ublksrv_complete_io() which has to be run in ubq_daemon
209*94c4a1e1SFrank Piva 	 * context.
210*94c4a1e1SFrank Piva 	 *
211*94c4a1e1SFrank Piva 	 * Follows the typical scenario:
212*94c4a1e1SFrank Piva 	 *
213*94c4a1e1SFrank Piva 	 * 1) one target io is completed in target pthread context, so
214*94c4a1e1SFrank Piva 	 * target code calls ublksrv_queue_send_event for notifying ubq
215*94c4a1e1SFrank Piva 	 * daemon
216*94c4a1e1SFrank Piva 	 *
217*94c4a1e1SFrank Piva 	 * 2) ubq daemon gets notified, so wakeup from io_uring_enter(),
218*94c4a1e1SFrank Piva 	 * then found eventfd is completed, so call ->handle_event()
219*94c4a1e1SFrank Piva 	 *
220*94c4a1e1SFrank Piva 	 * 3) inside ->handle_event(), if any io represented by one io
221*94c4a1e1SFrank Piva 	 * command is completed, ublksrv_complete_io() is called for
222*94c4a1e1SFrank Piva 	 * this io.
223*94c4a1e1SFrank Piva 	 *
224*94c4a1e1SFrank Piva 	 * 4) after returning from ->handle_event(), ubq_daemon will
225*94c4a1e1SFrank Piva 	 * queue & submit the eventfd io immediately for getting
226*94c4a1e1SFrank Piva 	 * notification from future event.
227*94c4a1e1SFrank Piva 	 *
228*94c4a1e1SFrank Piva 	 * Optional. Only needed if target IO is handled by target its
229*94c4a1e1SFrank Piva 	 * own pthread context.
230*94c4a1e1SFrank Piva 	 */
231*94c4a1e1SFrank Piva 	void (*handle_event)(const struct ublksrv_queue *);
232*94c4a1e1SFrank Piva 
233*94c4a1e1SFrank Piva 	/**
234*94c4a1e1SFrank Piva 	 * One typical use case is to flush meta data, which is usually done
235*94c4a1e1SFrank Piva 	 * in background. So there isn't any tag from libublksrv for this kind
236*94c4a1e1SFrank Piva 	 * of IOs, and the target code has to request for allocating extra ios
237*94c4a1e1SFrank Piva 	 * by passing tgt_type->extra_ios and let this callback consume & handle
238*94c4a1e1SFrank Piva 	 * these extra IOs.
239*94c4a1e1SFrank Piva 	 *
240*94c4a1e1SFrank Piva 	 * nr_queued_io: count of queued IOs in ublksrv_reap_events_uring of
241*94c4a1e1SFrank Piva 	 * this time
242*94c4a1e1SFrank Piva 	 *
243*94c4a1e1SFrank Piva 	 * Optional.
244*94c4a1e1SFrank Piva 	 */
245*94c4a1e1SFrank Piva 	void (*handle_io_background)(const struct ublksrv_queue *, int
246*94c4a1e1SFrank Piva 			nr_queued_io);
247*94c4a1e1SFrank Piva 
248*94c4a1e1SFrank Piva 	/**
249*94c4a1e1SFrank Piva 	 * show target specific command line for adding new device
250*94c4a1e1SFrank Piva 	 *
251*94c4a1e1SFrank Piva 	 * Be careful: this callback is the only one which is not run from
252*94c4a1e1SFrank Piva 	 * ublk device daemon task context.
253*94c4a1e1SFrank Piva 	 */
254*94c4a1e1SFrank Piva 	void (*usage_for_add)(void);
255*94c4a1e1SFrank Piva 
256*94c4a1e1SFrank Piva 	/**
257*94c4a1e1SFrank Piva 	 * initialize this new target, argc/argv includes target specific
258*94c4a1e1SFrank Piva 	 * command line parameters
259*94c4a1e1SFrank Piva 	 *
260*94c4a1e1SFrank Piva 	 * Required.
261*94c4a1e1SFrank Piva 	 */
262*94c4a1e1SFrank Piva 	int (*init_tgt)(struct ublksrv_dev *, int type, int argc,
263*94c4a1e1SFrank Piva 			char *argv[]);
264*94c4a1e1SFrank Piva 
265*94c4a1e1SFrank Piva 	/**
266*94c4a1e1SFrank Piva 	 * Deinitialize this target
267*94c4a1e1SFrank Piva 	 *
268*94c4a1e1SFrank Piva 	 * Optional.
269*94c4a1e1SFrank Piva 	 */
270*94c4a1e1SFrank Piva 	void (*deinit_tgt)(const struct ublksrv_dev *);
271*94c4a1e1SFrank Piva 
272*94c4a1e1SFrank Piva 	/**
273*94c4a1e1SFrank Piva 	 * callback for allocating io buffer
274*94c4a1e1SFrank Piva 	 *
275*94c4a1e1SFrank Piva 	 * Optional.
276*94c4a1e1SFrank Piva 	 */
277*94c4a1e1SFrank Piva 	void *(*alloc_io_buf)(const struct ublksrv_queue *q, int tag, int size);
278*94c4a1e1SFrank Piva 	/**
279*94c4a1e1SFrank Piva 	 * callback for freeing io buffer
280*94c4a1e1SFrank Piva 	 *
281*94c4a1e1SFrank Piva 	 * Optional.
282*94c4a1e1SFrank Piva 	 */
283*94c4a1e1SFrank Piva 	void (*free_io_buf)(const struct ublksrv_queue *q, void *buf, int tag);
284*94c4a1e1SFrank Piva 
285*94c4a1e1SFrank Piva 	/**
286*94c4a1e1SFrank Piva 	 * Called when the ublksrv io_uring is idle.
287*94c4a1e1SFrank Piva 	 *
288*94c4a1e1SFrank Piva 	 * Optional.
289*94c4a1e1SFrank Piva 	 */
290*94c4a1e1SFrank Piva 	void (*idle_fn)(const struct ublksrv_queue *q, bool enter);
291*94c4a1e1SFrank Piva 
292*94c4a1e1SFrank Piva 	/** target type */
293*94c4a1e1SFrank Piva 	int  type;
294*94c4a1e1SFrank Piva 
295*94c4a1e1SFrank Piva 	/** flags required for ublk driver */
296*94c4a1e1SFrank Piva 	unsigned ublk_flags;
297*94c4a1e1SFrank Piva 
298*94c4a1e1SFrank Piva 	/** flags required for ublksrv */
299*94c4a1e1SFrank Piva 	unsigned ublksrv_flags;
300*94c4a1e1SFrank Piva 	unsigned pad;
301*94c4a1e1SFrank Piva 
302*94c4a1e1SFrank Piva 	/** target name */
303*94c4a1e1SFrank Piva 	const char *name;
304*94c4a1e1SFrank Piva 
305*94c4a1e1SFrank Piva 	/**
306*94c4a1e1SFrank Piva 	 * recovery callback for this target
307*94c4a1e1SFrank Piva 	 *
308*94c4a1e1SFrank Piva 	 * Required.
309*94c4a1e1SFrank Piva 	 */
310*94c4a1e1SFrank Piva 	int (*recovery_tgt)(struct ublksrv_dev *, int type);
311*94c4a1e1SFrank Piva 
312*94c4a1e1SFrank Piva 	/**
313*94c4a1e1SFrank Piva 	 * queue_data_ptr points to address of q->priviate_data, so that
314*94c4a1e1SFrank Piva 	 * we still can pass 'const struct ublksrv_queue *', meantime
315*94c4a1e1SFrank Piva 	 * queue data can be stored to q->private_data via queue_data_ptr.
316*94c4a1e1SFrank Piva 	 *
317*94c4a1e1SFrank Piva 	 * ->init_queue provides one chance to override/init the passed
318*94c4a1e1SFrank Piva 	 * "queue_data" to ublksrv_queue_init(), "queue_data" is set to
319*94c4a1e1SFrank Piva 	 * q->private_data before calling ->init_queue()
320*94c4a1e1SFrank Piva 	 */
321*94c4a1e1SFrank Piva 	int (*init_queue)(const struct ublksrv_queue *, void **queue_data_ptr);
322*94c4a1e1SFrank Piva 
323*94c4a1e1SFrank Piva 	/** deinit queue data, counter pair of ->init_queue */
324*94c4a1e1SFrank Piva 	void (*deinit_queue)(const struct ublksrv_queue *);
325*94c4a1e1SFrank Piva 
326*94c4a1e1SFrank Piva 	unsigned long reserved[5];
327*94c4a1e1SFrank Piva };
328*94c4a1e1SFrank Piva 
329*94c4a1e1SFrank Piva /**
330*94c4a1e1SFrank Piva  * Build sqe->user_data.
331*94c4a1e1SFrank Piva  *
332*94c4a1e1SFrank Piva  * io_uring relies on ->user_data to map cqe to the submitted io represented by
333*94c4a1e1SFrank Piva  * sqe, encodes ublk interested info into ->user_data for handling IO
334*94c4a1e1SFrank Piva  * completion efficiently.
335*94c4a1e1SFrank Piva  *
336*94c4a1e1SFrank Piva  * @param tag ublk io tag
337*94c4a1e1SFrank Piva  * @param op operation code of submitted io
338*94c4a1e1SFrank Piva  * @param tgt_data target data for this io
339*94c4a1e1SFrank Piva  * @param is_taget_io is this one target io, and it should be true for target,
340*94c4a1e1SFrank Piva  * 	and false for ublksrv built uring command, which is for communicating
341*94c4a1e1SFrank Piva  * 	with ublk_drv
342*94c4a1e1SFrank Piva  */
build_user_data(unsigned tag,unsigned op,unsigned tgt_data,unsigned is_target_io)343*94c4a1e1SFrank Piva static inline __u64 build_user_data(unsigned tag, unsigned op,
344*94c4a1e1SFrank Piva 		unsigned tgt_data, unsigned is_target_io)
345*94c4a1e1SFrank Piva {
346*94c4a1e1SFrank Piva 	assert(!(tag >> 16) && !(op >> 8) && !(tgt_data >> 16));
347*94c4a1e1SFrank Piva 
348*94c4a1e1SFrank Piva 	return tag | (op << 16) | (tgt_data << 24) | (__u64)is_target_io << 63;
349*94c4a1e1SFrank Piva }
350*94c4a1e1SFrank Piva 
user_data_to_tag(__u64 user_data)351*94c4a1e1SFrank Piva static inline unsigned int user_data_to_tag(__u64 user_data)
352*94c4a1e1SFrank Piva {
353*94c4a1e1SFrank Piva 	return user_data & 0xffff;
354*94c4a1e1SFrank Piva }
355*94c4a1e1SFrank Piva 
user_data_to_op(__u64 user_data)356*94c4a1e1SFrank Piva static inline unsigned int user_data_to_op(__u64 user_data)
357*94c4a1e1SFrank Piva {
358*94c4a1e1SFrank Piva 	return (user_data >> 16) & 0xff;
359*94c4a1e1SFrank Piva }
360*94c4a1e1SFrank Piva 
user_data_to_tgt_data(__u64 user_data)361*94c4a1e1SFrank Piva static inline unsigned int user_data_to_tgt_data(__u64 user_data)
362*94c4a1e1SFrank Piva {
363*94c4a1e1SFrank Piva 	return (user_data >> 24) & 0xffff;
364*94c4a1e1SFrank Piva }
365*94c4a1e1SFrank Piva 
ublk_pos(__u16 q_id,__u16 tag,__u32 offset)366*94c4a1e1SFrank Piva static inline __u64 ublk_pos(__u16 q_id, __u16 tag, __u32 offset)
367*94c4a1e1SFrank Piva {
368*94c4a1e1SFrank Piva 	assert(!(offset & ~UBLK_IO_BUF_BITS_MASK));
369*94c4a1e1SFrank Piva 
370*94c4a1e1SFrank Piva 	return UBLKSRV_IO_BUF_OFFSET +
371*94c4a1e1SFrank Piva 		((((__u64)q_id) << UBLK_QID_OFF) |
372*94c4a1e1SFrank Piva 		(((__u64)tag) << UBLK_TAG_OFF) | (__u64)offset);
373*94c4a1e1SFrank Piva }
374*94c4a1e1SFrank Piva 
375*94c4a1e1SFrank Piva /**
376*94c4a1e1SFrank Piva  * \defgroup ctrl_dev control device API
377*94c4a1e1SFrank Piva  *
378*94c4a1e1SFrank Piva  *  Most of APIs are for sending command to ublk control device(/dev/ublk-control),
379*94c4a1e1SFrank Piva  *  and some of them are just for device management purpose, such as, retrieving
380*94c4a1e1SFrank Piva  *  device json buffer, run_dir, prepare for recovering, get cached device info ...
381*94c4a1e1SFrank Piva  *
382*94c4a1e1SFrank Piva  *  Almost all these APIs can be called in random context by random io uring
383*94c4a1e1SFrank Piva  *  context
384*94c4a1e1SFrank Piva  *
385*94c4a1e1SFrank Piva  *  @{
386*94c4a1e1SFrank Piva  */
387*94c4a1e1SFrank Piva 
388*94c4a1e1SFrank Piva /**
389*94c4a1e1SFrank Piva  * Deinit one control device
390*94c4a1e1SFrank Piva  *
391*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
392*94c4a1e1SFrank Piva  *
393*94c4a1e1SFrank Piva  */
394*94c4a1e1SFrank Piva extern void ublksrv_ctrl_deinit(struct ublksrv_ctrl_dev *dev);
395*94c4a1e1SFrank Piva 
396*94c4a1e1SFrank Piva /**
397*94c4a1e1SFrank Piva  * Allocate and init one control device
398*94c4a1e1SFrank Piva  *
399*94c4a1e1SFrank Piva  * @param data data for allocating & initializing this control device
400*94c4a1e1SFrank Piva  *
401*94c4a1e1SFrank Piva  */
402*94c4a1e1SFrank Piva extern struct ublksrv_ctrl_dev *ublksrv_ctrl_init(struct ublksrv_dev_data *data);
403*94c4a1e1SFrank Piva 
404*94c4a1e1SFrank Piva /**
405*94c4a1e1SFrank Piva  * Retrieve and store each queue's cpu affinity info into private data of the
406*94c4a1e1SFrank Piva  * control device by sending commands to ublk control device
407*94c4a1e1SFrank Piva  *
408*94c4a1e1SFrank Piva  * @param ctrl_dev the ublksrv control device instance
409*94c4a1e1SFrank Piva  *
410*94c4a1e1SFrank Piva  */
411*94c4a1e1SFrank Piva extern int ublksrv_ctrl_get_affinity(struct ublksrv_ctrl_dev *ctrl_dev);
412*94c4a1e1SFrank Piva 
413*94c4a1e1SFrank Piva /**
414*94c4a1e1SFrank Piva  * Add one ublk device by sending command to ublk driver
415*94c4a1e1SFrank Piva  *
416*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
417*94c4a1e1SFrank Piva  */
418*94c4a1e1SFrank Piva extern int ublksrv_ctrl_add_dev(struct ublksrv_ctrl_dev *dev);
419*94c4a1e1SFrank Piva 
420*94c4a1e1SFrank Piva /**
421*94c4a1e1SFrank Piva  * Delete this ublk device by sending command to ublk driver
422*94c4a1e1SFrank Piva  *
423*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
424*94c4a1e1SFrank Piva  */
425*94c4a1e1SFrank Piva extern int ublksrv_ctrl_del_dev(struct ublksrv_ctrl_dev *dev);
426*94c4a1e1SFrank Piva 
427*94c4a1e1SFrank Piva /**
428*94c4a1e1SFrank Piva  * Delete this ublk device asynchronously by sending command to ublk driver
429*94c4a1e1SFrank Piva  *
430*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
431*94c4a1e1SFrank Piva  */
432*94c4a1e1SFrank Piva extern int ublksrv_ctrl_del_dev_async(struct ublksrv_ctrl_dev *dev);
433*94c4a1e1SFrank Piva 
434*94c4a1e1SFrank Piva /**
435*94c4a1e1SFrank Piva  * Retrieve ublk device info by sending command to ublk control device
436*94c4a1e1SFrank Piva  *
437*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
438*94c4a1e1SFrank Piva  */
439*94c4a1e1SFrank Piva extern int ublksrv_ctrl_get_info(struct ublksrv_ctrl_dev *dev);
440*94c4a1e1SFrank Piva 
441*94c4a1e1SFrank Piva /**
442*94c4a1e1SFrank Piva  * Stop the specified ublk device by sending command to ublk control device
443*94c4a1e1SFrank Piva  *
444*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
445*94c4a1e1SFrank Piva  */
446*94c4a1e1SFrank Piva extern int ublksrv_ctrl_stop_dev(struct ublksrv_ctrl_dev *dev);
447*94c4a1e1SFrank Piva 
448*94c4a1e1SFrank Piva /**
449*94c4a1e1SFrank Piva  * Dump this ublk device
450*94c4a1e1SFrank Piva  *
451*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
452*94c4a1e1SFrank Piva  * @param buf ublk device json buffer, optional
453*94c4a1e1SFrank Piva  */
454*94c4a1e1SFrank Piva extern void ublksrv_ctrl_dump(struct ublksrv_ctrl_dev *dev, const char *buf);
455*94c4a1e1SFrank Piva 
456*94c4a1e1SFrank Piva /**
457*94c4a1e1SFrank Piva  * Start this ublk device by sending command to ublk control device
458*94c4a1e1SFrank Piva  *
459*94c4a1e1SFrank Piva  * @param ctrl_dev the ublksrv control device instance
460*94c4a1e1SFrank Piva  * @param daemon_pid pid of the ublksrv process
461*94c4a1e1SFrank Piva  */
462*94c4a1e1SFrank Piva extern int ublksrv_ctrl_start_dev(struct ublksrv_ctrl_dev *ctrl_dev,
463*94c4a1e1SFrank Piva 		int daemon_pid);
464*94c4a1e1SFrank Piva 
465*94c4a1e1SFrank Piva /**
466*94c4a1e1SFrank Piva  * Set specified device parameter by sending command to ublk control device
467*94c4a1e1SFrank Piva  *
468*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
469*94c4a1e1SFrank Piva  * @param params the specified parameter for setting device
470*94c4a1e1SFrank Piva  */
471*94c4a1e1SFrank Piva extern int ublksrv_ctrl_set_params(struct ublksrv_ctrl_dev *dev,
472*94c4a1e1SFrank Piva 		struct ublk_params *params);
473*94c4a1e1SFrank Piva 
474*94c4a1e1SFrank Piva /**
475*94c4a1e1SFrank Piva  * Get specified device parameter by sending command to ublk control device
476*94c4a1e1SFrank Piva  *
477*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
478*94c4a1e1SFrank Piva  * @param params the parameter buffer for storing the device parameter
479*94c4a1e1SFrank Piva  */
480*94c4a1e1SFrank Piva extern int ublksrv_ctrl_get_params(struct ublksrv_ctrl_dev *dev,
481*94c4a1e1SFrank Piva 		struct ublk_params *params);
482*94c4a1e1SFrank Piva 
483*94c4a1e1SFrank Piva /**
484*94c4a1e1SFrank Piva  * Start to recovery device by sending command to ublk control device
485*94c4a1e1SFrank Piva  *
486*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
487*94c4a1e1SFrank Piva  */
488*94c4a1e1SFrank Piva extern int ublksrv_ctrl_start_recovery(struct ublksrv_ctrl_dev *dev);
489*94c4a1e1SFrank Piva 
490*94c4a1e1SFrank Piva /**
491*94c4a1e1SFrank Piva  * End recovery device by sending command to ublk control device
492*94c4a1e1SFrank Piva  *
493*94c4a1e1SFrank Piva  * Once this command is successful, the device is recovered to normal state
494*94c4a1e1SFrank Piva  *
495*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
496*94c4a1e1SFrank Piva  * @param daemon_pid pid of the new ublksrv process
497*94c4a1e1SFrank Piva  */
498*94c4a1e1SFrank Piva extern int ublksrv_ctrl_end_recovery(struct ublksrv_ctrl_dev *dev,
499*94c4a1e1SFrank Piva 		int daemon_pid);
500*94c4a1e1SFrank Piva 
501*94c4a1e1SFrank Piva /**
502*94c4a1e1SFrank Piva  * Return cached device info for this device
503*94c4a1e1SFrank Piva  *
504*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
505*94c4a1e1SFrank Piva  */
506*94c4a1e1SFrank Piva extern const struct ublksrv_ctrl_dev_info *ublksrv_ctrl_get_dev_info(
507*94c4a1e1SFrank Piva 		const struct ublksrv_ctrl_dev *dev);
508*94c4a1e1SFrank Piva 
509*94c4a1e1SFrank Piva /**
510*94c4a1e1SFrank Piva  * Return feature set supported by ublk driver
511*94c4a1e1SFrank Piva  *
512*94c4a1e1SFrank Piva  * @features points to buffer for holding the returned features
513*94c4a1e1SFrank Piva  */
514*94c4a1e1SFrank Piva extern int ublksrv_ctrl_get_features(struct ublksrv_ctrl_dev *dev,
515*94c4a1e1SFrank Piva 		__u64 *features);
516*94c4a1e1SFrank Piva 
517*94c4a1e1SFrank Piva /**
518*94c4a1e1SFrank Piva  * Return run dir of ublk device
519*94c4a1e1SFrank Piva  *
520*94c4a1e1SFrank Piva  * Device pid file and json string stored under this dir
521*94c4a1e1SFrank Piva  *
522*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
523*94c4a1e1SFrank Piva  */
524*94c4a1e1SFrank Piva extern const char *ublksrv_ctrl_get_run_dir(const struct ublksrv_ctrl_dev *dev);
525*94c4a1e1SFrank Piva 
526*94c4a1e1SFrank Piva /**
527*94c4a1e1SFrank Piva  * Prepare for starting to recovery device
528*94c4a1e1SFrank Piva  *
529*94c4a1e1SFrank Piva  * Setup target type, run_dir and json buffer before starting to recovery device.
530*94c4a1e1SFrank Piva  *
531*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
532*94c4a1e1SFrank Piva  * @param tgt_type target type name of this device
533*94c4a1e1SFrank Piva  * @param tgt_ops target type of this devie
534*94c4a1e1SFrank Piva  * @param recovery_jbuf points to device json buffer
535*94c4a1e1SFrank Piva  */
536*94c4a1e1SFrank Piva extern void ublksrv_ctrl_prep_recovery(struct ublksrv_ctrl_dev *dev,
537*94c4a1e1SFrank Piva 		const char *tgt_type, const struct ublksrv_tgt_type *tgt_ops,
538*94c4a1e1SFrank Piva 		const char *recovery_jbuf);
539*94c4a1e1SFrank Piva 
540*94c4a1e1SFrank Piva /**
541*94c4a1e1SFrank Piva  * Return device's json buffer
542*94c4a1e1SFrank Piva  *
543*94c4a1e1SFrank Piva  * Setup target type, run_dir and json buffer before starting to recovery device.
544*94c4a1e1SFrank Piva  *
545*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
546*94c4a1e1SFrank Piva  */
547*94c4a1e1SFrank Piva extern const char *ublksrv_ctrl_get_recovery_jbuf(const struct ublksrv_ctrl_dev *dev);
548*94c4a1e1SFrank Piva 
549*94c4a1e1SFrank Piva /**
550*94c4a1e1SFrank Piva  * Return true if this control device is for recovering
551*94c4a1e1SFrank Piva  *
552*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
553*94c4a1e1SFrank Piva  */
554*94c4a1e1SFrank Piva extern bool ublksrv_is_recovering(const struct ublksrv_ctrl_dev *ctrl_dev);
555*94c4a1e1SFrank Piva 
556*94c4a1e1SFrank Piva /** @} */ // end of ctrl_dev group
557*94c4a1e1SFrank Piva 
558*94c4a1e1SFrank Piva 
559*94c4a1e1SFrank Piva /**
560*94c4a1e1SFrank Piva  * \defgroup ublksrv_dev ublksrv device API
561*94c4a1e1SFrank Piva  *
562*94c4a1e1SFrank Piva  * ublksrv device ("/dev/ublkcN") level APIs, and ublksrv device focuses on
563*94c4a1e1SFrank Piva  * IO handling related function
564*94c4a1e1SFrank Piva  *
565*94c4a1e1SFrank Piva  * All APIs in this group should be called in ublksrv daemon process context
566*94c4a1e1SFrank Piva  *
567*94c4a1e1SFrank Piva  *  @{
568*94c4a1e1SFrank Piva  */
569*94c4a1e1SFrank Piva 
570*94c4a1e1SFrank Piva /**
571*94c4a1e1SFrank Piva  * Allocate and initialize ublksrv device
572*94c4a1e1SFrank Piva  *
573*94c4a1e1SFrank Piva  * @param ctrl_dev the ublksrv control device instance
574*94c4a1e1SFrank Piva  */
575*94c4a1e1SFrank Piva extern const struct ublksrv_dev *ublksrv_dev_init(const struct ublksrv_ctrl_dev *
576*94c4a1e1SFrank Piva 		ctrl_dev);
577*94c4a1e1SFrank Piva 
578*94c4a1e1SFrank Piva /**
579*94c4a1e1SFrank Piva  * Deinitialize and free ublksrv device
580*94c4a1e1SFrank Piva  *
581*94c4a1e1SFrank Piva  * @param dev the ublksrv device instance
582*94c4a1e1SFrank Piva  */
583*94c4a1e1SFrank Piva extern void ublksrv_dev_deinit(const struct ublksrv_dev *dev);
584*94c4a1e1SFrank Piva 
585*94c4a1e1SFrank Piva /**
586*94c4a1e1SFrank Piva  * Return the associated ublksrv control device instance
587*94c4a1e1SFrank Piva  *
588*94c4a1e1SFrank Piva  * @param dev the ublksrv device instance
589*94c4a1e1SFrank Piva  */
590*94c4a1e1SFrank Piva extern const struct ublksrv_ctrl_dev *ublksrv_get_ctrl_dev(
591*94c4a1e1SFrank Piva 		const struct ublksrv_dev *dev);
592*94c4a1e1SFrank Piva 
593*94c4a1e1SFrank Piva /**
594*94c4a1e1SFrank Piva  * Return pid file FD of this ublksrv device
595*94c4a1e1SFrank Piva  *
596*94c4a1e1SFrank Piva  * @param dev the ublksrv device instance
597*94c4a1e1SFrank Piva  */
598*94c4a1e1SFrank Piva extern int ublksrv_get_pidfile_fd(const struct ublksrv_dev *dev);
599*94c4a1e1SFrank Piva 
600*94c4a1e1SFrank Piva /**
601*94c4a1e1SFrank Piva  * Set completion queue depth of this ublksrv device
602*94c4a1e1SFrank Piva  *
603*94c4a1e1SFrank Piva  * @param dev the ublksrv device instance
604*94c4a1e1SFrank Piva  * @param cq_depth depth of the completion queue of io_uring
605*94c4a1e1SFrank Piva  */
606*94c4a1e1SFrank Piva extern void ublksrv_dev_set_cq_depth(struct ublksrv_dev *dev, int cq_depth);
607*94c4a1e1SFrank Piva 
608*94c4a1e1SFrank Piva /**
609*94c4a1e1SFrank Piva  * Get completion queue depth of this ublksrv device
610*94c4a1e1SFrank Piva  *
611*94c4a1e1SFrank Piva  * @param dev the ublksrv device instance
612*94c4a1e1SFrank Piva  */
613*94c4a1e1SFrank Piva extern int ublksrv_dev_get_cq_depth(struct ublksrv_dev *dev);
614*94c4a1e1SFrank Piva 
615*94c4a1e1SFrank Piva /**
616*94c4a1e1SFrank Piva  *
617*94c4a1e1SFrank Piva  * Apply OOM porotection
618*94c4a1e1SFrank Piva  */
619*94c4a1e1SFrank Piva extern void ublksrv_apply_oom_protection(void);
620*94c4a1e1SFrank Piva 
621*94c4a1e1SFrank Piva /** @} */ // end of ublksrv_dev group
622*94c4a1e1SFrank Piva 
623*94c4a1e1SFrank Piva /* target json has to include the following key/value */
624*94c4a1e1SFrank Piva #define UBLKSRV_TGT_NAME_MAX_LEN 32
625*94c4a1e1SFrank Piva struct ublksrv_tgt_base_json {
626*94c4a1e1SFrank Piva 	char name[UBLKSRV_TGT_NAME_MAX_LEN];
627*94c4a1e1SFrank Piva 	int type;
628*94c4a1e1SFrank Piva 	unsigned int pad;
629*94c4a1e1SFrank Piva 	unsigned long long dev_size;
630*94c4a1e1SFrank Piva 	unsigned long reserved[8];
631*94c4a1e1SFrank Piva };
632*94c4a1e1SFrank Piva 
633*94c4a1e1SFrank Piva /**
634*94c4a1e1SFrank Piva  * \defgroup ublksrv_json ublksrv json string API
635*94c4a1e1SFrank Piva  *
636*94c4a1e1SFrank Piva  * ublksrv json string APIs
637*94c4a1e1SFrank Piva  *
638*94c4a1e1SFrank Piva  * APIs for serializing/deserializing device data to/from json string
639*94c4a1e1SFrank Piva  *
640*94c4a1e1SFrank Piva  *  @{
641*94c4a1e1SFrank Piva  */
642*94c4a1e1SFrank Piva 
643*94c4a1e1SFrank Piva /**
644*94c4a1e1SFrank Piva  * Serialize json buffer from device's ublksrv_ctrl_dev_info data
645*94c4a1e1SFrank Piva  *
646*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
647*94c4a1e1SFrank Piva  * @param buf json buffer
648*94c4a1e1SFrank Piva  * @param len length of json buffer
649*94c4a1e1SFrank Piva  */
650*94c4a1e1SFrank Piva extern int ublksrv_json_write_dev_info(const struct ublksrv_ctrl_dev *dev,
651*94c4a1e1SFrank Piva 		char *buf, int len);
652*94c4a1e1SFrank Piva 
653*94c4a1e1SFrank Piva /**
654*94c4a1e1SFrank Piva  * Deserialize json buffer to ublksrv_ctrl_dev_info instance
655*94c4a1e1SFrank Piva  *
656*94c4a1e1SFrank Piva  * @param json_buf json buffer
657*94c4a1e1SFrank Piva  * @param info device info for storing the parsed ublksrv_ctrl_dev_info
658*94c4a1e1SFrank Piva  */
659*94c4a1e1SFrank Piva extern int ublksrv_json_read_dev_info(const char *json_buf,
660*94c4a1e1SFrank Piva 		struct ublksrv_ctrl_dev_info *info);
661*94c4a1e1SFrank Piva 
662*94c4a1e1SFrank Piva /**
663*94c4a1e1SFrank Piva  * Serialize json buffer from ublksrv queue
664*94c4a1e1SFrank Piva  *
665*94c4a1e1SFrank Piva  * @param dev the ublksrv control device instance
666*94c4a1e1SFrank Piva  * @param jbuf json buffer
667*94c4a1e1SFrank Piva  * @param len length of json buffer
668*94c4a1e1SFrank Piva  * @param qid queue id
669*94c4a1e1SFrank Piva  * @param ubq_daemon_tid queue pthread tid
670*94c4a1e1SFrank Piva  */
671*94c4a1e1SFrank Piva extern int ublksrv_json_write_queue_info(const struct ublksrv_ctrl_dev *dev,
672*94c4a1e1SFrank Piva 		char *jbuf, int len, int qid, int ubq_daemon_tid);
673*94c4a1e1SFrank Piva 
674*94c4a1e1SFrank Piva /**
675*94c4a1e1SFrank Piva  * Deserialize json buffer to ublksrv queue
676*94c4a1e1SFrank Piva  *
677*94c4a1e1SFrank Piva  * @param jbuf json buffer
678*94c4a1e1SFrank Piva  * @param qid queue id
679*94c4a1e1SFrank Piva  * @param tid queue pthread tid
680*94c4a1e1SFrank Piva  * @param affinity_buf queue affinity buffer
681*94c4a1e1SFrank Piva  * @param len length of json buffer
682*94c4a1e1SFrank Piva  */
683*94c4a1e1SFrank Piva extern int ublksrv_json_read_queue_info(const char *jbuf, int qid,
684*94c4a1e1SFrank Piva 		unsigned *tid, char *affinity_buf, int len);
685*94c4a1e1SFrank Piva 
686*94c4a1e1SFrank Piva /**
687*94c4a1e1SFrank Piva  * Deserialize json buffer to target data
688*94c4a1e1SFrank Piva  *
689*94c4a1e1SFrank Piva  * @param jbuf json buffer
690*94c4a1e1SFrank Piva  * @param tgt_buf target buffer
691*94c4a1e1SFrank Piva  * @param len length of json buffer
692*94c4a1e1SFrank Piva  */
693*94c4a1e1SFrank Piva extern int ublksrv_json_read_target_info(const char *jbuf, char *tgt_buf,
694*94c4a1e1SFrank Piva 		int len);
695*94c4a1e1SFrank Piva 
696*94c4a1e1SFrank Piva /**
697*94c4a1e1SFrank Piva  * Deserialize json buffer to target string field
698*94c4a1e1SFrank Piva  *
699*94c4a1e1SFrank Piva  * @param jbuf json buffer
700*94c4a1e1SFrank Piva  * @param len length of json buffer
701*94c4a1e1SFrank Piva  * @param name string name
702*94c4a1e1SFrank Piva  * @param val string value
703*94c4a1e1SFrank Piva  */
704*94c4a1e1SFrank Piva extern int ublksrv_json_read_target_str_info(const char *jbuf, int len,
705*94c4a1e1SFrank Piva 		const char *name, char *val);
706*94c4a1e1SFrank Piva 
707*94c4a1e1SFrank Piva /**
708*94c4a1e1SFrank Piva  * Deserialize json buffer to target ulong field
709*94c4a1e1SFrank Piva  *
710*94c4a1e1SFrank Piva  * @param jbuf json buffer
711*94c4a1e1SFrank Piva  * @param name field name with ulong type
712*94c4a1e1SFrank Piva  * @param val field value with ulong type
713*94c4a1e1SFrank Piva  */
714*94c4a1e1SFrank Piva extern int ublksrv_json_read_target_ulong_info(const char *jbuf,
715*94c4a1e1SFrank Piva 		const char *name, long *val);
716*94c4a1e1SFrank Piva 
717*94c4a1e1SFrank Piva /**
718*94c4a1e1SFrank Piva  * Serialize json buffer from target field with string type
719*94c4a1e1SFrank Piva  *
720*94c4a1e1SFrank Piva  * @param jbuf json buffer
721*94c4a1e1SFrank Piva  * @param len length of json buffer
722*94c4a1e1SFrank Piva  * @param name field name with string type
723*94c4a1e1SFrank Piva  * @param val field value with string type
724*94c4a1e1SFrank Piva  */
725*94c4a1e1SFrank Piva extern int ublksrv_json_write_target_str_info(char *jbuf, int len,
726*94c4a1e1SFrank Piva 		const char *name, const char *val);
727*94c4a1e1SFrank Piva 
728*94c4a1e1SFrank Piva extern int ublksrv_json_write_target_long_info(char *jbuf, int len,
729*94c4a1e1SFrank Piva 		const char *name, long val);
730*94c4a1e1SFrank Piva 
731*94c4a1e1SFrank Piva /**
732*94c4a1e1SFrank Piva  * Serialize json buffer from target field with ulong type
733*94c4a1e1SFrank Piva  *
734*94c4a1e1SFrank Piva  * @param jbuf json buffer
735*94c4a1e1SFrank Piva  * @param len length of json buffer
736*94c4a1e1SFrank Piva  * @param name field name with ulong type
737*94c4a1e1SFrank Piva  * @param val field value with ulong type
738*94c4a1e1SFrank Piva  */
739*94c4a1e1SFrank Piva extern int ublksrv_json_write_target_ulong_info(char *jbuf, int len,
740*94c4a1e1SFrank Piva 		const char *name, unsigned long val);
741*94c4a1e1SFrank Piva 
742*94c4a1e1SFrank Piva extern void ublksrv_json_dump(const char *jbuf);
743*94c4a1e1SFrank Piva 
744*94c4a1e1SFrank Piva /**
745*94c4a1e1SFrank Piva  * Deserialize json buffer to ublksrv_tgt_base_json instance
746*94c4a1e1SFrank Piva  *
747*94c4a1e1SFrank Piva  * @param jbuf json buffer
748*94c4a1e1SFrank Piva  * @param tgt ublksrv_tgt_base_json instance
749*94c4a1e1SFrank Piva  */
750*94c4a1e1SFrank Piva extern int ublksrv_json_read_target_base_info(const char *jbuf,
751*94c4a1e1SFrank Piva 		struct ublksrv_tgt_base_json *tgt);
752*94c4a1e1SFrank Piva 
753*94c4a1e1SFrank Piva /**
754*94c4a1e1SFrank Piva  * Serialize json buffer from ublksrv_tgt_base_json
755*94c4a1e1SFrank Piva  *
756*94c4a1e1SFrank Piva  * @param jbuf json buffer
757*94c4a1e1SFrank Piva  * @param len length of json buffer
758*94c4a1e1SFrank Piva  * @param tgt ublksrv_tgt_base_json instance
759*94c4a1e1SFrank Piva  */
760*94c4a1e1SFrank Piva extern int ublksrv_json_write_target_base_info(char *jbuf, int len,
761*94c4a1e1SFrank Piva 		const struct ublksrv_tgt_base_json *tgt);
762*94c4a1e1SFrank Piva 
763*94c4a1e1SFrank Piva /**
764*94c4a1e1SFrank Piva  * Deserialize json buffer to ublk_params instance
765*94c4a1e1SFrank Piva  *
766*94c4a1e1SFrank Piva  * @param p ublk_params instance
767*94c4a1e1SFrank Piva  * @param jbuf json buffer
768*94c4a1e1SFrank Piva  */
769*94c4a1e1SFrank Piva extern int ublksrv_json_read_params(struct ublk_params *p,
770*94c4a1e1SFrank Piva 		const char *jbuf);
771*94c4a1e1SFrank Piva 
772*94c4a1e1SFrank Piva /**
773*94c4a1e1SFrank Piva  * Serialize json buffer from ublk_params instance
774*94c4a1e1SFrank Piva  *
775*94c4a1e1SFrank Piva  * @param p ublk_params instance
776*94c4a1e1SFrank Piva  * @param jbuf json buffer
777*94c4a1e1SFrank Piva  * @param len length of json buffer
778*94c4a1e1SFrank Piva  */
779*94c4a1e1SFrank Piva extern int ublksrv_json_write_params(const struct ublk_params *p,
780*94c4a1e1SFrank Piva 		char *jbuf, int len);
781*94c4a1e1SFrank Piva extern int ublksrv_json_dump_params(const char *jbuf);
782*94c4a1e1SFrank Piva 
783*94c4a1e1SFrank Piva /**
784*94c4a1e1SFrank Piva  * Return actual length of the json buffer
785*94c4a1e1SFrank Piva  *
786*94c4a1e1SFrank Piva  * @param jbuf json buffer
787*94c4a1e1SFrank Piva  */
788*94c4a1e1SFrank Piva extern int ublksrv_json_get_length(const char *jbuf);
789*94c4a1e1SFrank Piva 
790*94c4a1e1SFrank Piva /** @} */ // end of ublksrv_json group
791*94c4a1e1SFrank Piva 
792*94c4a1e1SFrank Piva /**
793*94c4a1e1SFrank Piva  * \defgroup ublksrv_queue ublksrv queue API
794*94c4a1e1SFrank Piva  *
795*94c4a1e1SFrank Piva  * ublksrv queue level APIs
796*94c4a1e1SFrank Piva  *
797*94c4a1e1SFrank Piva  * All APIs in this group is supposed to be called in the queue context
798*94c4a1e1SFrank Piva  *
799*94c4a1e1SFrank Piva  *  @{
800*94c4a1e1SFrank Piva  */
801*94c4a1e1SFrank Piva 
802*94c4a1e1SFrank Piva /**
803*94c4a1e1SFrank Piva  * Return the specified io private data
804*94c4a1e1SFrank Piva  *
805*94c4a1e1SFrank Piva  * Each IO has unique tag, so we use tag to represent specified io.
806*94c4a1e1SFrank Piva  *
807*94c4a1e1SFrank Piva  * Inside ->init_tgt() callback, target code sets io private data
808*94c4a1e1SFrank Piva  * size via dev->tgt.io_data_size, then io private data will be allocated
809*94c4a1e1SFrank Piva  * in ublksrv_queue_init(). The allocated io private data is very useful
810*94c4a1e1SFrank Piva  * to store target specific io data, then runtime memory allocation in io
811*94c4a1e1SFrank Piva  * handling code path can be avoided.
812*94c4a1e1SFrank Piva  *
813*94c4a1e1SFrank Piva  * @param q the ublksrv queue instance
814*94c4a1e1SFrank Piva  * @param tag tag for this io
815*94c4a1e1SFrank Piva  */
816*94c4a1e1SFrank Piva extern void *ublksrv_io_private_data(const struct ublksrv_queue *q, int tag);
817*94c4a1e1SFrank Piva 
818*94c4a1e1SFrank Piva /**
819*94c4a1e1SFrank Piva  * Return the specified io generic io data
820*94c4a1e1SFrank Piva  *
821*94c4a1e1SFrank Piva  * Each IO has unique tag, so we use tag to represent specified io.
822*94c4a1e1SFrank Piva  *
823*94c4a1e1SFrank Piva  * @param q the ublksrv queue instance
824*94c4a1e1SFrank Piva  * @param tag tag for this io
825*94c4a1e1SFrank Piva  * @return 'struct ublk_io_data' instance, which is for storing io descriptor,
826*94c4a1e1SFrank Piva  * 	tag, and private data
827*94c4a1e1SFrank Piva  */
828*94c4a1e1SFrank Piva extern const struct ublk_io_data *ublksrv_queue_get_io_data(
829*94c4a1e1SFrank Piva 		const struct ublksrv_queue *q, int tag);
830*94c4a1e1SFrank Piva 
831*94c4a1e1SFrank Piva /**
832*94c4a1e1SFrank Piva  * Return pre-allocated io buffer
833*94c4a1e1SFrank Piva  *
834*94c4a1e1SFrank Piva  * Each IO has unique tag, so we use tag to represent specified io.
835*94c4a1e1SFrank Piva  *
836*94c4a1e1SFrank Piva  * @param q the ublksrv queue instance
837*94c4a1e1SFrank Piva  * @param tag tag for this io
838*94c4a1e1SFrank Piva  * @return pre-allocated io buffer for this io
839*94c4a1e1SFrank Piva  */
840*94c4a1e1SFrank Piva extern void *ublksrv_queue_get_io_buf(const struct ublksrv_queue *q, int tag);
841*94c4a1e1SFrank Piva 
842*94c4a1e1SFrank Piva /**
843*94c4a1e1SFrank Piva  * Return current queue state
844*94c4a1e1SFrank Piva  *
845*94c4a1e1SFrank Piva  * queue state is usually for debug purpose
846*94c4a1e1SFrank Piva  *
847*94c4a1e1SFrank Piva  * @param q the ublksrv queue instance
848*94c4a1e1SFrank Piva  * @return queue current state
849*94c4a1e1SFrank Piva  */
850*94c4a1e1SFrank Piva extern unsigned int ublksrv_queue_state(const struct ublksrv_queue *q);
851*94c4a1e1SFrank Piva 
852*94c4a1e1SFrank Piva /**
853*94c4a1e1SFrank Piva  * Allocate and initialize ublksrv queue instance
854*94c4a1e1SFrank Piva  *
855*94c4a1e1SFrank Piva  * @param dev the ublksrv device instance
856*94c4a1e1SFrank Piva  * @param q_id queue id
857*94c4a1e1SFrank Piva  * @param queue_data queue private data
858*94c4a1e1SFrank Piva  */
859*94c4a1e1SFrank Piva extern const struct ublksrv_queue *ublksrv_queue_init(const struct ublksrv_dev *dev,
860*94c4a1e1SFrank Piva 		unsigned short q_id, void *queue_data);
861*94c4a1e1SFrank Piva 
862*94c4a1e1SFrank Piva /**
863*94c4a1e1SFrank Piva  * Deinit & free ublksrv queue instance
864*94c4a1e1SFrank Piva  *
865*94c4a1e1SFrank Piva  * @param q the ublksrv queue instance
866*94c4a1e1SFrank Piva  */
867*94c4a1e1SFrank Piva extern void ublksrv_queue_deinit(const struct ublksrv_queue *q);
868*94c4a1e1SFrank Piva 
869*94c4a1e1SFrank Piva /**
870*94c4a1e1SFrank Piva  * Return how many unconsumed cqes in CQ of queue uring
871*94c4a1e1SFrank Piva  *
872*94c4a1e1SFrank Piva  * @param q the ublksrv queue instance
873*94c4a1e1SFrank Piva  *
874*94c4a1e1SFrank Piva  * Return -1 if uring isn't setup correctly
875*94c4a1e1SFrank Piva  */
876*94c4a1e1SFrank Piva extern int ublksrv_queue_unconsumed_cqes(const struct ublksrv_queue *q);
877*94c4a1e1SFrank Piva 
878*94c4a1e1SFrank Piva extern int ublksrv_queue_handled_event(const struct ublksrv_queue *q);
879*94c4a1e1SFrank Piva extern int ublksrv_queue_send_event(const struct ublksrv_queue *q);
880*94c4a1e1SFrank Piva 
881*94c4a1e1SFrank Piva /**
882*94c4a1e1SFrank Piva  * Return the specified queue instance by ublksrv device and qid
883*94c4a1e1SFrank Piva  *
884*94c4a1e1SFrank Piva  * Retrieve queue instance by ublksrv device and queue id
885*94c4a1e1SFrank Piva  *
886*94c4a1e1SFrank Piva  * @param dev the ublksrv device instance
887*94c4a1e1SFrank Piva  * @param q_id queue id
888*94c4a1e1SFrank Piva  */
889*94c4a1e1SFrank Piva extern const struct ublksrv_queue *ublksrv_get_queue(const struct ublksrv_dev *dev,
890*94c4a1e1SFrank Piva 		int q_id);
891*94c4a1e1SFrank Piva 
892*94c4a1e1SFrank Piva /**
893*94c4a1e1SFrank Piva  * Process target IO & IO command from this queue's io_uring
894*94c4a1e1SFrank Piva  *
895*94c4a1e1SFrank Piva  * Handle incoming io command by calling target ->handle_io_async(), or
896*94c4a1e1SFrank Piva  * call ->tgt_io_done() if target IO is completed.
897*94c4a1e1SFrank Piva  *
898*94c4a1e1SFrank Piva  * It is the engine of libulksrv, almost everything is driven by this
899*94c4a1e1SFrank Piva  * API.
900*94c4a1e1SFrank Piva  *
901*94c4a1e1SFrank Piva  * @param q the ublksrv queue instance
902*94c4a1e1SFrank Piva  */
903*94c4a1e1SFrank Piva extern int ublksrv_process_io(const struct ublksrv_queue *q);
904*94c4a1e1SFrank Piva 
905*94c4a1e1SFrank Piva /**
906*94c4a1e1SFrank Piva  * Complete specified io with result of 'res'
907*94c4a1e1SFrank Piva  *
908*94c4a1e1SFrank Piva  * This API will tell ublk driver via /dev/ublkcN that this IO is completed.
909*94c4a1e1SFrank Piva  *
910*94c4a1e1SFrank Piva  * @param q the ublksrv queue instance
911*94c4a1e1SFrank Piva  * @param tag the io to be completed
912*94c4a1e1SFrank Piva  * @param res io result
913*94c4a1e1SFrank Piva  */
914*94c4a1e1SFrank Piva extern int ublksrv_complete_io(const struct ublksrv_queue *q, unsigned tag, int res);
915*94c4a1e1SFrank Piva /** @} */ // end of ublksrv_queue group
916*94c4a1e1SFrank Piva 
917*94c4a1e1SFrank Piva #ifdef __cplusplus
918*94c4a1e1SFrank Piva }
919*94c4a1e1SFrank Piva #endif
920*94c4a1e1SFrank Piva #endif
921