From: Sean Hefty Date: Mon, 16 Jul 2012 21:15:33 +0000 (-0700) Subject: Refresh of fork X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=7e2c9cdc85e44f458247366d42fe62261e32596b;p=~shefty%2Flibrdmacm.git Refresh of fork --- diff --git a/src/preload.c b/src/preload.c index 50430f76..8b9fbafd 100644 --- a/src/preload.c +++ b/src/preload.c @@ -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, ¶m, &len); + if (param && !ret) + ret = setsockopt_new(new_fd, SOL_SOCKET, SO_REUSEADDR, ¶m, len); + if (ret) + goto err; + + len = sizeof param; + ret = getsockopt_old(*fd, IPPROTO_TCP, TCP_NODELAY, ¶m, &len); + if (param && !ret) + ret = setsockopt_new(new_fd, IPPROTO_TCP, TCP_NODELAY, ¶m, 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;