summaryrefslogtreecommitdiffstats
path: root/support/nfs/svc_socket.c
diff options
context:
space:
mode:
authorBodo Stroesser <bstroesser@ts.fujitsu.com>2014-11-12 09:03:24 -0500
committerSteve Dickson <steved@redhat.com>2014-11-12 13:46:59 -0500
commite2989f2f5fd709c19eeb92780a51ae58d3501db8 (patch)
treee2b4aea11d8706606f39b5a53f603c0ed3ce06b9 /support/nfs/svc_socket.c
parentf44169dfe52ece05b1c36c0f3c3ea0427f295ace (diff)
downloadnfs-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>
Diffstat (limited to 'support/nfs/svc_socket.c')
-rw-r--r--support/nfs/svc_socket.c66
1 files changed, 34 insertions, 32 deletions
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);
}
/*