stats: Add hint information to per priority level stats
[fio.git] / engines / rdma.c
index da00cba8b66b3f6db0bcd3a9cba8b45b9362ffa7..ebdbcb1c808a524c5eff480ae70a8bc9109fcf40 100644 (file)
@@ -30,7 +30,7 @@
 #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>
@@ -59,6 +59,7 @@ struct rdmaio_options {
        struct thread_data *td;
        unsigned int port;
        enum rdma_io_mode verb;
+       char *bindname;
 };
 
 static int str_hostname_cb(void *data, const char *input)
@@ -81,6 +82,16 @@ static struct fio_option options[] = {
                .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",
@@ -215,7 +226,8 @@ static int client_recv(struct thread_data *td, struct ibv_wc *wc)
                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);
 
@@ -780,7 +792,8 @@ static int fio_rdmaio_recv(struct thread_data *td, struct io_u **io_us,
        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;
 
@@ -819,6 +832,12 @@ static void fio_rdmaio_queued(struct thread_data *td, struct io_u **io_us,
                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)
@@ -837,8 +856,6 @@ 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);
@@ -1004,30 +1021,53 @@ static int fio_rdmaio_close_file(struct thread_data *td, struct fio_file *f)
        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;
@@ -1072,15 +1112,20 @@ static int fio_rdmaio_setup_connect(struct thread_data *td, const char *host,
 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");
@@ -1153,9 +1198,10 @@ static int check_set_rlimits(struct thread_data *td)
 
 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;
@@ -1208,8 +1254,7 @@ static int fio_rdmaio_init(struct thread_data *td)
 {
        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");
@@ -1249,23 +1294,18 @@ static int fio_rdmaio_init(struct thread_data *td)
 
        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 */
@@ -1277,6 +1317,13 @@ static int fio_rdmaio_init(struct thread_data *td)
                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);
@@ -1285,8 +1332,7 @@ static int fio_rdmaio_init(struct thread_data *td)
        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,
@@ -1310,7 +1356,7 @@ static int fio_rdmaio_init(struct thread_data *td)
 
        rd->send_buf.nr = htonl(i);
 
-       return ret;
+       return 0;
 }
 
 static void fio_rdmaio_cleanup(struct thread_data *td)
@@ -1332,21 +1378,20 @@ static int fio_rdmaio_setup(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,
@@ -1355,17 +1400,18 @@ static struct ioengine_ops ioengine_rw = {
        .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);
 }