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