2 * librpma_fio: librpma_apm and librpma_gpspm engines' common header.
4 * Copyright 2021, Intel Corporation
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..
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.
17 #define LIBRPMA_FIO_H 1
20 #include "../optgroup.h"
24 /* servers' and clients' common */
26 #define librpma_td_verror(td, err, func) \
27 td_vmsg((td), (err), rpma_err_2str(err), (func))
29 /* ceil(a / b) = (a + b - 1) / b */
30 #define LIBRPMA_FIO_CEIL(a, b) (((a) + (b) - 1) / (b))
32 /* common option structure for server and client */
33 struct librpma_fio_options_values {
35 * FIO considers .off1 == 0 absent so the first meaningful field has to
36 * have padding ahead of it.
40 /* base server listening port */
42 /* Direct Write to PMem is possible */
43 unsigned int direct_write_to_pmem;
44 /* Set to 0 to wait for completion instead of busy-wait polling completion. */
45 unsigned int busy_wait_polling;
48 extern struct fio_option librpma_fio_options[];
51 * Limited by the maximum length of the private data
52 * for rdma_connect() in case of RDMA_PS_TCP (28 bytes).
54 #define LIBRPMA_FIO_DESCRIPTOR_MAX_SIZE 24
56 struct librpma_fio_workspace {
57 uint16_t max_msg_num; /* # of RQ slots */
58 uint8_t direct_write_to_pmem; /* Direct Write to PMem is possible */
59 uint8_t mr_desc_size; /* size of mr_desc in descriptor[] */
60 /* buffer containing mr_desc */
61 char descriptor[LIBRPMA_FIO_DESCRIPTOR_MAX_SIZE];
64 #define LIBRPMA_FIO_PORT_STR_LEN_MAX 12
66 int librpma_fio_td_port(const char *port_base_str, struct thread_data *td,
69 struct librpma_fio_mem {
73 /* size of the mapped persistent memory */
77 char *librpma_fio_allocate_dram(struct thread_data *td, size_t size,
78 struct librpma_fio_mem *mem);
80 char *librpma_fio_allocate_pmem(struct thread_data *td, struct fio_file *f,
81 size_t size, struct librpma_fio_mem *mem);
83 void librpma_fio_free(struct librpma_fio_mem *mem);
87 typedef int (*librpma_fio_flush_t)(struct thread_data *td,
88 struct io_u *first_io_u, struct io_u *last_io_u,
89 unsigned long long int len);
97 typedef int (*librpma_fio_get_io_u_index_t)(struct ibv_wc *wc,
98 unsigned int *io_u_index);
100 struct librpma_fio_client_data {
101 struct rpma_peer *peer;
102 struct rpma_conn *conn;
105 /* aligned td->orig_buffer */
106 char *orig_buffer_aligned;
108 /* ious's base address memory registration (cd->orig_buffer_aligned) */
109 struct rpma_mr_local *orig_mr;
111 struct librpma_fio_workspace *ws;
113 /* a server's memory representation */
114 struct rpma_mr_remote *server_mr;
115 enum rpma_flush_type server_mr_flush_type;
117 /* remote workspace description */
120 /* in-memory queues */
121 struct io_u **io_us_queued;
123 struct io_u **io_us_flight;
125 struct io_u **io_us_completed;
126 int io_u_completed_nr;
128 /* SQ control. Note: all of them have to be kept in sync. */
129 uint32_t op_send_posted;
130 uint32_t op_send_completed;
131 uint32_t op_recv_completed;
133 librpma_fio_flush_t flush;
134 librpma_fio_get_io_u_index_t get_io_u_index;
136 /* engine-specific client data */
140 int librpma_fio_client_init(struct thread_data *td,
141 struct rpma_conn_cfg *cfg);
142 void librpma_fio_client_cleanup(struct thread_data *td);
144 int librpma_fio_file_nop(struct thread_data *td, struct fio_file *f);
145 int librpma_fio_client_get_file_size(struct thread_data *td,
148 int librpma_fio_client_post_init(struct thread_data *td);
150 enum fio_q_status librpma_fio_client_queue(struct thread_data *td,
153 int librpma_fio_client_commit(struct thread_data *td);
155 int librpma_fio_client_getevents(struct thread_data *td, unsigned int min,
156 unsigned int max, const struct timespec *t);
158 struct io_u *librpma_fio_client_event(struct thread_data *td, int event);
160 char *librpma_fio_client_errdetails(struct io_u *io_u);
162 static inline int librpma_fio_client_io_read(struct thread_data *td,
163 struct io_u *io_u, int flags)
165 struct librpma_fio_client_data *ccd = td->io_ops_data;
166 size_t dst_offset = (char *)(io_u->xfer_buf) - ccd->orig_buffer_aligned;
167 size_t src_offset = io_u->offset;
170 if ((ret = rpma_read(ccd->conn, ccd->orig_mr, dst_offset,
171 ccd->server_mr, src_offset, io_u->xfer_buflen,
172 flags, (void *)(uintptr_t)io_u->index))) {
173 librpma_td_verror(td, ret, "rpma_read");
180 static inline int librpma_fio_client_io_write(struct thread_data *td,
183 struct librpma_fio_client_data *ccd = td->io_ops_data;
184 size_t src_offset = (char *)(io_u->xfer_buf) - ccd->orig_buffer_aligned;
185 size_t dst_offset = io_u->offset;
188 if ((ret = rpma_write(ccd->conn, ccd->server_mr, dst_offset,
189 ccd->orig_mr, src_offset, io_u->xfer_buflen,
190 RPMA_F_COMPLETION_ON_ERROR,
191 (void *)(uintptr_t)io_u->index))) {
192 librpma_td_verror(td, ret, "rpma_write");
199 static inline int librpma_fio_client_io_complete_all_sends(
200 struct thread_data *td)
202 struct librpma_fio_client_data *ccd = td->io_ops_data;
206 while (ccd->op_send_posted != ccd->op_send_completed) {
207 /* get a completion */
208 ret = rpma_cq_get_wc(ccd->cq, 1, &wc, NULL);
209 if (ret == RPMA_E_NO_COMPLETION) {
210 /* lack of completion is not an error */
212 } else if (ret != 0) {
213 /* an error occurred */
214 librpma_td_verror(td, ret, "rpma_cq_get_wc");
218 if (wc.status != IBV_WC_SUCCESS)
221 if (wc.opcode == IBV_WC_SEND)
222 ++ccd->op_send_completed;
225 "A completion other than IBV_WC_SEND got during cleaning up the CQ from SENDs\n");
231 * All posted SENDs are completed and RECVs for them (responses) are
232 * completed. This is the initial situation so the counters are reset.
234 if (ccd->op_send_posted == ccd->op_send_completed &&
235 ccd->op_send_completed == ccd->op_recv_completed) {
236 ccd->op_send_posted = 0;
237 ccd->op_send_completed = 0;
238 ccd->op_recv_completed = 0;
244 /* servers' common */
246 typedef int (*librpma_fio_prepare_connection_t)(
247 struct thread_data *td,
248 struct rpma_conn_req *conn_req);
250 struct librpma_fio_server_data {
251 struct rpma_peer *peer;
253 /* resources of an incoming connection */
254 struct rpma_conn *conn;
258 struct rpma_mr_local *ws_mr;
259 struct librpma_fio_mem mem;
261 /* engine-specific server data */
264 librpma_fio_prepare_connection_t prepare_connection;
267 int librpma_fio_server_init(struct thread_data *td);
269 void librpma_fio_server_cleanup(struct thread_data *td);
271 int librpma_fio_server_open_file(struct thread_data *td,
272 struct fio_file *f, struct rpma_conn_cfg *cfg);
274 int librpma_fio_server_close_file(struct thread_data *td,
277 #endif /* LIBRPMA_FIO_H */