]> git.openfabrics.org - ~shefty/librdmacm.git/commitdiff
Refresh of fork
authorSean Hefty <sean.hefty@intel.com>
Mon, 16 Jul 2012 21:15:33 +0000 (14:15 -0700)
committerSean Hefty <sean.hefty@intel.com>
Mon, 16 Jul 2012 21:15:33 +0000 (14:15 -0700)
src/preload.c

index 50430f76b0a7b3feb85c576462660bfc00fb1109..8b9fbafdfbbbc3542bb750fc58487027cb2c1512 100644 (file)
@@ -210,7 +210,7 @@ void getenv_options(void)
        if (var)
                sq_inline = atoi(var);
 
-       var = getenv("RS_FORK");
+       var = getenv("RDMAV_FORK_SAFE");
        if (var)
                fork_support = atoi(var);
 }
@@ -306,6 +306,68 @@ err:
        return ret;
 }
 
+/*
+ * Convert between an rsocket and a normal socket.  The new socket should have the
+ * same settings and bindings as the current socket.  We currently only handle
+ * setting a few of the more common values.
+ */
+static int
+transpose_socket(int index, int *fd, enum fd_type new_type,
+       int (*socket_new)(int domain, int type, int protocol),
+       int (*shutdown_old)(int socket, int how),
+       int (*close_old)(int socket),
+       int (*getsockname_old)(int socket, struct sockaddr *addr,
+                              socklen_t *addrlen),
+       int (*getsockopt_old)(int socket, int level, int optname,
+                             void *optval, socklen_t *optlen),
+       int (*setsockopt_new)(int socket, int level, int optname,
+                             const void *optval, socklen_t optlen),
+       int (*fcntl_old)(int socket, int cmd, ... /* arg */),
+       int (*fcntl_new)(int socket, int cmd, ... /* arg */))
+{
+       socklen_t len = 0;
+       int new_fd, param, ret;
+
+       ret = getsockname_old(*fd, NULL, &len);
+       if (ret)
+               return ret;
+
+       param = (len == sizeof(struct sockaddr_in6)) ? PF_INET6 : PF_INET;
+       new_fd = socket_new(param, SOCK_STREAM, 0);
+       if (new_fd < 0)
+               return new_fd;
+
+       ret = fcntl_old(*fd, F_GETFL);
+       if (ret > 0)
+               ret = fcntl_new(new_fd, F_SETFL, ret);
+       if (ret)
+               goto err;
+
+       len = sizeof param;
+       ret = getsockopt_old(*fd, SOL_SOCKET, SO_REUSEADDR, &param, &len);
+       if (param && !ret)
+               ret = setsockopt_new(new_fd, SOL_SOCKET, SO_REUSEADDR, &param, len);
+       if (ret)
+               goto err;
+
+       len = sizeof param;
+       ret = getsockopt_old(*fd, IPPROTO_TCP, TCP_NODELAY, &param, &len);
+       if (param && !ret)
+               ret = setsockopt_new(new_fd, IPPROTO_TCP, TCP_NODELAY, &param, len);
+       if (ret)
+               goto err;
+
+       shutdown_old(*fd, SHUT_RDWR);
+       close_old(*fd);
+       fd_store(socket, new_fd, new_type);
+       *fd = new_fd;
+       return 0;
+
+err:
+       real_close(new_fd);
+       return ret;
+}
+
 /*
  * Use defaults on failure.
  */
@@ -402,6 +464,29 @@ int accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
        }
 }
 
+static int connect_fork(int socket, const struct sockaddr *addr, socklen_t addrlen)
+{
+       uint32_t msg;
+       int rs, fd, ret;
+
+       fd = fd_getd(socket);
+       ret = real_connect(fd, addr, addrlen);
+       if (!ret)
+               return ret;
+
+       ret = real_read(fd, &msg, sizeof msg);
+       if (ret != sizeof msg)
+               return ret;
+
+       rs = rsocket(domain, type, protocol);
+
+       real_shutdown(fd, SHUT_RDWR);
+       real_close(fd);
+
+       fd_store(socket, fd, fd_rsocket);
+       return connect(socket, addr, addrlen);
+}
+
 int connect(int socket, const struct sockaddr *addr, socklen_t addrlen)
 {
        struct sockaddr_in *sin;