]> git.openfabrics.org - ~shefty/librdmacm.git/commitdiff
refresh
authorSean Hefty <sean.hefty@intel.com>
Tue, 23 Oct 2012 07:59:59 +0000 (00:59 -0700)
committerSean Hefty <sean.hefty@intel.com>
Tue, 23 Oct 2012 07:59:59 +0000 (00:59 -0700)
meta
patches/refresh-temp [deleted file]
patches/rs-iomap

diff --git a/meta b/meta
index 20ab6639044be6617c9dff2da55b03512c3a7cfd..0a7f3a4b1b250a567b913252fab63a93e2ef934f 100644 (file)
--- a/meta
+++ b/meta
@@ -1,9 +1,8 @@
 Version: 1
-Previous: d2b0428f8aa4a167a53833682c818422982dfe2e
-Head: f0fc707aeebfbb6b383d6d5d471310e2a46a004b
+Previous: 747ba387f3231c37084d5b777baa771386af7b08
+Head: c25bf6431d76aca86ee4bf93d71a319fe3096a83
 Applied:
-  rs-iomap: 4507f7d7d64e24375de21367e59a39665d85e12b
-  refresh-temp: f0fc707aeebfbb6b383d6d5d471310e2a46a004b
+  rs-iomap: c25bf6431d76aca86ee4bf93d71a319fe3096a83
 Unapplied:
   resv-rs-len: 7b6ff5c4894f54b221d877adcd709795dffb2fe9
   rs-target-sgl: 7a07c80f2242e80c076dcf3ec6bb4c94626b284f
diff --git a/patches/refresh-temp b/patches/refresh-temp
deleted file mode 100644 (file)
index 71003f0..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-Bottom: 5604b4bc827008a75c9690ec7b8ff3cc77314374
-Top:    ea70904deb6e6424cbdeacc9a46e20ee1b29e5c0
-Author: Sean Hefty <sean.hefty@intel.com>
-Date:   2012-10-23 00:59:59 -0700
-
-Refresh of rs-iomap
-
----
-
-diff --git a/include/rdma/rsocket.h b/include/rdma/rsocket.h
-index 65feda9..21477e4 100644
---- a/include/rdma/rsocket.h
-+++ b/include/rdma/rsocket.h
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 2011 Intel Corporation.  All rights reserved.
-+ * Copyright (c) 2011-2012 Intel Corporation.  All rights reserved.
-  *
-  * This software is available to you under a choice of one of two
-  * licenses.  You may choose to be licensed under the terms of the GNU
-@@ -85,6 +85,10 @@ int rgetsockopt(int socket, int level, int optname,
-               void *optval, socklen_t *optlen);
- int rfcntl(int socket, int cmd, ... /* arg */ );
-+off_t riomap(int socket, void *buf, size_t len, int prot, int flags, off_t offset);
-+int riounmap(int socket, void *buf, size_t len);
-+size_t riowrite(int socket, const void *buf, size_t count, off_t offset, int flags);
-+
- #ifdef __cplusplus
- }
- #endif
-diff --git a/src/indexer.h b/src/indexer.h
-index 26e7f98..0c5f388 100644
---- a/src/indexer.h
-+++ b/src/indexer.h
-@@ -31,6 +31,9 @@
-  *
-  */
-+#if !defined(INDEXER_H)
-+#define INDEXER_H
-+
- #if HAVE_CONFIG_H
- #  include <config.h>
- #endif /* HAVE_CONFIG_H */
-@@ -99,3 +102,43 @@ static inline void *idm_lookup(struct index_map *idm, int index)
-       return ((index <= IDX_MAX_INDEX) && idm->array[idx_array_index(index)]) ?
-               idm_at(idm, index) : NULL;
- }
-+
-+typedef struct _dlist_entry {
-+      struct _dlist_entry     *next;
-+      struct _dlist_entry     *prev;
-+}     dlist_entry;
-+
-+static inline void dlist_init(dlist_entry *head)
-+{
-+      head->next = head;
-+      head->prev = head;
-+}
-+
-+static inline int dlist_empty(dlist_entry *head)
-+{
-+      return head->next == head;
-+}
-+
-+static inline void dlist_insert_after(dlist_entry *item, dlist_entry *head)
-+{
-+      item->next = head->next;
-+      item->prev = head;
-+      head->next->prev = item;
-+      head->next = item;
-+}
-+
-+static inline void dlist_insert_before(dlist_entry *item, dlist_entry *head)
-+{
-+      dlist_insert_after(item, head->prev);
-+}
-+
-+#define dlist_insert_head dlist_insert_after
-+#define dlist_insert_tail dlist_insert_before
-+
-+static inline void dlist_remove(dlist_entry *item)
-+{
-+      item->prev->next = item->next;
-+      item->next->prev = item->prev;
-+}
-+
-+#endif /* INDEXER_H */
-diff --git a/src/rsocket.c b/src/rsocket.c
-index 40d9440..ed708d4 100644
---- a/src/rsocket.c
-+++ b/src/rsocket.c
-@@ -59,7 +59,6 @@
- #define RS_QP_CTRL_SIZE 4
- #define RS_CONN_RETRIES 6
- #define RS_SGL_SIZE 2
--#define RS_MAX_IOMAP 128
- static struct index_map idm;
- static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
-@@ -118,6 +117,14 @@ struct rs_iomap {
-       struct rs_sge sge;
- };
-+struct rs_iomap_mr {
-+      uint64_t offset;
-+      struct ibv_mr *mr;
-+      dlist_entry entry;
-+      atomic_t refcnt;
-+      int index;      /* -1 if mapping is local and not in iomap_list */
-+};
-+
- #define RS_MIN_INLINE      (sizeof(struct rs_sge))
- #define rs_host_is_net()   (1 == htonl(1))
- #define RS_CONN_FLAG_NET   (1 << 0)
-@@ -164,6 +171,7 @@ struct rsocket {
-       fastlock_t        rlock;
-       fastlock_t        cq_lock;
-       fastlock_t        cq_wait_lock;
-+      fastlock_t        iomap_lock;
-       int               opts;
-       long              fd_flags;
-@@ -196,7 +204,11 @@ struct rsocket {
-       int               remote_sge;
-       struct rs_sge     remote_sgl;
-       struct rs_sge     remote_iomap;
--      struct rs_iomap   *remote_iomappings;
-+
-+      struct rs_iomap_mr *remote_iomappings;
-+      dlist_entry       iomap_list;
-+      dlist_entry       iomap_queue;
-+      int               iomap_pending;
-       struct ibv_mr    *target_mr;
-       int               target_sge;
-@@ -336,6 +348,9 @@ static struct rsocket *rs_alloc(struct rsocket *inherited_rs)
-       fastlock_init(&rs->rlock);
-       fastlock_init(&rs->cq_lock);
-       fastlock_init(&rs->cq_wait_lock);
-+      fastlock_init(&rs->iomap_lock);
-+      dlist_init(&rs->iomap_list);
-+      dlist_init(&rs->iomap_queue);
-       return rs;
- }
-@@ -501,6 +516,42 @@ static int rs_create_ep(struct rsocket *rs)
-       return 0;
- }
-+/*
-+static xxx rs_acquire_iomap_mr(struct rsocket *rs, ...)
-+{
-+      TODO: write me
-+}
-+*/
-+
-+static void rs_release_iomap_mr(struct rs_iomap_mr *iomr)
-+{
-+      if (atomic_dec(&iomr->refcnt))
-+              return;
-+
-+      dlist_remove(&iomr->entry);
-+      ibv_dereg_mr(iomr->mr);
-+      if (iomr->index >= 0)
-+              iomr->mr = NULL;
-+      else
-+              free(iomr);
-+}
-+
-+static void rs_free_iomappings(struct rsocket *rs)
-+{
-+      struct rs_iomap_mr *iomr;
-+
-+      while (!dlist_empty(&rs->iomap_list)) {
-+              iomr = container_of(rs->iomap_list.next,
-+                                  struct rs_iomap_mr, entry);
-+              riounmap(iomr->mr->addr, iomr->mr->length);
-+      }
-+      while (!dlist_empty(&rs->iomap_queue)) {
-+              iomr = container_of(rs->iomap_queue.next,
-+                                  struct rs_iomap_mr, entry);
-+              riounmap(iomr->mr->addr, iomr->mr->length);
-+      }
-+}
-+
- static void rs_free(struct rsocket *rs)
- {
-       if (rs->index >= 0)
-@@ -528,11 +579,13 @@ static void rs_free(struct rsocket *rs)
-       }
-       if (rs->cm_id) {
-+              rs_free_iomappings(rs);
-               if (rs->cm_id->qp)
-                       rdma_destroy_qp(rs->cm_id);
-               rdma_destroy_id(rs->cm_id);
-       }
-+      fastlock_destroy(&rs->iomap_lock);
-       fastlock_destroy(&rs->cq_wait_lock);
-       fastlock_destroy(&rs->cq_lock);
-       fastlock_destroy(&rs->rlock);
-@@ -2081,3 +2134,117 @@ int rfcntl(int socket, int cmd, ... /* arg */ )
-       va_end(args);
-       return ret;
- }
-+
-+static struct rs_iomap_mr *rs_get_iomap_mr(struct rsocket *rs)
-+{
-+      struct rs_iomap_mr *iomr;
-+      int i;
-+
-+      if (!rs->remote_iomappings) {
-+              rs->remote_iomappings = calloc(rs->remote_iomap.length,
-+                                             sizeof(*rs->remote_iomappings));
-+              if (!rs->remote_iomappings)
-+                      return NULL;
-+
-+              for (i = 0; i < rs->remote_iomap.length; i++)
-+                      rs->remote_iomappings[i].index = i;
-+      }
-+
-+      for (i = 0; i < rs->remote_iomap.length; i++) {
-+              if (!rs->remote_iomappings[i]->mr)
-+                      return &rs->remote_iomappings[i];
-+      }
-+      return NULL;
-+}
-+
-+/*
-+ * If an offset is given, we map to it.  If offset is -1, then we map the
-+ * offset to the address of buf.  We do not check for conflicts, which must
-+ * be fixed at some point.
-+ */
-+off_t riomap(int socket, void *buf, size_t len, int prot, int flags, off_t offset)
-+{
-+      struct rsocket *rs;
-+      struct rs_iomap_mr *iomr;
-+      int ret, access = IBV_ACCESS_LOCAL_WRITE;
-+
-+      rs = idm_at(&idm, socket);
-+      if ((rs->state != rs_connect_rdwr) || (prot & ~(PROT_WRITE | PROT_NONE)))
-+              return ERR(EINVAL);
-+
-+      fastlock_acquire(&rs->iomap_lock);
-+      if (prot & PROT_WRITE) {
-+              iomr = rs_get_iomap_mr(rs);
-+              access |= IBV_ACCESS_REMOTE_WRITE;
-+      } else {
-+              iomr = calloc(1, sizeof *iomr);
-+              iomr->index = -1;
-+      }
-+      if (!iomr) {
-+              offset = ERR(ENOMEM);
-+              goto out;
-+      }
-+
-+      iomr->mr = ibv_reg_mr(rs->cm_id->pd, buf, len, access);
-+      if (!iomr->mr) {
-+              if (iomr->index < 0)
-+                      free(iomr);
-+              offset = -1;
-+              goto out;
-+      }
-+
-+      if (offset == -1)
-+              offset = (uintptr_t) buf;
-+      iomr->offset = offset;
-+      iomr->prot = prot;
-+      atomic_init(&iomr->refcnt);
-+      atomic_set(&iomr->refcnt, 1);
-+
-+      if (iomr->index >= 0) {
-+              dlist_insert_tail(&iomr->entry, &rs->iomap_queue);
-+              rs->iomap_pending = 1;
-+      } else {
-+              dlist_insert_tail(&iomr->entry, &rs->iomap_list);
-+      }
-+out:
-+      fastlock_release(&rs->iomap_lock);
-+      return offset;
-+}
-+
-+int riounmap(int socket, void *buf, size_t len)
-+{
-+      struct rsocket *rs;
-+      struct rs_iomap_mr *iomr;
-+      struct dlist_entry *entry;
-+      int ret = 0;
-+
-+      rs = idm_at(&idm, socket);
-+      fastlock_acquire(&rs->iomap_lock);
-+
-+      for (entry = rs->iomap_list.next; entry != &rs->iomap_list;
-+           entry = entry->next) {
-+              iomr = container_of(entry, struct rs_iomap_mr, entry);
-+              if (iomr->mr->addr == buf && iomr->mr->length == len) {
-+                      rs_release_iomap_mr(iomr);
-+                      goto out;
-+              }
-+      }
-+
-+      for (entry = rs->iomap_queue.next; entry != &rs->iomap_queue;
-+           entry = entry->next) {
-+              iomr = container_of(entry, struct rs_iomap_mr, entry);
-+              if (iomr->mr->addr == buf && iomr->mr->length == len) {
-+                      rs_release_iomap_mr(iomr);
-+                      goto out;
-+              }
-+      }
-+      ret = ERR(EINVAL);
-+out:
-+      fastlock_release(&rs->iomap_lock);
-+      return ret;
-+}
-+
-+size_t riowrite(int socket, const void *buf, size_t count, off_t offset, int flags)
-+{
-+
-+}
index cdbf1158b83f9b2cd250f3da247d0dc5a049e249..7dc0c1c37b3a90e5744dbd923b12ea0085556e80 100644 (file)
@@ -1,5 +1,5 @@
 Bottom: daf53db464152f40dc8d6f2c99844510b03f8567
-Top:    5604b4bc827008a75c9690ec7b8ff3cc77314374
+Top:    ea70904deb6e6424cbdeacc9a46e20ee1b29e5c0
 Author: Sean Hefty <sean.hefty@intel.com>
 Date:   2012-10-21 14:16:03 -0700
 
@@ -10,15 +10,91 @@ Signed-off-by: Sean Hefty <sean.hefty@intel.com>
 
 ---
 
+diff --git a/include/rdma/rsocket.h b/include/rdma/rsocket.h
+index 65feda9..21477e4 100644
+--- a/include/rdma/rsocket.h
++++ b/include/rdma/rsocket.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2011 Intel Corporation.  All rights reserved.
++ * Copyright (c) 2011-2012 Intel Corporation.  All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+  * licenses.  You may choose to be licensed under the terms of the GNU
+@@ -85,6 +85,10 @@ int rgetsockopt(int socket, int level, int optname,
+               void *optval, socklen_t *optlen);
+ int rfcntl(int socket, int cmd, ... /* arg */ );
++off_t riomap(int socket, void *buf, size_t len, int prot, int flags, off_t offset);
++int riounmap(int socket, void *buf, size_t len);
++size_t riowrite(int socket, const void *buf, size_t count, off_t offset, int flags);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/src/indexer.h b/src/indexer.h
+index 26e7f98..0c5f388 100644
+--- a/src/indexer.h
++++ b/src/indexer.h
+@@ -31,6 +31,9 @@
+  *
+  */
++#if !defined(INDEXER_H)
++#define INDEXER_H
++
+ #if HAVE_CONFIG_H
+ #  include <config.h>
+ #endif /* HAVE_CONFIG_H */
+@@ -99,3 +102,43 @@ static inline void *idm_lookup(struct index_map *idm, int index)
+       return ((index <= IDX_MAX_INDEX) && idm->array[idx_array_index(index)]) ?
+               idm_at(idm, index) : NULL;
+ }
++
++typedef struct _dlist_entry {
++      struct _dlist_entry     *next;
++      struct _dlist_entry     *prev;
++}     dlist_entry;
++
++static inline void dlist_init(dlist_entry *head)
++{
++      head->next = head;
++      head->prev = head;
++}
++
++static inline int dlist_empty(dlist_entry *head)
++{
++      return head->next == head;
++}
++
++static inline void dlist_insert_after(dlist_entry *item, dlist_entry *head)
++{
++      item->next = head->next;
++      item->prev = head;
++      head->next->prev = item;
++      head->next = item;
++}
++
++static inline void dlist_insert_before(dlist_entry *item, dlist_entry *head)
++{
++      dlist_insert_after(item, head->prev);
++}
++
++#define dlist_insert_head dlist_insert_after
++#define dlist_insert_tail dlist_insert_before
++
++static inline void dlist_remove(dlist_entry *item)
++{
++      item->prev->next = item->next;
++      item->next->prev = item->prev;
++}
++
++#endif /* INDEXER_H */
 diff --git a/src/rsocket.c b/src/rsocket.c
-index cc5effe..40d9440 100644
+index cc5effe..ed708d4 100644
 --- a/src/rsocket.c
 +++ b/src/rsocket.c
-@@ -59,9 +59,11 @@
- #define RS_QP_CTRL_SIZE 4
- #define RS_CONN_RETRIES 6
- #define RS_SGL_SIZE 2
-+#define RS_MAX_IOMAP 128
+@@ -62,6 +62,7 @@
  static struct index_map idm;
  static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
  
@@ -26,7 +102,7 @@ index cc5effe..40d9440 100644
  static uint16_t def_inline = 64;
  static uint16_t def_sqsize = 384;
  static uint16_t def_rqsize = 384;
-@@ -76,7 +78,7 @@ static uint32_t polling_time = 10;
+@@ -76,7 +77,7 @@ static uint32_t polling_time = 10;
   * bit 29: more data, 0 - end of transfer, 1 - more data available
   *
   * for data transfers:
@@ -35,7 +111,7 @@ index cc5effe..40d9440 100644
   * for control messages:
   * bits [28-0]: receive credits granted
   */
-@@ -111,15 +113,22 @@ struct rs_sge {
+@@ -111,15 +112,30 @@ struct rs_sge {
        uint32_t length;
  };
  
@@ -47,6 +123,14 @@ index cc5effe..40d9440 100644
 +      struct rs_sge sge;
 +};
 +
++struct rs_iomap_mr {
++      uint64_t offset;
++      struct ibv_mr *mr;
++      dlist_entry entry;
++      atomic_t refcnt;
++      int index;      /* -1 if mapping is local and not in iomap_list */
++};
++
 +#define RS_MIN_INLINE      (sizeof(struct rs_sge))
 +#define rs_host_is_net()   (1 == htonl(1))
 +#define RS_CONN_FLAG_NET   (1 << 0)
@@ -62,12 +146,24 @@ index cc5effe..40d9440 100644
        struct rs_sge     target_sgl;
        struct rs_sge     data_buf;
  };
-@@ -186,10 +195,15 @@ struct rsocket {
+@@ -155,6 +171,7 @@ struct rsocket {
+       fastlock_t        rlock;
+       fastlock_t        cq_lock;
+       fastlock_t        cq_wait_lock;
++      fastlock_t        iomap_lock;
+       int               opts;
+       long              fd_flags;
+@@ -186,10 +203,19 @@ struct rsocket {
  
        int               remote_sge;
        struct rs_sge     remote_sgl;
 +      struct rs_sge     remote_iomap;
-+      struct rs_iomap   *remote_iomappings;
++
++      struct rs_iomap_mr *remote_iomappings;
++      dlist_entry       iomap_list;
++      dlist_entry       iomap_queue;
++      int               iomap_pending;
  
        struct ibv_mr    *target_mr;
        int               target_sge;
@@ -79,7 +175,7 @@ index cc5effe..40d9440 100644
  
        uint32_t          rbuf_size;
        struct ibv_mr    *rmr;
-@@ -201,6 +215,18 @@ struct rsocket {
+@@ -201,6 +227,18 @@ struct rsocket {
        uint8_t           *sbuf;
  };
  
@@ -98,7 +194,7 @@ index cc5effe..40d9440 100644
  void rs_configure(void)
  {
        FILE *f;
-@@ -251,6 +277,15 @@ void rs_configure(void)
+@@ -251,6 +289,15 @@ void rs_configure(void)
                if (def_wmem < 1)
                        def_wmem = 1;
        }
@@ -114,7 +210,7 @@ index cc5effe..40d9440 100644
        init = 1;
  out:
        pthread_mutex_unlock(&mut);
-@@ -287,6 +322,7 @@ static struct rsocket *rs_alloc(struct rsocket *inherited_rs)
+@@ -287,6 +334,7 @@ static struct rsocket *rs_alloc(struct rsocket *inherited_rs)
                rs->sq_size = inherited_rs->sq_size;
                rs->rq_size = inherited_rs->rq_size;
                rs->ctrl_avail = inherited_rs->ctrl_avail;
@@ -122,7 +218,7 @@ index cc5effe..40d9440 100644
        } else {
                rs->sbuf_size = def_wmem;
                rs->rbuf_size = def_mem;
-@@ -294,6 +330,7 @@ static struct rsocket *rs_alloc(struct rsocket *inherited_rs)
+@@ -294,11 +342,15 @@ static struct rsocket *rs_alloc(struct rsocket *inherited_rs)
                rs->sq_size = def_sqsize;
                rs->rq_size = def_rqsize;
                rs->ctrl_avail = RS_QP_CTRL_SIZE;
@@ -130,7 +226,15 @@ index cc5effe..40d9440 100644
        }
        fastlock_init(&rs->slock);
        fastlock_init(&rs->rlock);
-@@ -336,6 +373,8 @@ static void rs_set_qp_size(struct rsocket *rs)
+       fastlock_init(&rs->cq_lock);
+       fastlock_init(&rs->cq_wait_lock);
++      fastlock_init(&rs->iomap_lock);
++      dlist_init(&rs->iomap_list);
++      dlist_init(&rs->iomap_queue);
+       return rs;
+ }
+@@ -336,6 +388,8 @@ static void rs_set_qp_size(struct rsocket *rs)
  
  static int rs_init_bufs(struct rsocket *rs)
  {
@@ -139,7 +243,7 @@ index cc5effe..40d9440 100644
        rs->rmsg = calloc(rs->rq_size + 1, sizeof(*rs->rmsg));
        if (!rs->rmsg)
                return -1;
-@@ -348,11 +387,21 @@ static int rs_init_bufs(struct rsocket *rs)
+@@ -348,11 +402,21 @@ static int rs_init_bufs(struct rsocket *rs)
        if (!rs->smr)
                return -1;
  
@@ -163,7 +267,50 @@ index cc5effe..40d9440 100644
        rs->rbuf = calloc(rs->rbuf_size, sizeof(*rs->rbuf));
        if (!rs->rbuf)
                return -1;
-@@ -472,8 +521,11 @@ static void rs_free(struct rsocket *rs)
+@@ -452,6 +516,42 @@ static int rs_create_ep(struct rsocket *rs)
+       return 0;
+ }
++/*
++static xxx rs_acquire_iomap_mr(struct rsocket *rs, ...)
++{
++      TODO: write me
++}
++*/
++
++static void rs_release_iomap_mr(struct rs_iomap_mr *iomr)
++{
++      if (atomic_dec(&iomr->refcnt))
++              return;
++
++      dlist_remove(&iomr->entry);
++      ibv_dereg_mr(iomr->mr);
++      if (iomr->index >= 0)
++              iomr->mr = NULL;
++      else
++              free(iomr);
++}
++
++static void rs_free_iomappings(struct rsocket *rs)
++{
++      struct rs_iomap_mr *iomr;
++
++      while (!dlist_empty(&rs->iomap_list)) {
++              iomr = container_of(rs->iomap_list.next,
++                                  struct rs_iomap_mr, entry);
++              riounmap(iomr->mr->addr, iomr->mr->length);
++      }
++      while (!dlist_empty(&rs->iomap_queue)) {
++              iomr = container_of(rs->iomap_queue.next,
++                                  struct rs_iomap_mr, entry);
++              riounmap(iomr->mr->addr, iomr->mr->length);
++      }
++}
++
+ static void rs_free(struct rsocket *rs)
+ {
+       if (rs->index >= 0)
+@@ -472,15 +572,20 @@ static void rs_free(struct rsocket *rs)
                free(rs->rbuf);
        }
  
@@ -176,8 +323,17 @@ index cc5effe..40d9440 100644
 +      }
  
        if (rs->cm_id) {
++              rs_free_iomappings(rs);
                if (rs->cm_id->qp)
-@@ -492,9 +544,11 @@ static void rs_set_conn_data(struct rsocket *rs, struct rdma_conn_param *param,
+                       rdma_destroy_qp(rs->cm_id);
+               rdma_destroy_id(rs->cm_id);
+       }
++      fastlock_destroy(&rs->iomap_lock);
+       fastlock_destroy(&rs->cq_wait_lock);
+       fastlock_destroy(&rs->cq_lock);
+       fastlock_destroy(&rs->rlock);
+@@ -492,9 +597,11 @@ static void rs_set_conn_data(struct rsocket *rs, struct rdma_conn_param *param,
                             struct rs_conn_data *conn)
  {
        conn->version = 1;
@@ -191,7 +347,7 @@ index cc5effe..40d9440 100644
  
        conn->target_sgl.addr = htonll((uintptr_t) rs->target_sgl);
        conn->target_sgl.length = htonl(RS_SGL_SIZE);
-@@ -518,6 +572,13 @@ static void rs_save_conn_data(struct rsocket *rs, struct rs_conn_data *conn)
+@@ -518,6 +625,13 @@ static void rs_save_conn_data(struct rsocket *rs, struct rs_conn_data *conn)
            (!rs_host_is_net() && (conn->flags & RS_CONN_FLAG_NET)))
                rs->opts = RS_OPT_SWAP_SGL;
  
@@ -205,3 +361,121 @@ index cc5effe..40d9440 100644
        rs->target_sgl[0].addr = ntohll(conn->data_buf.addr);
        rs->target_sgl[0].length = ntohl(conn->data_buf.length);
        rs->target_sgl[0].key = ntohl(conn->data_buf.key);
+@@ -2020,3 +2134,117 @@ int rfcntl(int socket, int cmd, ... /* arg */ )
+       va_end(args);
+       return ret;
+ }
++
++static struct rs_iomap_mr *rs_get_iomap_mr(struct rsocket *rs)
++{
++      struct rs_iomap_mr *iomr;
++      int i;
++
++      if (!rs->remote_iomappings) {
++              rs->remote_iomappings = calloc(rs->remote_iomap.length,
++                                             sizeof(*rs->remote_iomappings));
++              if (!rs->remote_iomappings)
++                      return NULL;
++
++              for (i = 0; i < rs->remote_iomap.length; i++)
++                      rs->remote_iomappings[i].index = i;
++      }
++
++      for (i = 0; i < rs->remote_iomap.length; i++) {
++              if (!rs->remote_iomappings[i]->mr)
++                      return &rs->remote_iomappings[i];
++      }
++      return NULL;
++}
++
++/*
++ * If an offset is given, we map to it.  If offset is -1, then we map the
++ * offset to the address of buf.  We do not check for conflicts, which must
++ * be fixed at some point.
++ */
++off_t riomap(int socket, void *buf, size_t len, int prot, int flags, off_t offset)
++{
++      struct rsocket *rs;
++      struct rs_iomap_mr *iomr;
++      int ret, access = IBV_ACCESS_LOCAL_WRITE;
++
++      rs = idm_at(&idm, socket);
++      if ((rs->state != rs_connect_rdwr) || (prot & ~(PROT_WRITE | PROT_NONE)))
++              return ERR(EINVAL);
++
++      fastlock_acquire(&rs->iomap_lock);
++      if (prot & PROT_WRITE) {
++              iomr = rs_get_iomap_mr(rs);
++              access |= IBV_ACCESS_REMOTE_WRITE;
++      } else {
++              iomr = calloc(1, sizeof *iomr);
++              iomr->index = -1;
++      }
++      if (!iomr) {
++              offset = ERR(ENOMEM);
++              goto out;
++      }
++
++      iomr->mr = ibv_reg_mr(rs->cm_id->pd, buf, len, access);
++      if (!iomr->mr) {
++              if (iomr->index < 0)
++                      free(iomr);
++              offset = -1;
++              goto out;
++      }
++
++      if (offset == -1)
++              offset = (uintptr_t) buf;
++      iomr->offset = offset;
++      iomr->prot = prot;
++      atomic_init(&iomr->refcnt);
++      atomic_set(&iomr->refcnt, 1);
++
++      if (iomr->index >= 0) {
++              dlist_insert_tail(&iomr->entry, &rs->iomap_queue);
++              rs->iomap_pending = 1;
++      } else {
++              dlist_insert_tail(&iomr->entry, &rs->iomap_list);
++      }
++out:
++      fastlock_release(&rs->iomap_lock);
++      return offset;
++}
++
++int riounmap(int socket, void *buf, size_t len)
++{
++      struct rsocket *rs;
++      struct rs_iomap_mr *iomr;
++      struct dlist_entry *entry;
++      int ret = 0;
++
++      rs = idm_at(&idm, socket);
++      fastlock_acquire(&rs->iomap_lock);
++
++      for (entry = rs->iomap_list.next; entry != &rs->iomap_list;
++           entry = entry->next) {
++              iomr = container_of(entry, struct rs_iomap_mr, entry);
++              if (iomr->mr->addr == buf && iomr->mr->length == len) {
++                      rs_release_iomap_mr(iomr);
++                      goto out;
++              }
++      }
++
++      for (entry = rs->iomap_queue.next; entry != &rs->iomap_queue;
++           entry = entry->next) {
++              iomr = container_of(entry, struct rs_iomap_mr, entry);
++              if (iomr->mr->addr == buf && iomr->mr->length == len) {
++                      rs_release_iomap_mr(iomr);
++                      goto out;
++              }
++      }
++      ret = ERR(EINVAL);
++out:
++      fastlock_release(&rs->iomap_lock);
++      return ret;
++}
++
++size_t riowrite(int socket, const void *buf, size_t count, off_t offset, int flags)
++{
++
++}