rx: Don't clear the receive queue when out of packets
authorSimon Wilkinson <sxw@your-file-system.com>
Wed, 12 Oct 2011 13:47:14 +0000 (09:47 -0400)
committerDerrick Brashear <shadow@dementix.org>
Sun, 23 Oct 2011 22:37:01 +0000 (15:37 -0700)
We can end up discarding a receive queue that's been soft acked,
effectively taking back soft acks we sent. Whilst the RX
documentation says that a client can drop soft acked packets at
will, our RX implementation assumes that if the final packet in
a call has been soft acked, we won't clear the queue. If a client
clears the queue in this situation, the call will hang.

What *should* happen is that we should take necessary locks,
confirm that we have not soft-acked all of the packets in a flow,
and then discard, or, if we're just going to discard, error the
call.

Change-Id: Ic8e358b8648c1a6f0154009093468531a9e3cf74
Reviewed-on: http://gerrit.openafs.org/5603
Reviewed-by: Derrick Brashear <shadow@dementix.org>
Tested-by: Derrick Brashear <shadow@dementix.org>

src/rx/rx.c
src/rx/rx_globals.h

index b6a1316..bb49d60 100644 (file)
@@ -3803,8 +3803,9 @@ rxi_ReceiveDataPacket(struct rx_call *call,
        call->rprev = np->header.serial;
        rxi_calltrace(RX_TRACE_DROP, call);
        dpf(("packet %"AFS_PTR_FMT" dropped on receipt - quota problems\n", np));
-       if (rxi_doreclaim)
-           rxi_ClearReceiveQueue(call);
+        /* We used to clear the receive queue here, in an attempt to free
+         * packets. However this is unsafe if the queue has received a
+         * soft ACK for the final packet */
        clock_GetTime(&now);
        when = now;
        clock_Add(&when, &rx_softAckDelay);
index 3e17c7c..1e51890 100644 (file)
@@ -481,7 +481,6 @@ EXT osi_socket rx_minSocketNumber GLOBALSINIT(0x7fffffff);
 #define        RX_MAX_QUOTA    15      /* part of min packet computation */
 EXT int rx_packetQuota[RX_N_PACKET_CLASSES] GLOBALSINIT(RX_PACKET_QUOTAS);
 EXT int meltdown_1pkt GLOBALSINIT(1);  /* prefer to schedule single-packet calls */
-EXT int rxi_doreclaim GLOBALSINIT(1);  /* if discard one packet, discard all */
 EXT int rxi_md2cnt GLOBALSINIT(0);     /* counter of skipped calls */
 EXT int rxi_2dchoice GLOBALSINIT(1);   /* keep track of another call to schedule */