From 62faf7d37bd8b6be6657b1e3b61f92eac5b84653 Mon Sep 17 00:00:00 2001 From: Krishnan Parthasarathi Date: Thu, 11 Oct 2018 15:16:41 +0530 Subject: socket: use accept4/paccept for nonblocking socket This reduces the no. of syscalls on Linux systems from 2, accept(2) and fcntl(2) for setting O_NONBLOCK, to a single accept4(2). On NetBSD, we have paccept(2) that does the same, if we leave signal masking aside. Added sys_accept which accepts an extra flags argument than accept(2). This would opportunistically use accept4/paccept as available. It would fallback to accept(2) and fcntl(2) otherwise. While at this, the patch sets FD_CLOEXEC flag on the accepted socket fd. BUG: 1236272 Change-Id: I41e43fd3e36d6dabb07e578a1cea7f45b7b4e37f fixes: bz#1236272 Signed-off-by: Krishnan Parthasarathi --- libglusterfs/src/libglusterfs.sym | 1 + libglusterfs/src/syscall.c | 60 +++++++++++++++++++++++++++++++++++++++ libglusterfs/src/syscall.h | 4 +++ 3 files changed, 65 insertions(+) (limited to 'libglusterfs') diff --git a/libglusterfs/src/libglusterfs.sym b/libglusterfs/src/libglusterfs.sym index 18c9fff34a..27eb1175b5 100644 --- a/libglusterfs/src/libglusterfs.sym +++ b/libglusterfs/src/libglusterfs.sym @@ -1052,6 +1052,7 @@ sys_utimensat sys_write sys_writev sys_socket +sys_accept tbf_init tbf_throttle timespec_now diff --git a/libglusterfs/src/syscall.c b/libglusterfs/src/syscall.c index dd504f734f..b28f2b9d17 100644 --- a/libglusterfs/src/syscall.c +++ b/libglusterfs/src/syscall.c @@ -741,3 +741,63 @@ sys_socket(int domain, int type, int protocol) fcntl(fd, F_SETFD, FD_CLOEXEC); return fd; } + +#if (defined(HAVE_ACCEPT4) || defined(HAVE_PACCEPT)) +static inline int +prep_accept_flags(int flags) +{ + if (flags & O_NONBLOCK) { + flags &= ~O_NONBLOCK; + flags |= SOCK_NONBLOCK; + } + + flags |= SOCK_CLOEXEC; + + return flags; +} +#endif + +int +sys_accept(int sock, struct sockaddr *sockaddr, socklen_t *socklen, int flags) +{ + int newsock = -1; + +#ifdef HAVE_ACCEPT4 + + flags = prep_accept_flags(flags); + newsock = accept4(sock, sockaddr, socklen, flags); + +#elif HAVE_PACCEPT + flags = prep_accept_flags(flags); + newsock = paccept(sock, sockaddr, socklen, NULL, flags); + +#else + int op_errno = 0; + int curflag = 0; + int ret = 0; + + newsock = accept(sock, sockaddr, socklen); + if (newsock != -1) { + curflag = fcntl(newsock, F_GETFL); + if (fcntl(newsock, F_SETFL, curflag | flags) == -1) { + op_errno = errno; + goto err; + } + + curflag = fcntl(newsock, F_GETFD); + if (fcntl(newsock, F_SETFD, curflag | FD_CLOEXEC) == -1) { + op_errno = errno; + goto err; + } + } + +err: + if (op_errno) { + close(newsock); + errno = op_errno; + return -1; + } + +#endif + return newsock; +} diff --git a/libglusterfs/src/syscall.h b/libglusterfs/src/syscall.h index 9bad49edb7..faaf694b22 100644 --- a/libglusterfs/src/syscall.h +++ b/libglusterfs/src/syscall.h @@ -16,6 +16,7 @@ #include #include #include +#include /* GF follows the Linux XATTR definition, which differs in Darwin. */ #define GF_XATTR_CREATE 0x1 /* set value, fail if attr already exists */ @@ -224,4 +225,7 @@ sys_pwrite(int fd, const void *buf, size_t count, off_t offset); int sys_socket(int domain, int type, int protocol); +int +sys_accept(int sock, struct sockaddr *sockaddr, socklen_t *socklen, int flags); + #endif /* __SYSCALL_H__ */ -- cgit