rpma: add librpma_apm_* and librpma_gpspm_* engines
[fio.git] / engines / librpma_fio.h
CommitLineData
e4c4625f
JM
1/*
2 * librpma_fio: librpma_apm and librpma_gpspm engines' common header.
3 *
4 * Copyright 2021, Intel Corporation
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License,
8 * version 2 as published by the Free Software Foundation..
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#ifndef LIBRPMA_FIO_H
17#define LIBRPMA_FIO_H 1
18
19#include "../fio.h"
20#include "../optgroup.h"
21
22#include <librpma.h>
23
24/* servers' and clients' common */
25
26#define librpma_td_verror(td, err, func) \
27 td_vmsg((td), (err), rpma_err_2str(err), (func))
28
29/* ceil(a / b) = (a + b - 1) / b */
30#define LIBRPMA_FIO_CEIL(a, b) (((a) + (b) - 1) / (b))
31
32/* common option structure for server and client */
33struct librpma_fio_options_values {
34 /*
35 * FIO considers .off1 == 0 absent so the first meaningful field has to
36 * have padding ahead of it.
37 */
38 void *pad;
39 char *server_ip;
40 /* base server listening port */
41 char *port;
42 /* Direct Write to PMem is possible */
43 unsigned int direct_write_to_pmem;
44};
45
46extern struct fio_option librpma_fio_options[];
47
48/*
49 * Limited by the maximum length of the private data
50 * for rdma_connect() in case of RDMA_PS_TCP (28 bytes).
51 */
52#define LIBRPMA_FIO_DESCRIPTOR_MAX_SIZE 24
53
54struct librpma_fio_workspace {
55 uint16_t max_msg_num; /* # of RQ slots */
56 uint8_t direct_write_to_pmem; /* Direct Write to PMem is possible */
57 uint8_t mr_desc_size; /* size of mr_desc in descriptor[] */
58 /* buffer containing mr_desc */
59 char descriptor[LIBRPMA_FIO_DESCRIPTOR_MAX_SIZE];
60};
61
62#define LIBRPMA_FIO_PORT_STR_LEN_MAX 12
63
64int librpma_fio_td_port(const char *port_base_str, struct thread_data *td,
65 char *port_out);
66
67struct librpma_fio_mem {
68 /* memory buffer */
69 char *mem_ptr;
70
71 /* size of the mapped persistent memory */
72 size_t size_mmap;
73};
74
75char *librpma_fio_allocate_dram(struct thread_data *td, size_t size,
76 struct librpma_fio_mem *mem);
77
78char *librpma_fio_allocate_pmem(struct thread_data *td, const char *filename,
79 size_t size, struct librpma_fio_mem *mem);
80
81void librpma_fio_free(struct librpma_fio_mem *mem);
82
83/* clients' common */
84
85typedef int (*librpma_fio_flush_t)(struct thread_data *td,
86 struct io_u *first_io_u, struct io_u *last_io_u,
87 unsigned long long int len);
88
89/*
90 * RETURN VALUE
91 * - ( 1) - on success
92 * - ( 0) - skip
93 * - (-1) - on error
94 */
95typedef int (*librpma_fio_get_io_u_index_t)(struct rpma_completion *cmpl,
96 unsigned int *io_u_index);
97
98struct librpma_fio_client_data {
99 struct rpma_peer *peer;
100 struct rpma_conn *conn;
101
102 /* aligned td->orig_buffer */
103 char *orig_buffer_aligned;
104
105 /* ious's base address memory registration (cd->orig_buffer_aligned) */
106 struct rpma_mr_local *orig_mr;
107
108 struct librpma_fio_workspace *ws;
109
110 /* a server's memory representation */
111 struct rpma_mr_remote *server_mr;
112 enum rpma_flush_type server_mr_flush_type;
113
114 /* remote workspace description */
115 size_t ws_size;
116
117 /* in-memory queues */
118 struct io_u **io_us_queued;
119 int io_u_queued_nr;
120 struct io_u **io_us_flight;
121 int io_u_flight_nr;
122 struct io_u **io_us_completed;
123 int io_u_completed_nr;
124
125 /* SQ control. Note: all of them have to be kept in sync. */
126 uint32_t op_send_posted;
127 uint32_t op_send_completed;
128 uint32_t op_recv_completed;
129
130 librpma_fio_flush_t flush;
131 librpma_fio_get_io_u_index_t get_io_u_index;
132
133 /* engine-specific client data */
134 void *client_data;
135};
136
137int librpma_fio_client_init(struct thread_data *td,
138 struct rpma_conn_cfg *cfg);
139void librpma_fio_client_cleanup(struct thread_data *td);
140
141int librpma_fio_file_nop(struct thread_data *td, struct fio_file *f);
142int librpma_fio_client_get_file_size(struct thread_data *td,
143 struct fio_file *f);
144
145int librpma_fio_client_post_init(struct thread_data *td);
146
147enum fio_q_status librpma_fio_client_queue(struct thread_data *td,
148 struct io_u *io_u);
149
150int librpma_fio_client_commit(struct thread_data *td);
151
152int librpma_fio_client_getevents(struct thread_data *td, unsigned int min,
153 unsigned int max, const struct timespec *t);
154
155struct io_u *librpma_fio_client_event(struct thread_data *td, int event);
156
157char *librpma_fio_client_errdetails(struct io_u *io_u);
158
159static inline int librpma_fio_client_io_read(struct thread_data *td,
160 struct io_u *io_u, int flags)
161{
162 struct librpma_fio_client_data *ccd = td->io_ops_data;
163 size_t dst_offset = (char *)(io_u->xfer_buf) - ccd->orig_buffer_aligned;
164 size_t src_offset = io_u->offset;
165 int ret;
166
167 if ((ret = rpma_read(ccd->conn, ccd->orig_mr, dst_offset,
168 ccd->server_mr, src_offset, io_u->xfer_buflen,
169 flags, (void *)(uintptr_t)io_u->index))) {
170 librpma_td_verror(td, ret, "rpma_read");
171 return -1;
172 }
173
174 return 0;
175}
176
177static inline int librpma_fio_client_io_write(struct thread_data *td,
178 struct io_u *io_u)
179{
180 struct librpma_fio_client_data *ccd = td->io_ops_data;
181 size_t src_offset = (char *)(io_u->xfer_buf) - ccd->orig_buffer_aligned;
182 size_t dst_offset = io_u->offset;
183 int ret;
184
185 if ((ret = rpma_write(ccd->conn, ccd->server_mr, dst_offset,
186 ccd->orig_mr, src_offset, io_u->xfer_buflen,
187 RPMA_F_COMPLETION_ON_ERROR,
188 (void *)(uintptr_t)io_u->index))) {
189 librpma_td_verror(td, ret, "rpma_write");
190 return -1;
191 }
192
193 return 0;
194}
195
196static inline int librpma_fio_client_io_complete_all_sends(
197 struct thread_data *td)
198{
199 struct librpma_fio_client_data *ccd = td->io_ops_data;
200 struct rpma_completion cmpl;
201 int ret;
202
203 while (ccd->op_send_posted != ccd->op_send_completed) {
204 /* get a completion */
205 ret = rpma_conn_completion_get(ccd->conn, &cmpl);
206 if (ret == RPMA_E_NO_COMPLETION) {
207 /* lack of completion is not an error */
208 continue;
209 } else if (ret != 0) {
210 /* an error occurred */
211 librpma_td_verror(td, ret, "rpma_conn_completion_get");
212 break;
213 }
214
215 if (cmpl.op_status != IBV_WC_SUCCESS)
216 return -1;
217
218 if (cmpl.op == RPMA_OP_SEND)
219 ++ccd->op_send_completed;
220 else {
221 log_err(
222 "A completion other than RPMA_OP_SEND got during cleaning up the CQ from SENDs\n");
223 return -1;
224 }
225 }
226
227 /*
228 * All posted SENDs are completed and RECVs for them (responses) are
229 * completed. This is the initial situation so the counters are reset.
230 */
231 if (ccd->op_send_posted == ccd->op_send_completed &&
232 ccd->op_send_completed == ccd->op_recv_completed) {
233 ccd->op_send_posted = 0;
234 ccd->op_send_completed = 0;
235 ccd->op_recv_completed = 0;
236 }
237
238 return 0;
239}
240
241/* servers' common */
242
243typedef int (*librpma_fio_prepare_connection_t)(
244 struct thread_data *td,
245 struct rpma_conn_req *conn_req);
246
247struct librpma_fio_server_data {
248 struct rpma_peer *peer;
249
250 /* resources of an incoming connection */
251 struct rpma_conn *conn;
252
253 char *ws_ptr;
254 struct rpma_mr_local *ws_mr;
255 struct librpma_fio_mem mem;
256
257 /* engine-specific server data */
258 void *server_data;
259
260 librpma_fio_prepare_connection_t prepare_connection;
261};
262
263int librpma_fio_server_init(struct thread_data *td);
264
265void librpma_fio_server_cleanup(struct thread_data *td);
266
267int librpma_fio_server_open_file(struct thread_data *td,
268 struct fio_file *f, struct rpma_conn_cfg *cfg);
269
270int librpma_fio_server_close_file(struct thread_data *td,
271 struct fio_file *f);
272
273#endif /* LIBRPMA_FIO_H */