svcrpc: fix wspace-checking race
commit9c335c0b8daf56b9f73479d00b1dd726e1fcca09
authorJ. Bruce Fields <bfields@redhat.com>
Tue, 26 Oct 2010 15:32:03 +0000 (26 11:32 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Fri, 19 Nov 2010 23:35:12 +0000 (19 18:35 -0500)
tree1b408ebd50345d5f3c699a2cd14c73248f39a29d
parentb176331627fccc726d28f4fc4a357d1f3c19dbf0
svcrpc: fix wspace-checking race

We call svc_xprt_enqueue() after something happens which we think may
require handling from a server thread.  To avoid such events being lost,
svc_xprt_enqueue() must guarantee that there will be a svc_serv() call
from a server thread following any such event.  It does that by either
waking up a server thread itself, or checking that XPT_BUSY is set (in
which case somebody else is doing it).

But the check of XPT_BUSY could occur just as someone finishes
processing some other event, and just before they clear XPT_BUSY.

Therefore it's important not to clear XPT_BUSY without subsequently
doing another svc_export_enqueue() to check whether the xprt should be
requeued.

The xpo_wspace() check in svc_xprt_enqueue() breaks this rule, allowing
an event to be missed in situations like:

data arrives
call svc_tcp_data_ready():
call svc_xprt_enqueue():
set BUSY
find no write space
svc_reserve():
free up write space
call svc_enqueue():
test BUSY
clear BUSY

So, instead, check wspace in the same places that the state flags are
checked: before taking BUSY, and in svc_receive().

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
net/sunrpc/svc_xprt.c