Version: 1
-Previous: 2ca8d8e3f8c03a21bd0b77329b913303428bf45a
+Previous: e3c09a30db48aee5e4670d2edbcae80921b1ff68
Head: 8a5515f7d6d3f715693147fb032978c7d1931df1
Applied:
- real-close: 3409f8d6af187d25c63a5d1f8ee8bff5f14555e2
- dup2: ca5813e7cf95dee5933fc417e4a34d26f2b01824
- oobinline: ac51c1095f505373a6ec54b8f1d990259fb34d97
- fork-pass: 9d661d643b62858fe119794e0ca41b5575faa0ce
- fork-connect: a50a83fb4e574a2cc435bba1abf6f9df3d0cc7a6
- sendfile: 9073427ddddfa2f7c93d0ac4a6da9844cb7d2960
- fstat: a957d5786c30dfb1da9cf9345e4a639f6006fbda
- waitall: d7cda32bb4b602342b191888d2b9f861b2592ec9
- waitall-ex: 8a5515f7d6d3f715693147fb032978c7d1931df1
Unapplied:
dbg-out: 4b4c0572eab77856d8fbb919b1feb8f3502a101a
dbg: 0c269855776d3001e37da8c8afe283c20e1d6cd6
+++ /dev/null
-Bottom: c4f9e56fde30641b69e81060e3981b0df33f49c2
-Top: 7cfa8b8bbb7449eac973ab817f043b3f1a3850b7
-Author: Sean Hefty <sean.hefty@intel.com>
-Date: 2012-07-30 16:06:32 -0700
-
-rspreload: Support dup2 calls
-
-vsftpd requires dup2() support. To handle dup2, we need to add
-reference count tracking to the preload fd's.
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
----
-
-diff --git a/src/cma.h b/src/cma.h
-index cedc0c3..6c3df27 100644
---- a/src/cma.h
-+++ b/src/cma.h
-@@ -79,6 +79,31 @@ static inline uint64_t ntohll(uint64_t x) { return x; }
- #define fastlock_destroy(lock) pthread_mutex_destroy(lock)
- #define fastlock_acquire(lock) pthread_mutex_lock(lock)
- #define fastlock_release(lock) pthread_mutex_unlock(lock)
-+
-+typedef struct { pthread_mutex_t mut; int val; } atomic_t;
-+static inline int atomic_inc(atomic_t *atomic)
-+{
-+ int v;
-+
-+ pthread_mutex_lock(&atomic->mut);
-+ v = ++(atomic->val);
-+ pthread_mutex_unlock(&atomic->mut);
-+ return v;
-+}
-+static inline int atomic_dec(atomic_t *atomic)
-+{
-+ int v;
-+
-+ pthread_mutex_lock(&atomic->mut);
-+ v = --(atomic->val);
-+ pthread_mutex_unlock(&atomic->mut);
-+ return v;
-+}
-+static inline void atomic_init(atomic_t *atomic)
-+{
-+ pthread_mutex_init(&atomic->mut, NULL);
-+ atomic->val = 0;
-+}
- #else
- typedef struct {
- sem_t sem;
-@@ -103,7 +128,14 @@ static inline void fastlock_release(fastlock_t *lock)
- if (__sync_sub_and_fetch(&lock->cnt, 1) > 0)
- sem_post(&lock->sem);
- }
-+
-+typedef struct { volatile int val; } atomic_t;
-+#define atomic_inc(v) (__sync_add_and_fetch(&(v)->val, 1))
-+#define atomic_dec(v) (__sync_sub_and_fetch(&(v)->val, 1))
-+#define atomic_init(v) ((v)->val = 0)
- #endif /* DEFINE_ATOMICS */
-+#define atomic_get(v) ((v)->val)
-+#define atomic_set(v, s) ((v)->val = s)
-
- int ucma_max_qpsize(struct rdma_cm_id *id);
- int ucma_complete(struct rdma_cm_id *id);
-diff --git a/src/preload.c b/src/preload.c
-index a680143..b18d310 100644
---- a/src/preload.c
-+++ b/src/preload.c
-@@ -83,6 +83,7 @@ struct socket_calls {
- int (*getsockopt)(int socket, int level, int optname,
- void *optval, socklen_t *optlen);
- int (*fcntl)(int socket, int cmd, ... /* arg */);
-+ int (*dup2)(int oldfd, int newfd);
- };
-
- static struct socket_calls real;
-@@ -105,6 +106,8 @@ enum fd_type {
- struct fd_info {
- enum fd_type type;
- int fd;
-+ int dupfd;
-+ atomic_t refcnt;
- };
-
- static int fd_open(void)
-@@ -122,6 +125,9 @@ static int fd_open(void)
- goto err1;
- }
-
-+ fdi->dupfd = -1;
-+ atomic_init(&fdi->refcnt);
-+ atomic_set(&fdi->refcnt, 1);
- pthread_mutex_lock(&mut);
- ret = idm_set(&idm, index, fdi);
- pthread_mutex_unlock(&mut);
-@@ -252,6 +258,7 @@ static void init_preload(void)
- real.setsockopt = dlsym(RTLD_NEXT, "setsockopt");
- real.getsockopt = dlsym(RTLD_NEXT, "getsockopt");
- real.fcntl = dlsym(RTLD_NEXT, "fcntl");
-+ real.dup2 = dlsym(RTLD_NEXT, "dup2");
-
- rs.socket = dlsym(RTLD_DEFAULT, "rsocket");
- rs.bind = dlsym(RTLD_DEFAULT, "rbind");
-@@ -807,9 +814,28 @@ int shutdown(int socket, int how)
-
- int close(int socket)
- {
-- int fd;
-+ struct fd_info *fdi;
-+ int ret;
-+
- init_preload();
-- return (fd_close(socket, &fd) == fd_rsocket) ? rclose(fd) : real.close(fd);
-+ fdi = idm_lookup(&idm, socket);
-+ if (!fdi)
-+ return real.close(socket);
-+
-+ if (fdi->dupfd != -1) {
-+ ret = close(fdi->dupfd);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ if (atomic_dec(&fdi->refcnt))
-+ return 0;
-+
-+ idm_clear(&idm, socket);
-+ real.close(socket);
-+ ret = (fdi->type == fd_rsocket) ? rclose(fdi->fd) : real.close(fdi->fd);
-+ free(fdi);
-+ return ret;
- }
-
- int getpeername(int socket, struct sockaddr *addr, socklen_t *addrlen)
-@@ -886,3 +912,52 @@ int fcntl(int socket, int cmd, ... /* arg */)
- va_end(args);
- return ret;
- }
-+
-+/*
-+ * dup2 is not thread safe
-+ */
-+int dup2(int oldfd, int newfd)
-+{
-+ struct fd_info *oldfdi, *newfdi;
-+ int ret;
-+
-+ init_preload();
-+ oldfdi = idm_lookup(&idm, oldfd);
-+ if (oldfdi && oldfdi->type == fd_fork)
-+ fork_passive(oldfd);
-+
-+ newfdi = idm_lookup(&idm, newfd);
-+ if (newfdi) {
-+ /* newfd cannot have been dup'ed directly */
-+ if (atomic_get(&newfdi->refcnt) > 1)
-+ return ERR(EBUSY);
-+ close(newfd);
-+ }
-+
-+ ret = real.dup2(oldfd, newfd);
-+ if (!oldfdi || ret != newfd)
-+ return ret;
-+
-+ newfdi = calloc(1, sizeof *newfdi);
-+ if (!newfdi) {
-+ close(newfd);
-+ return ERR(ENOMEM);
-+ }
-+
-+ pthread_mutex_lock(&mut);
-+ idm_set(&idm, newfd, newfdi);
-+ pthread_mutex_unlock(&mut);
-+
-+ newfdi->fd = oldfdi->fd;
-+ newfdi->type = oldfdi->type;
-+ if (oldfdi->dupfd != -1) {
-+ newfdi->dupfd = oldfdi->dupfd;
-+ oldfdi = idm_lookup(&idm, oldfdi->dupfd);
-+ } else {
-+ newfdi->dupfd = oldfd;
-+ }
-+ atomic_init(&newfdi->refcnt);
-+ atomic_set(&newfdi->refcnt, 1);
-+ atomic_inc(&oldfdi->refcnt);
-+ return newfd;
-+}
+++ /dev/null
-Bottom: 216c0397df2215433e2acfe73e52db57cbf694c4
-Top: 652ae6e1dadacc92be353adaafd434f1ff7ddbfa
-Author: Sean Hefty <sean.hefty@intel.com>
-Date: 2012-08-10 21:44:39 -0700
-
-rspreload: Do not block connect when supporting fork
-
-Many FTP servers require fork support. However, FTP clients,
-such as ncftp, will perform the following call sequence:
-
-send PASV request to server over connection 1
- server will listen for connection 2
-issue nonblocking connect to server
-send ACCEPT request to server over connection 1
- server will accept connection 2
-
-The current fork support converts all nonblocking connect
-calls to blocking. The result is that the FTP client ends up
-blocked waiting for the server to accept the connection,
-which it will never do.
-
-To handle this case, we have the active side follow the same
-rule as the server side and defer establishing the rsocket
-connection until the user calls the first data transfer routine.
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
----
-
-diff --git a/src/preload.c b/src/preload.c
-index bb8e3fb..8b86415 100644
---- a/src/preload.c
-+++ b/src/preload.c
-@@ -99,12 +99,20 @@ static int fork_support;
-
- enum fd_type {
- fd_normal,
-- fd_rsocket,
-- fd_fork
-+ fd_rsocket
-+};
-+
-+enum fd_fork_state {
-+ fd_ready,
-+ fd_fork,
-+ fd_fork_listen,
-+ fd_fork_active,
-+ fd_fork_passive
- };
-
- struct fd_info {
- enum fd_type type;
-+ enum fd_fork_state state;
- int fd;
- int dupfd;
- atomic_t refcnt;
-@@ -143,13 +151,14 @@ err1:
- return ret;
- }
-
--static void fd_store(int index, int fd, enum fd_type type)
-+static void fd_store(int index, int fd, enum fd_type type, enum fd_fork_state state)
- {
- struct fd_info *fdi;
-
- fdi = idm_at(&idm, index);
- fdi->fd = fd;
- fdi->type = type;
-+ fdi->state = state;
- }
-
- static inline enum fd_type fd_get(int index, int *fd)
-@@ -175,6 +184,14 @@ static inline int fd_getd(int index)
- return fdi ? fdi->fd : index;
- }
-
-+static inline enum fd_fork_state fd_gets(int index)
-+{
-+ struct fd_info *fdi;
-+
-+ fdi = idm_lookup(&idm, index);
-+ return fdi ? fdi->state : fd_ready;
-+}
-+
- static inline enum fd_type fd_gett(int index)
- {
- struct fd_info *fdi;
-@@ -353,7 +370,7 @@ static int transpose_socket(int socket, enum fd_type new_type)
- if (ret)
- goto err;
-
-- fd_store(socket, dfd, new_type);
-+ fd_store(socket, dfd, new_type, fd_ready);
- return dfd;
-
- err:
-@@ -398,9 +415,9 @@ int socket(int domain, int type, int protocol)
- ret = real.socket(domain, type, protocol);
- if (ret < 0)
- return ret;
-- fd_store(index, ret, fd_fork);
-+ fd_store(index, ret, fd_normal, fd_fork);
- } else {
-- fd_store(index, ret, fd_rsocket);
-+ fd_store(index, ret, fd_rsocket, fd_ready);
- set_rsocket_options(ret);
- }
- return index;
-@@ -419,30 +436,46 @@ int bind(int socket, const struct sockaddr *addr, socklen_t addrlen)
-
- int listen(int socket, int backlog)
- {
-- int fd;
-- return (fd_get(socket, &fd) == fd_rsocket) ?
-- rlisten(fd, backlog) : real.listen(fd, backlog);
-+ int fd, ret;
-+ if (fd_get(socket, &fd) == fd_rsocket) {
-+ ret = rlisten(fd, backlog);
-+ } else {
-+ ret = real.listen(fd, backlog);
-+ if (!ret && fd_gets(socket) == fd_fork)
-+ fd_store(socket, fd, fd_normal, fd_fork_listen);
-+ }
-+ return ret;
- }
-
- int accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
- {
- int fd, index, ret;
-- enum fd_type type;
-
-- type = fd_get(socket, &fd);
-- if (type == fd_rsocket || type == fd_fork) {
-+ if (fd_get(socket, &fd) == fd_rsocket) {
- index = fd_open();
- if (index < 0)
- return index;
-
-- ret = (type == fd_rsocket) ? raccept(fd, addr, addrlen) :
-- real.accept(fd, addr, addrlen);
-+ ret = raccept(fd, addr, addrlen);
- if (ret < 0) {
- fd_close(index, &fd);
- return ret;
- }
-
-- fd_store(index, ret, type);
-+ fd_store(index, ret, fd_rsocket, fd_ready);
-+ return index;
-+ } else if (fd_gets(socket) == fd_fork_listen) {
-+ index = fd_open();
-+ if (index < 0)
-+ return index;
-+
-+ ret = real.accept(fd, addr, addrlen);
-+ if (ret < 0) {
-+ fd_close(index, &fd);
-+ return ret;
-+ }
-+
-+ fd_store(index, ret, fd_normal, fd_fork_passive);
- return index;
- } else {
- return real.accept(fd, addr, addrlen);
-@@ -453,37 +486,57 @@ int accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
- * We can't fork RDMA connections and pass them from the parent to the child
- * process. Instead, we need to establish the RDMA connection after calling
- * fork. To do this, we delay establishing the RDMA connection until we try
-- * to send/receive on the server side. On the client side, we don't expect
-- * to fork, so we switch from a TCP connection to an rsocket when connecting.
-+ * to send/receive on the server side.
- */
--static int fork_active(int socket, const struct sockaddr *addr, socklen_t addrlen)
-+static void fork_active(int socket)
- {
-- int fd, ret;
-+ struct sockaddr_storage addr;
-+ int sfd, dfd, ret;
-+ socklen_t len;
- uint32_t msg;
- long flags;
-
-- fd = fd_getd(socket);
-- flags = real.fcntl(fd, F_GETFL);
-- real.fcntl(fd, F_SETFL, 0);
-- ret = real.connect(fd, addr, addrlen);
-+ sfd = fd_getd(socket);
-+
-+ len = sizeof addr;
-+ ret = real.getpeername(sfd, (struct sockaddr *) &addr, &len);
- if (ret)
-- return ret;
-+ goto err1;
-
-- ret = real.recv(fd, &msg, sizeof msg, MSG_PEEK);
-- if ((ret != sizeof msg) || msg) {
-- fd_store(socket, fd, fd_normal);
-- return 0;
-- }
-+ dfd = rsocket(addr.ss_family, SOCK_STREAM, 0);
-+ if (dfd < 0)
-+ goto err1;
-
-- real.fcntl(fd, F_SETFL, flags);
-- ret = transpose_socket(socket, fd_rsocket);
-- if (ret < 0)
-- return ret;
-+ flags = real.fcntl(sfd, F_GETFL);
-+ real.fcntl(sfd, F_SETFL, 0);
-+ ret = real.recv(sfd, &msg, sizeof msg, MSG_PEEK);
-+ real.fcntl(sfd, F_SETFL, flags);
-+ if ((ret != sizeof msg) || msg)
-+ goto err2;
-+
-+ ret = rconnect(ret, (struct sockaddr *) &addr, len);
-+ if (ret)
-+ goto err2;
-
-- real.close(fd);
-- return rconnect(ret, addr, addrlen);
-+ set_rsocket_options(dfd);
-+ copysockopts(dfd, sfd, &rs, &real);
-+ real.shutdown(sfd, SHUT_RDWR);
-+ real.close(sfd);
-+ fd_store(socket, dfd, fd_rsocket, fd_ready);
-+ return;
-+
-+err2:
-+ rclose(dfd);
-+err1:
-+ fd_store(socket, sfd, fd_normal, fd_ready);
- }
-
-+/*
-+ * The server will start listening for the new connection, then send a
-+ * message to the active side when the listen is ready. This does leave
-+ * fork unsupported in the following case: the server is nonblocking and
-+ * calls select/poll waiting to receive data from the client.
-+ */
- static void fork_passive(int socket)
- {
- struct sockaddr_in6 sin6;
-@@ -541,7 +594,7 @@ static void fork_passive(int socket)
- copysockopts(dfd, sfd, &rs, &real);
- real.shutdown(sfd, SHUT_RDWR);
- real.close(sfd);
-- fd_store(socket, dfd, fd_rsocket);
-+ fd_store(socket, dfd, fd_rsocket, fd_ready);
-
- lclose:
- rclose(lfd);
-@@ -550,7 +603,7 @@ sclose:
- sem_close(sem);
- out:
- if (ret)
-- fd_store(socket, sfd, fd_normal);
-+ fd_store(socket, sfd, fd_normal, fd_ready);
- }
-
- static inline enum fd_type fd_fork_get(int index, int *fd)
-@@ -559,8 +612,10 @@ static inline enum fd_type fd_fork_get(int index, int *fd)
-
- fdi = idm_lookup(&idm, index);
- if (fdi) {
-- if (fdi->type == fd_fork)
-+ if (fdi->type == fd_fork_passive)
- fork_passive(index);
-+ else if (fdi->type == fd_fork_active)
-+ fork_active(index);
- *fd = fdi->fd;
- return fdi->type;
-
-@@ -574,10 +629,7 @@ int connect(int socket, const struct sockaddr *addr, socklen_t addrlen)
- {
- int fd, ret;
-
-- switch (fd_get(socket, &fd)) {
-- case fd_fork:
-- return fork_active(socket, addr, addrlen);
-- case fd_rsocket:
-+ if (fd_get(socket, &fd) == fd_rsocket) {
- ret = rconnect(fd, addr, addrlen);
- if (!ret || errno == EINPROGRESS)
- return ret;
-@@ -588,9 +640,8 @@ int connect(int socket, const struct sockaddr *addr, socklen_t addrlen)
-
- rclose(fd);
- fd = ret;
-- break;
-- default:
-- break;
-+ } else if (fd_gets(socket) == fd_fork) {
-+ fd_store(socket, fd, fd_normal, fd_fork_active);
- }
-
- return real.connect(fd, addr, addrlen);
+++ /dev/null
-Bottom: 3ea2748a5c41b11a2e7033c56bddd938d2770b6c
-Top: 216c0397df2215433e2acfe73e52db57cbf694c4
-Author: Sean Hefty <sean.hefty@intel.com>
-Date: 2012-08-13 16:00:16 -0700
-
-rspreload: Minor cleanup of fork_passive handling
-
-Minor code cleanup in passive side handling of fork support.
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
----
-
-diff --git a/src/preload.c b/src/preload.c
-index b18d310..bb8e3fb 100644
---- a/src/preload.c
-+++ b/src/preload.c
-@@ -492,7 +492,7 @@ static void fork_passive(int socket)
- socklen_t len;
- uint32_t msg;
-
-- fd_get(socket, &sfd);
-+ sfd = fd_getd(socket);
-
- len = sizeof sin6;
- ret = real.getsockname(sfd, (struct sockaddr *) &sin6, &len);
-@@ -510,7 +510,7 @@ static void fork_passive(int socket)
-
- lfd = rsocket(sin6.sin6_family, SOCK_STREAM, 0);
- if (lfd < 0) {
-- ret = lfd;
-+ ret = lfd;
- goto sclose;
- }
-
-@@ -537,10 +537,7 @@ static void fork_passive(int socket)
- goto lclose;
- }
-
-- param = 1;
-- rsetsockopt(dfd, IPPROTO_TCP, TCP_NODELAY, ¶m, sizeof param);
- set_rsocket_options(dfd);
--
- copysockopts(dfd, sfd, &rs, &real);
- real.shutdown(sfd, SHUT_RDWR);
- real.close(sfd);
+++ /dev/null
-Bottom: 03b5e28f4ac8f642409cf46b6a2bfc0da609ec5d
-Top: 3f4ba48a611f719563dc773a1c33fbd391708df0
-Author: Sean Hefty <sean.hefty@intel.com>
-Date: 2012-08-07 09:37:24 -0700
-
-rspreload: Add fstat support
-
-vsftpd calls fstat on a socket. Fake it out.
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
----
-
-diff --git a/src/preload.c b/src/preload.c
-index c6cf176..8f19af5 100644
---- a/src/preload.c
-+++ b/src/preload.c
-@@ -87,6 +87,7 @@ struct socket_calls {
- int (*fcntl)(int socket, int cmd, ... /* arg */);
- int (*dup2)(int oldfd, int newfd);
- ssize_t (*sendfile)(int out_fd, int in_fd, off_t *offset, size_t count);
-+ int (*fxstat)(int ver, int fd, struct stat *buf);
- };
-
- static struct socket_calls real;
-@@ -280,6 +281,7 @@ static void init_preload(void)
- real.fcntl = dlsym(RTLD_NEXT, "fcntl");
- real.dup2 = dlsym(RTLD_NEXT, "dup2");
- real.sendfile = dlsym(RTLD_NEXT, "sendfile");
-+ real.fxstat = dlsym(RTLD_NEXT, "__fxstat");
-
- rs.socket = dlsym(RTLD_DEFAULT, "rsocket");
- rs.bind = dlsym(RTLD_DEFAULT, "rbind");
-@@ -1033,3 +1035,18 @@ ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
- munmap(file_addr, count);
- return ret;
- }
-+
-+int __fxstat(int ver, int socket, struct stat *buf)
-+{
-+ int fd, ret;
-+
-+ init_preload();
-+ if (fd_get(socket, &fd) == fd_rsocket) {
-+ ret = real.fxstat(ver, socket, buf);
-+ if (!ret)
-+ buf->st_mode = (buf->st_mode & ~S_IFMT) | __S_IFSOCK;
-+ } else {
-+ ret = real.fxstat(ver, fd, buf);
-+ }
-+ return ret;
-+}
+++ /dev/null
-Bottom: 7cfa8b8bbb7449eac973ab817f043b3f1a3850b7
-Top: 3ea2748a5c41b11a2e7033c56bddd938d2770b6c
-Author: Sean Hefty <sean.hefty@intel.com>
-Date: 2012-08-07 21:31:12 -0700
-
-rsockets: Support SO_OOBINLINE
-
-We don't support urgent data, so just return success.
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
-
----
-
-diff --git a/src/rsocket.c b/src/rsocket.c
-index b9105a1..996cb2f 100644
---- a/src/rsocket.c
-+++ b/src/rsocket.c
-@@ -1820,6 +1820,10 @@ int rsetsockopt(int socket, int level, int optname,
- opt_on = *(int *) optval;
- ret = 0;
- break;
-+ case SO_OOBINLINE:
-+ opt_on = *(int *) optval;
-+ ret = 0;
-+ break;
- default:
- break;
- }
-@@ -1898,6 +1902,7 @@ int rgetsockopt(int socket, int level, int optname,
- switch (optname) {
- case SO_REUSEADDR:
- case SO_KEEPALIVE:
-+ case SO_OOBINLINE:
- *((int *) optval) = !!(rs->so_opts & (1 << optname));
- *optlen = sizeof(int);
- break;
+++ /dev/null
-Bottom: d24dd0fae6823a86b3a40de76ff29ff00831ae09
-Top: c4f9e56fde30641b69e81060e3981b0df33f49c2
-Author: Sean Hefty <sean.hefty@intel.com>
-Date: 2012-08-01 16:26:11 -0700
-
-rspreload: Call real.close in fd_close
-
-The index into the preload lookup table is obtained by opening
-/dev/null and use the returned value. When closing the file,
-use the real close call and not the preload close call. This
-is a minor optimization, but clarifies the expected operation.
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
----
-
-diff --git a/src/preload.c b/src/preload.c
-index 52eaf1a..a680143 100644
---- a/src/preload.c
-+++ b/src/preload.c
-@@ -131,7 +131,7 @@ static int fd_open(void)
- return index;
-
- err2:
-- close(index);
-+ real.close(index);
- err1:
- free(fdi);
- return ret;
-@@ -187,7 +187,7 @@ static enum fd_type fd_close(int index, int *fd)
- idm_clear(&idm, index);
- *fd = fdi->fd;
- type = fdi->type;
-- close(index);
-+ real.close(index);
- free(fdi);
- } else {
- *fd = index;
+++ /dev/null
-Bottom: 652ae6e1dadacc92be353adaafd434f1ff7ddbfa
-Top: 03b5e28f4ac8f642409cf46b6a2bfc0da609ec5d
-Author: Sean Hefty <sean.hefty@intel.com>
-Date: 2012-08-13 17:00:42 -0700
-
-rspreload: Support sendfile
-
-Handle users calling sendfile with an rsocket.
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
----
-
-diff --git a/src/preload.c b/src/preload.c
-index 8b86415..c6cf176 100644
---- a/src/preload.c
-+++ b/src/preload.c
-@@ -38,6 +38,8 @@
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/stat.h>
-+#include <sys/mman.h>
-+#include <sys/sendfile.h>
- #include <stdarg.h>
- #include <dlfcn.h>
- #include <netdb.h>
-@@ -84,6 +86,7 @@ struct socket_calls {
- void *optval, socklen_t *optlen);
- int (*fcntl)(int socket, int cmd, ... /* arg */);
- int (*dup2)(int oldfd, int newfd);
-+ ssize_t (*sendfile)(int out_fd, int in_fd, off_t *offset, size_t count);
- };
-
- static struct socket_calls real;
-@@ -276,6 +279,7 @@ static void init_preload(void)
- real.getsockopt = dlsym(RTLD_NEXT, "getsockopt");
- real.fcntl = dlsym(RTLD_NEXT, "fcntl");
- real.dup2 = dlsym(RTLD_NEXT, "dup2");
-+ real.sendfile = dlsym(RTLD_NEXT, "sendfile");
-
- rs.socket = dlsym(RTLD_DEFAULT, "rsocket");
- rs.bind = dlsym(RTLD_DEFAULT, "rbind");
-@@ -1009,3 +1013,23 @@ int dup2(int oldfd, int newfd)
- atomic_inc(&oldfdi->refcnt);
- return newfd;
- }
-+
-+ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
-+{
-+ void *file_addr;
-+ int fd;
-+ size_t ret;
-+
-+ if (fd_get(out_fd, &fd) != fd_rsocket)
-+ return real.sendfile(fd, in_fd, offset, count);
-+
-+ file_addr = mmap(NULL, count, PROT_READ, 0, in_fd, offset ? *offset : 0);
-+ if (file_addr == (void *) -1)
-+ return -1;
-+
-+ ret = rwrite(fd, file_addr, count);
-+ if ((ret > 0) && offset)
-+ lseek(in_fd, ret, SEEK_CUR);
-+ munmap(file_addr, count);
-+ return ret;
-+}
+++ /dev/null
-Bottom: 3f4ba48a611f719563dc773a1c33fbd391708df0
-Top: 0c97026b5f690fd1e2693e9f9c63549fc3e00f00
-Author: Sean Hefty <sean.hefty@intel.com>
-Date: 2012-06-28 11:34:38 -0700
-
-rsockets: Add support for MSG_WAITALL rrecv() flag
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
----
-
-diff --git a/src/rsocket.c b/src/rsocket.c
-index 996cb2f..4c4821b 100644
---- a/src/rsocket.c
-+++ b/src/rsocket.c
-@@ -1131,43 +1131,48 @@ ssize_t rrecv(int socket, void *buf, size_t len, int flags)
- }
- }
- fastlock_acquire(&rs->rlock);
-- if (!rs_have_rdata(rs)) {
-- ret = rs_get_comp(rs, rs_nonblocking(rs, flags), rs_conn_have_rdata);
-- if (ret)
-- goto out;
-- }
--
-- ret = 0;
-- if (flags & MSG_PEEK) {
-- left = len - rs_peek(rs, buf, len);
-- goto out;
-- }
-+ do {
-+ if (!rs_have_rdata(rs)) {
-+ ret = rs_get_comp(rs, rs_nonblocking(rs, flags),
-+ rs_conn_have_rdata);
-+ if (ret)
-+ break;
-+ }
-
-- for (; left && rs_have_rdata(rs); left -= rsize) {
-- if (left < rs->rmsg[rs->rmsg_head].data) {
-- rsize = left;
-- rs->rmsg[rs->rmsg_head].data -= left;
-- } else {
-- rs->rseq_no++;
-- rsize = rs->rmsg[rs->rmsg_head].data;
-- if (++rs->rmsg_head == rs->rq_size + 1)
-- rs->rmsg_head = 0;
-+ ret = 0;
-+ if (flags & MSG_PEEK) {
-+ left = len - rs_peek(rs, buf, left);
-+ break;
- }
-
-- end_size = rs->rbuf_size - rs->rbuf_offset;
-- if (rsize > end_size) {
-- memcpy(buf, &rs->rbuf[rs->rbuf_offset], end_size);
-- rs->rbuf_offset = 0;
-- buf += end_size;
-- rsize -= end_size;
-- left -= end_size;
-+ for (; left && rs_have_rdata(rs); left -= rsize) {
-+ if (left < rs->rmsg[rs->rmsg_head].data) {
-+ rsize = left;
-+ rs->rmsg[rs->rmsg_head].data -= left;
-+ } else {
-+ rs->rseq_no++;
-+ rsize = rs->rmsg[rs->rmsg_head].data;
-+ if (++rs->rmsg_head == rs->rq_size + 1)
-+ rs->rmsg_head = 0;
-+ }
-+
-+ end_size = rs->rbuf_size - rs->rbuf_offset;
-+ if (rsize > end_size) {
-+ memcpy(buf, &rs->rbuf[rs->rbuf_offset], end_size);
-+ rs->rbuf_offset = 0;
-+ buf += end_size;
-+ rsize -= end_size;
-+ left -= end_size;
-+ rs->rbuf_bytes_avail += end_size;
-+ }
-+ memcpy(buf, &rs->rbuf[rs->rbuf_offset], rsize);
-+ rs->rbuf_offset += rsize;
-+ buf += rsize;
-+ rs->rbuf_bytes_avail += rsize;
- }
-- memcpy(buf, &rs->rbuf[rs->rbuf_offset], rsize);
-- rs->rbuf_offset += rsize;
-- buf += rsize;
-- }
-- rs->rbuf_bytes_avail += len - left;
--out:
-+
-+ } while (left && (flags & MSG_WAITALL) && (rs->state & rs_connect_rd));
-+
- fastlock_release(&rs->rlock);
- return ret ? ret : len - left;
- }
+++ /dev/null
-Bottom: 0c97026b5f690fd1e2693e9f9c63549fc3e00f00
-Top: 15d584ee23e38f450359c3caea511818f5bf14c0
-Author: Sean Hefty <sean.hefty@intel.com>
-Date: 2012-08-16 15:41:35 -0700
-
-rstream: Use MSG_WAITALL for blocking test
-
-Signed-off-by: Sean Hefty <sean.hefty@intel.com>
-
-
----
-
-diff --git a/examples/rstream.c b/examples/rstream.c
-index befb7c6..1d221d0 100644
---- a/examples/rstream.c
-+++ b/examples/rstream.c
-@@ -607,7 +607,7 @@ static int set_test_opt(char *optarg)
- use_async = 1;
- break;
- case 'b':
-- flags &= ~MSG_DONTWAIT;
-+ flags = (flags & ~MSG_DONTWAIT) | MSG_WAITALL;
- break;
- case 'f':
- use_fork = 1;
-@@ -628,7 +628,7 @@ static int set_test_opt(char *optarg)
- } else if (!strncasecmp("async", optarg, 5)) {
- use_async = 1;
- } else if (!strncasecmp("block", optarg, 5)) {
-- flags &= ~MSG_DONTWAIT;
-+ flags = (flags & ~MSG_DONTWAIT) | MSG_WAITALL;
- } else if (!strncasecmp("nonblock", optarg, 8)) {
- flags |= MSG_DONTWAIT;
- } else if (!strncasecmp("verify", optarg, 6)) {