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