#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
-#include <sys/poll.h>
+#include <poll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
struct thread_data *td;
unsigned int port;
enum rdma_io_mode verb;
+ char *bindname;
};
static int str_hostname_cb(void *data, const char *input)
.category = FIO_OPT_C_ENGINE,
.group = FIO_OPT_G_RDMA,
},
+ {
+ .name = "bindname",
+ .lname = "rdma engine bindname",
+ .type = FIO_OPT_STR_STORE,
+ .off1 = offsetof(struct rdmaio_options, bindname),
+ .help = "Bind for RDMA IO engine",
+ .def = "",
+ .category = FIO_OPT_C_ENGINE,
+ .group = FIO_OPT_G_RDMA,
+ },
{
.name = "port",
.lname = "rdma engine port",
rd->rmt_nr = ntohl(rd->recv_buf.nr);
for (i = 0; i < rd->rmt_nr; i++) {
- rd->rmt_us[i].buf = be64_to_cpu(rd->recv_buf.rmt_us[i].buf);
+ rd->rmt_us[i].buf = __be64_to_cpu(
+ rd->recv_buf.rmt_us[i].buf);
rd->rmt_us[i].rkey = ntohl(rd->recv_buf.rmt_us[i].rkey);
rd->rmt_us[i].size = ntohl(rd->recv_buf.rmt_us[i].size);
return i;
}
-static int fio_rdmaio_queue(struct thread_data *td, struct io_u *io_u)
+static enum fio_q_status fio_rdmaio_queue(struct thread_data *td,
+ struct io_u *io_u)
{
struct rdmaio_data *rd = td->io_ops_data;
memcpy(&io_u->issue_time, &now, sizeof(now));
io_u_queued(td, io_u);
}
+
+ /*
+ * only used for iolog
+ */
+ if (td->o.read_iolog_file)
+ memcpy(&td->last_issue, &now, sizeof(now));
}
static int fio_rdmaio_commit(struct thread_data *td)
ret = fio_rdmaio_send(td, io_us, rd->io_u_queued_nr);
else if (!rd->is_client)
ret = fio_rdmaio_recv(td, io_us, rd->io_u_queued_nr);
- else
- ret = 0; /* must be a SYNC */
if (ret > 0) {
fio_rdmaio_queued(td, io_us, ret);
return 0;
}
+static int aton(struct thread_data *td, const char *host,
+ struct sockaddr_in *addr)
+{
+ if (inet_aton(host, &addr->sin_addr) != 1) {
+ struct hostent *hent;
+
+ hent = gethostbyname(host);
+ if (!hent) {
+ td_verror(td, errno, "gethostbyname");
+ return 1;
+ }
+
+ memcpy(&addr->sin_addr, hent->h_addr, 4);
+ }
+ return 0;
+}
+
static int fio_rdmaio_setup_connect(struct thread_data *td, const char *host,
unsigned short port)
{
struct rdmaio_data *rd = td->io_ops_data;
+ struct rdmaio_options *o = td->eo;
+ struct sockaddr_storage addrb;
struct ibv_recv_wr *bad_wr;
int err;
rd->addr.sin_family = AF_INET;
rd->addr.sin_port = htons(port);
- if (inet_aton(host, &rd->addr.sin_addr) != 1) {
- struct hostent *hent;
+ err = aton(td, host, &rd->addr);
+ if (err)
+ return err;
- hent = gethostbyname(host);
- if (!hent) {
- td_verror(td, errno, "gethostbyname");
- return 1;
- }
+ /* resolve route */
+ if (o->bindname && strlen(o->bindname)) {
+ addrb.ss_family = AF_INET;
+ err = aton(td, o->bindname, (struct sockaddr_in *)&addrb);
+ if (err)
+ return err;
+ err = rdma_resolve_addr(rd->cm_id, (struct sockaddr *)&addrb,
+ (struct sockaddr *)&rd->addr, 2000);
- memcpy(&rd->addr.sin_addr, hent->h_addr, 4);
+ } else {
+ err = rdma_resolve_addr(rd->cm_id, NULL,
+ (struct sockaddr *)&rd->addr, 2000);
}
- /* resolve route */
- err = rdma_resolve_addr(rd->cm_id, NULL, (struct sockaddr *)&rd->addr, 2000);
if (err != 0) {
log_err("fio: rdma_resolve_addr: %d\n", err);
return 1;
static int fio_rdmaio_setup_listen(struct thread_data *td, short port)
{
struct rdmaio_data *rd = td->io_ops_data;
+ struct rdmaio_options *o = td->eo;
struct ibv_recv_wr *bad_wr;
int state = td->runstate;
td_set_runstate(td, TD_SETTING_UP);
rd->addr.sin_family = AF_INET;
- rd->addr.sin_addr.s_addr = htonl(INADDR_ANY);
rd->addr.sin_port = htons(port);
+ if (!o->bindname || !strlen(o->bindname))
+ rd->addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ else
+ rd->addr.sin_addr.s_addr = htonl(*o->bindname);
+
/* rdma_listen */
if (rdma_bind_addr(rd->cm_id, (struct sockaddr *)&rd->addr) != 0) {
log_err("fio: rdma_bind_addr fail: %m\n");
static int compat_options(struct thread_data *td)
{
- // The original RDMA engine had an ugly / seperator
+ // The original RDMA engine had an ugly / separator
// on the filename for it's options. This function
- // retains backwards compatibility with it.100
+ // retains backwards compatibility with it. Note we do not
+ // support setting the bindname option is this legacy mode.
struct rdmaio_options *o = td->eo;
char *modep, *portp;
{
struct rdmaio_data *rd = td->io_ops_data;
struct rdmaio_options *o = td->eo;
- unsigned int max_bs;
- int ret, i;
+ int ret;
if (td_rw(td)) {
log_err("fio: rdma connections must be read OR write\n");
if ((rd->rdma_protocol == FIO_RDMA_MEM_WRITE) ||
(rd->rdma_protocol == FIO_RDMA_MEM_READ)) {
- rd->rmt_us =
- malloc(FIO_RDMA_MAX_IO_DEPTH * sizeof(struct remote_u));
- memset(rd->rmt_us, 0,
- FIO_RDMA_MAX_IO_DEPTH * sizeof(struct remote_u));
+ rd->rmt_us = calloc(FIO_RDMA_MAX_IO_DEPTH,
+ sizeof(struct remote_u));
rd->rmt_nr = 0;
}
- rd->io_us_queued = malloc(td->o.iodepth * sizeof(struct io_u *));
- memset(rd->io_us_queued, 0, td->o.iodepth * sizeof(struct io_u *));
+ rd->io_us_queued = calloc(td->o.iodepth, sizeof(struct io_u *));
rd->io_u_queued_nr = 0;
- rd->io_us_flight = malloc(td->o.iodepth * sizeof(struct io_u *));
- memset(rd->io_us_flight, 0, td->o.iodepth * sizeof(struct io_u *));
+ rd->io_us_flight = calloc(td->o.iodepth, sizeof(struct io_u *));
rd->io_u_flight_nr = 0;
- rd->io_us_completed = malloc(td->o.iodepth * sizeof(struct io_u *));
- memset(rd->io_us_completed, 0, td->o.iodepth * sizeof(struct io_u *));
+ rd->io_us_completed = calloc(td->o.iodepth, sizeof(struct io_u *));
rd->io_u_completed_nr = 0;
if (td_read(td)) { /* READ as the server */
rd->is_client = 1;
ret = fio_rdmaio_setup_connect(td, td->o.filename, o->port);
}
+ return ret;
+}
+static int fio_rdmaio_post_init(struct thread_data *td)
+{
+ unsigned int max_bs;
+ int i;
+ struct rdmaio_data *rd = td->io_ops_data;
max_bs = max(td->o.max_bs[DDIR_READ], td->o.max_bs[DDIR_WRITE]);
rd->send_buf.max_bs = htonl(max_bs);
for (i = 0; i < td->io_u_freelist.nr; i++) {
struct io_u *io_u = td->io_u_freelist.io_us[i];
- io_u->engine_data = malloc(sizeof(struct rdma_io_u_data));
- memset(io_u->engine_data, 0, sizeof(struct rdma_io_u_data));
+ io_u->engine_data = calloc(1, sizeof(struct rdma_io_u_data));
((struct rdma_io_u_data *)io_u->engine_data)->wr_id = i;
io_u->mr = ibv_reg_mr(rd->pd, io_u->buf, max_bs,
rd->send_buf.nr = htonl(i);
- return ret;
+ return 0;
}
static void fio_rdmaio_cleanup(struct thread_data *td)
}
if (!td->io_ops_data) {
- rd = malloc(sizeof(*rd));
-
- memset(rd, 0, sizeof(*rd));
- init_rand_seed(&rd->rand_state, (unsigned int) GOLDEN_RATIO_PRIME, 0);
+ rd = calloc(1, sizeof(*rd));
+ init_rand_seed(&rd->rand_state, (unsigned int) GOLDEN_RATIO_64, 0);
td->io_ops_data = rd;
}
return 0;
}
-static struct ioengine_ops ioengine_rw = {
+FIO_STATIC struct ioengine_ops ioengine = {
.name = "rdma",
.version = FIO_IOOPS_VERSION,
.setup = fio_rdmaio_setup,
.init = fio_rdmaio_init,
+ .post_init = fio_rdmaio_post_init,
.prep = fio_rdmaio_prep,
.queue = fio_rdmaio_queue,
.commit = fio_rdmaio_commit,
.cleanup = fio_rdmaio_cleanup,
.open_file = fio_rdmaio_open_file,
.close_file = fio_rdmaio_close_file,
- .flags = FIO_DISKLESSIO | FIO_UNIDIR | FIO_PIPEIO,
+ .flags = FIO_DISKLESSIO | FIO_UNIDIR | FIO_PIPEIO |
+ FIO_ASYNCIO_SETS_ISSUE_TIME,
.options = options,
.option_struct_size = sizeof(struct rdmaio_options),
};
static void fio_init fio_rdmaio_register(void)
{
- register_ioengine(&ioengine_rw);
+ register_ioengine(&ioengine);
}
static void fio_exit fio_rdmaio_unregister(void)
{
- unregister_ioengine(&ioengine_rw);
+ unregister_ioengine(&ioengine);
}