NFS TCP race condition with SOCK_ASYNC_NOSPACE |
|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
- Subject: NFS TCP race condition with SOCK_ASYNC_NOSPACE
- From: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
- Date: Fri, 18 Nov 2011 18:40:01 +0000
- User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.23) Gecko/20110921 Lightning/1.0b2 Thunderbird/3.1.15
Hello,
As described originally in
http://www.spinics.net/lists/linux-nfs/msg25314.html, we were
encountering a bug whereby the NFS session was unexpectedly timing out.
I believe I have found the source of the race condition causing the timeout.
Brief overview of setup:
10GiB network, NFS mounted using TCP. Problem reproduces with
multiple different NICs, with synchronous or asynchronous mounts, and
with soft and hard mounts. Reproduces on 2.6.32 and I am currently
trying to reproduce with mainline. (I don't have physical access to the
servers so installing stuff is not fantastically easy)
In net/sunrpc/xprtsock.c:xs_tcp_send_request(), we try to write data to
the sock buffer using xs_sendpages()
When the sock buffer is nearly fully, we get an EAGAIN from
xs_sendpages() which causes a break out of the loop. Lower down the
function, we switch on status which cases us to call xs_nospace() with
the task.
In xs_nospace(), we test the SOCK_ASYNC_NOSPACE bit from the socket, and
in the rare case where that bit is clear, we return 0 instead of
EAGAIN. This promptly overwrites status in xs_tcp_send_request().
The result is that xs_tcp_release_xprt() finds a request which has no
error, but has not sent all of the bytes in its send buffer. It cleans
up by setting XPRT_CLOSE_WAIT which causes xprt_clear_locked() to queue
xprt->task_cleanup, which closes the TCP connection.
Under normal operation, the TCP connection goes down and back up without
interruption to the NFS layer. However, when the NFS server hangs in a
half closed state, the client forces a RST of the TCP connection,
leading to the timeout.
I have tried a few naive fixes such as changing the default return value
in xs_nospace() from 0 to -EAGAIN (meaning that 0 will never be
returned) but this causes a kernel memory leak. Can someone who a
better understanding of these interactions than me have a look? It
seems that the if (test_bit()) test in xs_nospace() should have an else
clause.
Thanks in advance,
--
Andrew Cooper - Dom0 Kernel Engineer, Citrix XenServer
T: +44 (0)1223 225 900, http://www.citrix.com
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
[Linux Kernel Discussion]
[Ethernet Bridging]
[Linux Wireless Networking]
[Linux Bluetooth Networking]
[Linux Networking Users]
[VLAN]
[Git]
[IETF Annouce]
[Linux Assembly]
[Security]
[Bugtraq]
[Photo]
[Singles Social Networking]
[Yosemite Information]
[MIPS Linux]
[ARM Linux Kernel]
[ARM Linux]
[Linux Virtualization]
[Linux Security]
[Linux IDE]
[Linux RAID]
[Linux SCSI]
[Free Dating]