diff options
| author | Krishnan Parthasarathi <kparthas@redhat.com> | 2018-10-11 15:16:41 +0530 | 
|---|---|---|
| committer | Raghavendra G <rgowdapp@redhat.com> | 2018-10-12 02:11:38 +0000 | 
| commit | 62faf7d37bd8b6be6657b1e3b61f92eac5b84653 (patch) | |
| tree | 0143f6ae133ff56fa4823815d3084c632ce37440 /libglusterfs/src/syscall.c | |
| parent | 807ec72d740a4548c250cc660c89fc59d2f191d6 (diff) | |
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 <kparthas@redhat.com>
Diffstat (limited to 'libglusterfs/src/syscall.c')
| -rw-r--r-- | libglusterfs/src/syscall.c | 60 | 
1 files changed, 60 insertions, 0 deletions
diff --git a/libglusterfs/src/syscall.c b/libglusterfs/src/syscall.c index dd504f734fc..b28f2b9d17d 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; +}  | 
