diff options
author | Bodo Stroesser <bstroesser@ts.fujitsu.com> | 2014-11-12 09:03:24 -0500 |
---|---|---|
committer | Steve Dickson <steved@redhat.com> | 2014-11-12 13:46:59 -0500 |
commit | e2989f2f5fd709c19eeb92780a51ae58d3501db8 (patch) | |
tree | e2b4aea11d8706606f39b5a53f603c0ed3ce06b9 | |
parent | f44169dfe52ece05b1c36c0f3c3ea0427f295ace (diff) | |
download | nfs-utils-e2989f2f5fd709c19eeb92780a51ae58d3501db8.tar.gz nfs-utils-e2989f2f5fd709c19eeb92780a51ae58d3501db8.tar.xz nfs-utils-e2989f2f5fd709c19eeb92780a51ae58d3501db8.zip |
rpc.mountd: set nonblocking mode if no libtirpc
If mountd is built without libtirpc and it is started using "-p XXX"
option, the tcp listeners and the sockets waiting for UDP messages
are not in non-blocking mode. Thus if running with multiple threads (-t XX),
all threads will wake up from select on a connection request or a UDP
message, but only one thread will succeed. All others will wait on
accept() or read() for the next event.
Reviewed-by: NeilBrown <neilb@suse.de>
Signed-off-by: Bodo Stroesser <bstroesser@ts.fujitsu.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
-rw-r--r-- | support/include/nfslib.h | 1 | ||||
-rw-r--r-- | support/nfs/rpcmisc.c | 2 | ||||
-rw-r--r-- | support/nfs/svc_socket.c | 66 |
3 files changed, 36 insertions, 33 deletions
diff --git a/support/include/nfslib.h b/support/include/nfslib.h index ce4b14b..a6a2e8d 100644 --- a/support/include/nfslib.h +++ b/support/include/nfslib.h @@ -174,6 +174,7 @@ void closeall(int min); int svctcp_socket (u_long __number, int __reuse); int svcudp_socket (u_long __number); +int svcsock_nonblock (int __sock); /* Misc shared code prototypes */ size_t strlcat(char *, const char *, size_t); diff --git a/support/nfs/rpcmisc.c b/support/nfs/rpcmisc.c index 64c98ff..ae2c0a6 100644 --- a/support/nfs/rpcmisc.c +++ b/support/nfs/rpcmisc.c @@ -104,7 +104,7 @@ makesock(int port, int proto) return -1; } - return sock; + return svcsock_nonblock(sock); } void diff --git a/support/nfs/svc_socket.c b/support/nfs/svc_socket.c index 74273b9..99321e7 100644 --- a/support/nfs/svc_socket.c +++ b/support/nfs/svc_socket.c @@ -76,6 +76,39 @@ int getservport(u_long number, const char *proto) return 0; } +int +svcsock_nonblock(int sock) +{ + int flags; + + if (sock < 0) + return sock; + + /* This socket might be shared among multiple processes + * if mountd is run multi-threaded. So it is safest to + * make it non-blocking, else all threads might wake + * one will get the data, and the others will block + * indefinitely. + * In all cases, transaction on this socket are atomic + * (accept for TCP, packet-read and packet-write for UDP) + * so O_NONBLOCK will not confuse unprepared code causing + * it to corrupt messages. + * It generally safest to have O_NONBLOCK when doing an accept + * as if we get a RST after the SYN and before accept runs, + * we can block despite being told there was an acceptable + * connection. + */ + if ((flags = fcntl(sock, F_GETFL)) < 0) + perror(_("svc_socket: can't get socket flags")); + else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0) + perror(_("svc_socket: can't set socket flags")); + else + return sock; + + (void) __close(sock); + return -1; +} + static int svc_socket (u_long number, int type, int protocol, int reuse) { @@ -113,38 +146,7 @@ svc_socket (u_long number, int type, int protocol, int reuse) sock = -1; } - if (sock >= 0) - { - /* This socket might be shared among multiple processes - * if mountd is run multi-threaded. So it is safest to - * make it non-blocking, else all threads might wake - * one will get the data, and the others will block - * indefinitely. - * In all cases, transaction on this socket are atomic - * (accept for TCP, packet-read and packet-write for UDP) - * so O_NONBLOCK will not confuse unprepared code causing - * it to corrupt messages. - * It generally safest to have O_NONBLOCK when doing an accept - * as if we get a RST after the SYN and before accept runs, - * we can block despite being told there was an acceptable - * connection. - */ - int flags; - if ((flags = fcntl(sock, F_GETFL)) < 0) - { - perror (_("svc_socket: can't get socket flags")); - (void) __close (sock); - sock = -1; - } - else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0) - { - perror (_("svc_socket: can't set socket flags")); - (void) __close (sock); - sock = -1; - } - } - - return sock; + return svcsock_nonblock(sock); } /* |