1*94c4a1e1SFrank Piva // SPDX-License-Identifier: MIT or LGPL-2.1-only
2*94c4a1e1SFrank Piva
3*94c4a1e1SFrank Piva #ifndef UBLKSRV_AIO_INC_H
4*94c4a1e1SFrank Piva #define UBLKSRV_AIO_INC_H
5*94c4a1e1SFrank Piva
6*94c4a1e1SFrank Piva /*
7*94c4a1e1SFrank Piva * APIs for offloading IO handling in non-ublksrv context, refer to
8*94c4a1e1SFrank Piva * demo_event.c for how to use these APIs
9*94c4a1e1SFrank Piva */
10*94c4a1e1SFrank Piva
11*94c4a1e1SFrank Piva #ifdef __cplusplus
12*94c4a1e1SFrank Piva extern "C" {
13*94c4a1e1SFrank Piva #endif
14*94c4a1e1SFrank Piva
15*94c4a1e1SFrank Piva struct ublksrv_aio_ctx;
16*94c4a1e1SFrank Piva struct ublksrv_aio;
17*94c4a1e1SFrank Piva
18*94c4a1e1SFrank Piva /*
19*94c4a1e1SFrank Piva * return value:
20*94c4a1e1SFrank Piva *
21*94c4a1e1SFrank Piva * > 0 : the request is done
22*94c4a1e1SFrank Piva * = 0 : submitted successfully, but not done
23*94c4a1e1SFrank Piva * < 0 : submitted not successfully
24*94c4a1e1SFrank Piva */
25*94c4a1e1SFrank Piva typedef int (ublksrv_aio_submit_fn)(struct ublksrv_aio_ctx *ctx,
26*94c4a1e1SFrank Piva struct ublksrv_aio *req);
27*94c4a1e1SFrank Piva
28*94c4a1e1SFrank Piva #define ublksrv_aio_qid(val) ((val >> 13) & 0x7ff)
29*94c4a1e1SFrank Piva #define ublksrv_aio_tag(val) (val & 0x1fff)
30*94c4a1e1SFrank Piva
ublksrv_aio_pid_tag(unsigned qid,unsigned tag)31*94c4a1e1SFrank Piva static inline unsigned ublksrv_aio_pid_tag(unsigned qid, unsigned tag)
32*94c4a1e1SFrank Piva {
33*94c4a1e1SFrank Piva return tag | (qid << 13);
34*94c4a1e1SFrank Piva }
35*94c4a1e1SFrank Piva
36*94c4a1e1SFrank Piva struct ublksrv_aio {
37*94c4a1e1SFrank Piva struct ublksrv_io_desc io;
38*94c4a1e1SFrank Piva union {
39*94c4a1e1SFrank Piva int res; /* output */
40*94c4a1e1SFrank Piva int fd; /* input */
41*94c4a1e1SFrank Piva };
42*94c4a1e1SFrank Piva
43*94c4a1e1SFrank Piva /* reserved 31 ~ 24, bit 23 ~ 13: qid, bit 12 ~ 0: tag */
44*94c4a1e1SFrank Piva unsigned id;
45*94c4a1e1SFrank Piva struct ublksrv_aio *next;
46*94c4a1e1SFrank Piva unsigned long data[0];
47*94c4a1e1SFrank Piva };
48*94c4a1e1SFrank Piva
49*94c4a1e1SFrank Piva struct aio_list {
50*94c4a1e1SFrank Piva struct ublksrv_aio *head, *tail;
51*94c4a1e1SFrank Piva };
52*94c4a1e1SFrank Piva
aio_list_init(struct aio_list * al)53*94c4a1e1SFrank Piva static inline void aio_list_init(struct aio_list *al)
54*94c4a1e1SFrank Piva {
55*94c4a1e1SFrank Piva al->head = al->tail = NULL;
56*94c4a1e1SFrank Piva }
57*94c4a1e1SFrank Piva
aio_list_add(struct aio_list * al,struct ublksrv_aio * io)58*94c4a1e1SFrank Piva static inline void aio_list_add(struct aio_list *al, struct ublksrv_aio *io)
59*94c4a1e1SFrank Piva {
60*94c4a1e1SFrank Piva io->next = NULL;
61*94c4a1e1SFrank Piva
62*94c4a1e1SFrank Piva if (al->tail)
63*94c4a1e1SFrank Piva al->tail->next = io;
64*94c4a1e1SFrank Piva else
65*94c4a1e1SFrank Piva al->head = io;
66*94c4a1e1SFrank Piva al->tail = io;
67*94c4a1e1SFrank Piva }
68*94c4a1e1SFrank Piva
aio_list_splice(struct aio_list * n,struct aio_list * head)69*94c4a1e1SFrank Piva static inline void aio_list_splice(struct aio_list *n,
70*94c4a1e1SFrank Piva struct aio_list *head)
71*94c4a1e1SFrank Piva {
72*94c4a1e1SFrank Piva if (!n->head)
73*94c4a1e1SFrank Piva return;
74*94c4a1e1SFrank Piva
75*94c4a1e1SFrank Piva if (head->tail)
76*94c4a1e1SFrank Piva head->tail->next = n->head;
77*94c4a1e1SFrank Piva else
78*94c4a1e1SFrank Piva head->head = n->head;
79*94c4a1e1SFrank Piva
80*94c4a1e1SFrank Piva head->tail = n->tail;
81*94c4a1e1SFrank Piva
82*94c4a1e1SFrank Piva aio_list_init(n);
83*94c4a1e1SFrank Piva }
84*94c4a1e1SFrank Piva
aio_list_empty(const struct aio_list * al)85*94c4a1e1SFrank Piva static inline int aio_list_empty(const struct aio_list *al)
86*94c4a1e1SFrank Piva {
87*94c4a1e1SFrank Piva return al->head == NULL;
88*94c4a1e1SFrank Piva }
89*94c4a1e1SFrank Piva
aio_list_pop(struct aio_list * al)90*94c4a1e1SFrank Piva static inline struct ublksrv_aio *aio_list_pop(struct aio_list *al)
91*94c4a1e1SFrank Piva {
92*94c4a1e1SFrank Piva struct ublksrv_aio *io = al->head;
93*94c4a1e1SFrank Piva
94*94c4a1e1SFrank Piva if (io) {
95*94c4a1e1SFrank Piva al->head = io->next;
96*94c4a1e1SFrank Piva if (!al->head)
97*94c4a1e1SFrank Piva al->tail = NULL;
98*94c4a1e1SFrank Piva
99*94c4a1e1SFrank Piva io->next = NULL;
100*94c4a1e1SFrank Piva }
101*94c4a1e1SFrank Piva
102*94c4a1e1SFrank Piva return io;
103*94c4a1e1SFrank Piva }
104*94c4a1e1SFrank Piva
105*94c4a1e1SFrank Piva struct ublksrv_aio_list {
106*94c4a1e1SFrank Piva pthread_spinlock_t lock;
107*94c4a1e1SFrank Piva struct aio_list list;
108*94c4a1e1SFrank Piva };
109*94c4a1e1SFrank Piva
ublksrv_aio_init_list(struct ublksrv_aio_list * l)110*94c4a1e1SFrank Piva static inline void ublksrv_aio_init_list(struct ublksrv_aio_list *l)
111*94c4a1e1SFrank Piva {
112*94c4a1e1SFrank Piva pthread_spin_init(&l->lock, PTHREAD_PROCESS_PRIVATE);
113*94c4a1e1SFrank Piva aio_list_init(&l->list);
114*94c4a1e1SFrank Piva }
115*94c4a1e1SFrank Piva
116*94c4a1e1SFrank Piva struct ublksrv_aio_ctx *ublksrv_aio_ctx_init(const struct ublksrv_dev *dev,
117*94c4a1e1SFrank Piva unsigned flags);
118*94c4a1e1SFrank Piva void ublksrv_aio_ctx_shutdown(struct ublksrv_aio_ctx *ctx);
119*94c4a1e1SFrank Piva void ublksrv_aio_ctx_deinit(struct ublksrv_aio_ctx *ctx);
120*94c4a1e1SFrank Piva struct ublksrv_aio *ublksrv_aio_alloc_req(struct ublksrv_aio_ctx *ctx,
121*94c4a1e1SFrank Piva int payload_size);
122*94c4a1e1SFrank Piva void ublksrv_aio_free_req(struct ublksrv_aio_ctx *ctx, struct ublksrv_aio *req);
123*94c4a1e1SFrank Piva void ublksrv_aio_submit_req(struct ublksrv_aio_ctx *ctx,
124*94c4a1e1SFrank Piva const struct ublksrv_queue *q, struct ublksrv_aio *req);
125*94c4a1e1SFrank Piva void ublksrv_aio_get_completed_reqs(struct ublksrv_aio_ctx *ctx,
126*94c4a1e1SFrank Piva const struct ublksrv_queue *q,
127*94c4a1e1SFrank Piva struct aio_list *al);
128*94c4a1e1SFrank Piva int ublksrv_aio_submit_worker(struct ublksrv_aio_ctx *ctx,
129*94c4a1e1SFrank Piva ublksrv_aio_submit_fn *fn, struct aio_list *submitted);
130*94c4a1e1SFrank Piva void ublksrv_aio_complete_worker(struct ublksrv_aio_ctx *ctx,
131*94c4a1e1SFrank Piva struct aio_list *completed);
132*94c4a1e1SFrank Piva void ublksrv_aio_handle_event(struct ublksrv_aio_ctx *ctx,
133*94c4a1e1SFrank Piva const struct ublksrv_queue *q);
134*94c4a1e1SFrank Piva int ublksrv_aio_get_efd(struct ublksrv_aio_ctx *ctx);
135*94c4a1e1SFrank Piva void ublksrv_aio_set_ctx_data(struct ublksrv_aio_ctx *ctx, void *data);
136*94c4a1e1SFrank Piva void *ublksrv_aio_get_ctx_data(struct ublksrv_aio_ctx *ctx);
137*94c4a1e1SFrank Piva bool ublksrv_aio_ctx_dead(struct ublksrv_aio_ctx *ctx);
138*94c4a1e1SFrank Piva const struct ublksrv_dev *ublksrv_aio_get_dev(struct ublksrv_aio_ctx *ctx);
139*94c4a1e1SFrank Piva
140*94c4a1e1SFrank Piva #ifdef __cplusplus
141*94c4a1e1SFrank Piva }
142*94c4a1e1SFrank Piva #endif
143*94c4a1e1SFrank Piva #endif
144