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