rx: Add rxi_FlushWriteLocked 21/12421/4
authorAndrew Deason <adeason@dson.org>
Wed, 26 Oct 2016 21:04:51 +0000 (16:04 -0500)
committerBenjamin Kaduk <kaduk@mit.edu>
Mon, 5 Dec 2016 05:32:41 +0000 (00:32 -0500)
commit4c03e42f91b36a0bf59398b0f649aa0b31b02975
tree493c4693c0b498b8573aa4405594045d7ad0dd4b
parentf413fd927af14a9a87034e47125a78eec63e599e
rx: Add rxi_FlushWriteLocked

Currently, a couple of places in Rx do this:

    MUTEX_EXIT(&call->lock);
    rxi_FlushWrite(call);
    MUTEX_ENTER(&call->lock);

This is a little silly, because if rxi_FlushWrite has anything to do,
it just acquires/drops call->lock again.

This seems like a very minor performance penalty, but in the right
situation it can become more noticeable. Specifically, when an Rx call
on the server ends successfully, rx_EndCall will rxi_FlushWrite (to
send out the last Rx packet to the client) before marking the call as
finished. If the client receives the last Rx packet and starts a new
Rx call on the same channel before the server locks the call again,
the client can receive a BUSY packet (because it looks like the
previous call on the server hasn't finished yet). Nothing breaks, but
this means the client waits 3 seconds to retry.

This situation can probably happen with various rates of success in
almost any situation, but I can see it consistently happen with 'vos
move' when running 'vos' on the same machine as the source fileserver.
It is most noticeable when moving a large number of small volumes
(since you must wait an extra 3+ seconds per volume, where nothing is
happening).

To avoid this, create a new variant of rxi_FlushWrite, called
rxi_FlushWriteLocked. This just assumes the call lock is already held
by the caller, and avoids one extra lock/unlock pair. This is not the
only place where we unlock/lock the call during the rx_EndCall
situation described above, but it seems to be easiest to solve, and
it's enough (for me) to avoid the 3-second delay in the 'vos move'
scenario. Ideally, Rx should be able to atomically 'end' a call while
sending out this last packet, but for now, this commit is easy to do.

Note that rxi_FlushWrite previously didn't do much of note before
locking the call. It did call rxi_FreePackets without the call lock,
but calling that with the call lock is also fine; other callers do
that.

Change-Id: I8f71e86f6c1f6019abea21c205d2b26b7da0d808
Reviewed-on: https://gerrit.openafs.org/12421
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
src/rx/rx.c
src/rx/rx_prototypes.h
src/rx/rx_rdwr.c