rx: Use _IsLast to check for last call in queue 58/14158/2
authorAndrew Deason <adeason@sinenomine.net>
Sun, 26 Apr 2020 22:26:02 +0000 (17:26 -0500)
committerBenjamin Kaduk <kaduk@mit.edu>
Fri, 1 May 2020 21:37:14 +0000 (17:37 -0400)
Ever since commits 170dbb3c (rx: Use opr queues) and d9fc4890 (rx: Fix
test for end of call queue for LWP), rx_GetCall checks if the current
call is the last one on rx_incomingCallQueue by doing this:

    opr_queue_IsEnd(&rx_incomingCallQueue, cursor)

But opr_queue_IsEnd checks if the given pointer is the _end_ of the
last; that is, if it's the end-of-list sentinel, not an item on the
actual list. Testing for the last item in a list is what
opr_queue_IsLast is for. This is the same convention that the old Rx
queues used, but 170dbb3c just accidentally replaced queue_IsLast with
opr_queue_IsEnd (instead of opr_queue_IsLast), and d9fc4890 copied the
mistake.

So because this is inside an opr_queue_Scan loop, opr_queue_IsEnd will
never be true, so we'll never enter this block of code (unless we are
the "fcfs" thread). This means that an incoming Rx call can get stuck
in the incoming call queue, if all of the following are true:

 - The incoming call consists of more than 1 packet of incoming data.

 - The incoming call "waits" when it comes in (that is, there are no
   free threads or the service is over quota).

 - The "fcfs" thread doesn't scan the incoming call queue (because it
   is idle when the call comes in, but the relevant service is over
   quota).

To fix this, just use opr_queue_IsLast here instead of
opr_queue_IsEnd.

Change-Id: I04b90b1279f81dc518eb61e7bd450e3c0be37a77
Reviewed-on: https://gerrit.openafs.org/14158
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

src/rx/rx.c

index eac6733..c33a451 100644 (file)
@@ -2062,7 +2062,7 @@ rx_GetCall(int tno, struct rx_service *cur_service, osi_socket * socketp)
                }
                MUTEX_ENTER(&rx_pthread_mutex);
                if (tno == rxi_fcfs_thread_num
-                       || opr_queue_IsEnd(&rx_incomingCallQueue, cursor)) {
+                       || opr_queue_IsLast(&rx_incomingCallQueue, cursor)) {
                    MUTEX_EXIT(&rx_pthread_mutex);
                    /* If we're the fcfs thread , then  we'll just use
                     * this call. If we haven't been able to find an optimal
@@ -2238,7 +2238,7 @@ rx_GetCall(int tno, struct rx_service *cur_service, osi_socket * socketp)
            if (QuotaOK(service)) {
                MUTEX_ENTER(&rx_pthread_mutex);
                if (tno == rxi_fcfs_thread_num
-                       || opr_queue_IsEnd(&rx_incomingCallQueue, cursor)) {
+                       || opr_queue_IsLast(&rx_incomingCallQueue, cursor)) {
                    MUTEX_EXIT(&rx_pthread_mutex);
                    /* If we're the fcfs thread, then  we'll just use
                     * this call. If we haven't been able to find an optimal