Rx: protect rx_conn and rx_call refCount field with rx_refcnt_mutex
[openafs.git] / src / rx / rx_rdwr.c
index 5aca916..f086894 100644 (file)
@@ -1,7 +1,7 @@
  /*
   * Copyright 2000, International Business Machines Corporation and others.
   * All Rights Reserved.
-  * 
+  *
   * This software has been released under the terms of the IBM Public
   * License.  For details, see the LICENSE file in the top-level source
   * directory or online at http://www.openafs.org/dl/license10.html
@@ -26,7 +26,7 @@
 #include "h/types.h"
 #include "h/time.h"
 #include "h/stat.h"
-#if defined(AFS_AIX_ENV) || defined(AFS_AUX_ENV) || defined(AFS_SUN5_ENV) 
+#if defined(AFS_AIX_ENV) || defined(AFS_AUX_ENV) || defined(AFS_SUN5_ENV)
 #include "h/systm.h"
 #endif
 #ifdef AFS_OSF_ENV
@@ -65,7 +65,6 @@
 #undef kmem_free
 #undef mem_alloc
 #undef mem_free
-#undef register
 #endif /* AFS_OSF_ENV */
 #else /* KERNEL */
 # include <sys/types.h>
@@ -138,7 +137,9 @@ rxi_ReadProc(struct rx_call *call, char *buf,
                        afs_int32 error;
                        struct rx_connection *conn = call->conn;
                        queue_Remove(rp);
+#ifdef RX_TRACK_PACKETS
                        rp->flags &= ~RX_PKTFLAG_RQ;
+#endif
 #ifdef RXDEBUG_PACKET
                         call->rqc--;
 #endif /* RXDEBUG_PACKET */
@@ -150,8 +151,8 @@ rxi_ReadProc(struct rx_call *call, char *buf,
                        if ((error =
                             RXS_CheckPacket(conn->securityObject, call,
                                             rp))) {
-                           /* Used to merely shut down the call, but now we 
-                            * shut down the whole connection since this may 
+                           /* Used to merely shut down the call, but now we
+                            * shut down the whole connection since this may
                             * indicate an attempt to hijack it */
 
                            MUTEX_EXIT(&call->lock);
@@ -166,9 +167,11 @@ rxi_ReadProc(struct rx_call *call, char *buf,
                        }
                        call->rnext++;
                        cp = call->currentPacket = rp;
+#ifdef RX_TRACK_PACKETS
                        call->currentPacket->flags |= RX_PKTFLAG_CP;
+#endif
                        call->curvec = 1;       /* 0th vec is always header */
-                       /* begin at the beginning [ more or less ], continue 
+                       /* begin at the beginning [ more or less ], continue
                         * on until the end, then stop. */
                        call->curpos =
                            (char *)cp->wirevec[1].iov_base +
@@ -209,8 +212,10 @@ rxi_ReadProc(struct rx_call *call, char *buf,
                                    rxevent_Cancel(call->delayedAckEvent,
                                                   call,
                                                   RX_CALL_REFCOUNT_DELAY);
+                                    MUTEX_ENTER(&rx_refcnt_mutex);
                                    CALL_HOLD(call, RX_CALL_REFCOUNT_DELAY);
-                                   call->delayedAckEvent =
+                                    MUTEX_EXIT(&rx_refcnt_mutex);
+                                    call->delayedAckEvent =
                                      rxevent_PostNow(&when, &now,
                                                     rxi_SendDelayedAck, call,
                                                     0);
@@ -221,7 +226,7 @@ rxi_ReadProc(struct rx_call *call, char *buf,
                    }
                }
 
-                /* 
+                /*
                  * If we reach this point either we have no packets in the
                  * receive queue or the next packet in the queue is not the
                  * one we are looking for.  There is nothing else for us to
@@ -243,7 +248,6 @@ rxi_ReadProc(struct rx_call *call, char *buf,
                    osi_rxSleep(&call->rq);
 #endif
                }
-                /* cp is no longer valid since we may have given up the lock */
                 cp = call->currentPacket;
 
                call->startWait = 0;
@@ -275,7 +279,9 @@ rxi_ReadProc(struct rx_call *call, char *buf,
 
                if (!call->nLeft) {
                    /* out of packet.  Get another one. */
+#ifdef RX_TRACK_PACKETS
                    call->currentPacket->flags &= ~RX_PKTFLAG_CP;
+#endif
                    rxi_FreePacket(cp);
                    cp = call->currentPacket = (struct rx_packet *)0;
                } else if (!call->curlen) {
@@ -283,7 +289,9 @@ rxi_ReadProc(struct rx_call *call, char *buf,
                    if (++call->curvec >= cp->niovecs) {
                        /* current packet is exhausted, get ready for another */
                        /* don't worry about curvec and stuff, they get set somewhere else */
+#ifdef RX_TRACK_PACKETS
                        call->currentPacket->flags &= ~RX_PKTFLAG_CP;
+#endif
                        rxi_FreePacket(cp);
                        cp = call->currentPacket = (struct rx_packet *)0;
                        call->nLeft = 0;
@@ -313,13 +321,7 @@ rx_ReadProc(struct rx_call *call, char *buf, int nbytes)
     char *tcurpos;
     SPLVAR;
 
-    /*
-     * Free any packets from the last call to ReadvProc/WritevProc.
-     * We do not need the lock because the receiver threads only
-     * touch the iovq when the RX_CALL_IOVEC_WAIT flag is set, and the
-     * RX_CALL_IOVEC_WAIT is always cleared before returning from
-     * ReadvProc/WritevProc.
-     */
+    /* Free any packets from the last call to ReadvProc/WritevProc */
     if (!queue_IsEmpty(&call->iovq)) {
 #ifdef RXDEBUG_PACKET
         call->iovqc -=
@@ -329,28 +331,22 @@ rx_ReadProc(struct rx_call *call, char *buf, int nbytes)
 
     /*
      * Most common case, all of the data is in the current iovec.
-     * We do not need the lock because this is the only thread that
-     * updates the curlen, curpos, nLeft fields.
-     *
      * We are relying on nLeft being zero unless the call is in receive mode.
      */
     tcurlen = call->curlen;
     tnLeft = call->nLeft;
     if (!call->error && tcurlen > nbytes && tnLeft > nbytes) {
        tcurpos = call->curpos;
-       memcpy(buf, tcurpos, nbytes);
+        memcpy(buf, tcurpos, nbytes);
+
        call->curpos = tcurpos + nbytes;
        call->curlen = tcurlen - nbytes;
        call->nLeft = tnLeft - nbytes;
 
-        if (!call->nLeft) {
+        if (!call->nLeft && call->currentPacket != NULL) {
             /* out of packet.  Get another one. */
-            NETPRI;
-            MUTEX_ENTER(&call->lock);
             rxi_FreePacket(call->currentPacket);
             call->currentPacket = (struct rx_packet *)0;
-            MUTEX_EXIT(&call->lock);
-            USERPRI;
         }
        return nbytes;
     }
@@ -373,13 +369,7 @@ rx_ReadProc32(struct rx_call *call, afs_int32 * value)
     char *tcurpos;
     SPLVAR;
 
-    /*
-     * Free any packets from the last call to ReadvProc/WritevProc.
-     * We do not need the lock because the receiver threads only
-     * touch the iovq when the RX_CALL_IOVEC_WAIT flag is set, and the
-     * RX_CALL_IOVEC_WAIT is always cleared before returning from
-     * ReadvProc/WritevProc.
-     */
+    /* Free any packets from the last call to ReadvProc/WritevProc */
     if (!queue_IsEmpty(&call->iovq)) {
 #ifdef RXDEBUG_PACKET
         call->iovqc -=
@@ -389,9 +379,6 @@ rx_ReadProc32(struct rx_call *call, afs_int32 * value)
 
     /*
      * Most common case, all of the data is in the current iovec.
-     * We do not need the lock because this is the only thread that
-     * updates the curlen, curpos, nLeft fields.
-     *
      * We are relying on nLeft being zero unless the call is in receive mode.
      */
     tcurlen = call->curlen;
@@ -399,18 +386,16 @@ rx_ReadProc32(struct rx_call *call, afs_int32 * value)
     if (!call->error && tcurlen >= sizeof(afs_int32)
        && tnLeft >= sizeof(afs_int32)) {
        tcurpos = call->curpos;
-       memcpy((char *)value, tcurpos, sizeof(afs_int32));
-       call->curpos = tcurpos + sizeof(afs_int32);
+
+        memcpy((char *)value, tcurpos, sizeof(afs_int32));
+
+        call->curpos = tcurpos + sizeof(afs_int32);
        call->curlen = (u_short)(tcurlen - sizeof(afs_int32));
        call->nLeft = (u_short)(tnLeft - sizeof(afs_int32));
         if (!call->nLeft && call->currentPacket != NULL) {
             /* out of packet.  Get another one. */
-            NETPRI;
-            MUTEX_ENTER(&call->lock);
             rxi_FreePacket(call->currentPacket);
             call->currentPacket = (struct rx_packet *)0;
-            MUTEX_EXIT(&call->lock);
-            USERPRI;
         }
        return sizeof(afs_int32);
     }
@@ -420,6 +405,7 @@ rx_ReadProc32(struct rx_call *call, afs_int32 * value)
     bytes = rxi_ReadProc(call, (char *)value, sizeof(afs_int32));
     MUTEX_EXIT(&call->lock);
     USERPRI;
+
     return bytes;
 }
 
@@ -456,7 +442,9 @@ rxi_FillReadVec(struct rx_call *call, afs_uint32 serial)
                    afs_int32 error;
                    struct rx_connection *conn = call->conn;
                    queue_Remove(rp);
+#ifdef RX_TRACK_PACKETS
                    rp->flags &= ~RX_PKTFLAG_RQ;
+#endif
 #ifdef RXDEBUG_PACKET
                     call->rqc--;
 #endif /* RXDEBUG_PACKET */
@@ -467,8 +455,8 @@ rxi_FillReadVec(struct rx_call *call, afs_uint32 serial)
                     * data + the header. */
                    if ((error =
                         RXS_CheckPacket(conn->securityObject, call, rp))) {
-                       /* Used to merely shut down the call, but now we 
-                        * shut down the whole connection since this may 
+                       /* Used to merely shut down the call, but now we
+                        * shut down the whole connection since this may
                         * indicate an attempt to hijack it */
 
                        MUTEX_EXIT(&call->lock);
@@ -483,10 +471,12 @@ rxi_FillReadVec(struct rx_call *call, afs_uint32 serial)
                    }
                    call->rnext++;
                    curp = call->currentPacket = rp;
+#ifdef RX_TRACK_PACKETS
                    call->currentPacket->flags |= RX_PKTFLAG_CP;
+#endif
                    call->curvec = 1;   /* 0th vec is always header */
                    cur_iov = &curp->wirevec[1];
-                   /* begin at the beginning [ more or less ], continue 
+                   /* begin at the beginning [ more or less ], continue
                     * on until the end, then stop. */
                    call->curpos =
                        (char *)curp->wirevec[1].iov_base +
@@ -538,8 +528,10 @@ rxi_FillReadVec(struct rx_call *call, afs_uint32 serial)
 
            if (!call->nLeft) {
                /* out of packet.  Get another one. */
+#ifdef RX_TRACK_PACKETS
                 curp->flags &= ~RX_PKTFLAG_CP;
                 curp->flags |= RX_PKTFLAG_IOVQ;
+#endif
                queue_Append(&call->iovq, curp);
 #ifdef RXDEBUG_PACKET
                 call->iovqc++;
@@ -550,8 +542,10 @@ rxi_FillReadVec(struct rx_call *call, afs_uint32 serial)
                if (++call->curvec >= curp->niovecs) {
                    /* current packet is exhausted, get ready for another */
                    /* don't worry about curvec and stuff, they get set somewhere else */
+#ifdef RX_TRACK_PACKETS
                    curp->flags &= ~RX_PKTFLAG_CP;
                    curp->flags |= RX_PKTFLAG_IOVQ;
+#endif
                    queue_Append(&call->iovq, curp);
 #ifdef RXDEBUG_PACKET
                     call->iovqc++;
@@ -585,7 +579,9 @@ rxi_FillReadVec(struct rx_call *call, afs_uint32 serial)
                || clock_Gt(&call->delayedAckEvent->eventTime, &when)) {
                rxevent_Cancel(call->delayedAckEvent, call,
                               RX_CALL_REFCOUNT_DELAY);
+                MUTEX_ENTER(&rx_refcnt_mutex);
                CALL_HOLD(call, RX_CALL_REFCOUNT_DELAY);
+                MUTEX_EXIT(&rx_refcnt_mutex);
                call->delayedAckEvent =
                    rxevent_PostNow(&when, &now, rxi_SendDelayedAck, call, 0);
            }
@@ -607,12 +603,6 @@ int
 rxi_ReadvProc(struct rx_call *call, struct iovec *iov, int *nio, int maxio,
              int nbytes)
 {
-    int requestCount;
-    int nextio;
-
-    requestCount = nbytes;
-    nextio = 0;
-
     /* Free any packets from the last call to ReadvProc/WritevProc */
     if (queue_IsNotEmpty(&call->iovq)) {
 #ifdef RXDEBUG_PACKET
@@ -711,7 +701,9 @@ rxi_WriteProc(struct rx_call *call, char *buf,
            && (call->mode == RX_MODE_RECEIVING)) {
            call->mode = RX_MODE_SENDING;
            if (cp) {
+#ifdef RX_TRACK_PACKETS
                cp->flags &= ~RX_PKTFLAG_CP;
+#endif
                rxi_FreePacket(cp);
                cp = call->currentPacket = (struct rx_packet *)0;
                call->nLeft = 0;
@@ -730,11 +722,13 @@ rxi_WriteProc(struct rx_call *call, char *buf,
        if (call->nFree == 0) {
            if (!call->error && cp) {
                 /* Clear the current packet now so that if
-                 * we are forced to wait and drop the lock 
-                 * the packet we are planning on using 
+                 * we are forced to wait and drop the lock
+                 * the packet we are planning on using
                  * cannot be freed.
                  */
+#ifdef RX_TRACK_PACKETS
                 cp->flags &= ~RX_PKTFLAG_CP;
+#endif
                call->currentPacket = (struct rx_packet *)0;
 #ifdef AFS_GLOBAL_RXLOCK_KERNEL
                /* Wait until TQ_BUSY is reset before adding any
@@ -742,21 +736,27 @@ rxi_WriteProc(struct rx_call *call, char *buf,
                 */
                while (call->flags & RX_CALL_TQ_BUSY) {
                    call->flags |= RX_CALL_TQ_WAIT;
+                    call->tqWaiters++;
 #ifdef RX_ENABLE_LOCKS
                    CV_WAIT(&call->cv_tq, &call->lock);
 #else /* RX_ENABLE_LOCKS */
                    osi_rxSleep(&call->tq);
 #endif /* RX_ENABLE_LOCKS */
+                    call->tqWaiters--;
+                    if (call->tqWaiters == 0)
+                        call->flags &= ~RX_CALL_TQ_WAIT;
                }
 #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
                clock_NewTime();        /* Bogus:  need new time package */
-               /* The 0, below, specifies that it is not the last packet: 
+               /* The 0, below, specifies that it is not the last packet:
                 * there will be others. PrepareSendPacket may
                 * alter the packet length by up to
                 * conn->securityMaxTrailerSize */
                hadd32(call->bytesSent, cp->length);
                rxi_PrepareSendPacket(call, cp, 0);
+#ifdef RX_TRACK_PACKETS
                cp->flags |= RX_PKTFLAG_TQ;
+#endif
                queue_Append(&call->tq, cp);
 #ifdef RXDEBUG_PACKET
                 call->tqc++;
@@ -769,7 +769,9 @@ rxi_WriteProc(struct rx_call *call, char *buf,
                    rxi_Start(0, call, 0, 0);
                }
            } else if (cp) {
+#ifdef RX_TRACK_PACKETS
                cp->flags &= ~RX_PKTFLAG_CP;
+#endif
                rxi_FreePacket(cp);
                cp = call->currentPacket = (struct rx_packet *)0;
            }
@@ -794,11 +796,13 @@ rxi_WriteProc(struct rx_call *call, char *buf,
 #endif /* RX_ENABLE_LOCKS */
            }
            if ((cp = rxi_AllocSendPacket(call, nbytes))) {
+#ifdef RX_TRACK_PACKETS
                cp->flags |= RX_PKTFLAG_CP;
+#endif
                call->currentPacket = cp;
                call->nFree = cp->length;
                call->curvec = 1;       /* 0th vec is always header */
-               /* begin at the beginning [ more or less ], continue 
+               /* begin at the beginning [ more or less ], continue
                 * on until the end, then stop. */
                call->curpos =
                    (char *)cp->wirevec[1].iov_base +
@@ -808,7 +812,9 @@ rxi_WriteProc(struct rx_call *call, char *buf,
            }
            if (call->error) {
                if (cp) {
+#ifdef RX_TRACK_PACKETS
                    cp->flags &= ~RX_PKTFLAG_CP;
+#endif
                    rxi_FreePacket(cp);
                    call->currentPacket = NULL;
                }
@@ -880,13 +886,7 @@ rx_WriteProc(struct rx_call *call, char *buf, int nbytes)
     char *tcurpos;
     SPLVAR;
 
-    /*
-     * Free any packets from the last call to ReadvProc/WritevProc.
-     * We do not need the lock because the receiver threads only
-     * touch the iovq when the RX_CALL_IOVEC_WAIT flag is set, and the
-     * RX_CALL_IOVEC_WAIT is always cleared before returning from
-     * ReadvProc/WritevProc.
-     */
+    /* Free any packets from the last call to ReadvProc/WritevProc */
     if (queue_IsNotEmpty(&call->iovq)) {
 #ifdef RXDEBUG_PACKET
         call->iovqc -=
@@ -896,15 +896,13 @@ rx_WriteProc(struct rx_call *call, char *buf, int nbytes)
 
     /*
      * Most common case: all of the data fits in the current iovec.
-     * We do not need the lock because this is the only thread that
-     * updates the curlen, curpos, nFree fields.
-     *
      * We are relying on nFree being zero unless the call is in send mode.
      */
     tcurlen = (int)call->curlen;
     tnFree = (int)call->nFree;
     if (!call->error && tcurlen >= nbytes && tnFree >= nbytes) {
        tcurpos = call->curpos;
+
        memcpy(tcurpos, buf, nbytes);
        call->curpos = tcurpos + nbytes;
        call->curlen = (u_short)(tcurlen - nbytes);
@@ -930,13 +928,6 @@ rx_WriteProc32(struct rx_call *call, afs_int32 * value)
     char *tcurpos;
     SPLVAR;
 
-    /*
-     * Free any packets from the last call to ReadvProc/WritevProc.
-     * We do not need the lock because the receiver threads only
-     * touch the iovq when the RX_CALL_IOVEC_WAIT flag is set, and the
-     * RX_CALL_IOVEC_WAIT is always cleared before returning from
-     * ReadvProc/WritevProc.
-     */
     if (queue_IsNotEmpty(&call->iovq)) {
 #ifdef RXDEBUG_PACKET
         call->iovqc -=
@@ -946,9 +937,6 @@ rx_WriteProc32(struct rx_call *call, afs_int32 * value)
 
     /*
      * Most common case: all of the data fits in the current iovec.
-     * We do not need the lock because this is the only thread that
-     * updates the curlen, curpos, nFree fields.
-     *
      * We are relying on nFree being zero unless the call is in send mode.
      */
     tcurlen = call->curlen;
@@ -956,6 +944,7 @@ rx_WriteProc32(struct rx_call *call, afs_int32 * value)
     if (!call->error && tcurlen >= sizeof(afs_int32)
        && tnFree >= sizeof(afs_int32)) {
        tcurpos = call->curpos;
+
        if (!((size_t)tcurpos & (sizeof(afs_int32) - 1))) {
            *((afs_int32 *) (tcurpos)) = *value;
        } else {
@@ -992,7 +981,7 @@ rxi_WritevAlloc(struct rx_call *call, struct iovec *iov, int *nio, int maxio,
     int nextio;
     /* Temporary values, real work is done in rxi_WritevProc */
     int tnFree;
-    int tcurvec;
+    unsigned int tcurvec;
     char *tcurpos;
     int tcurlen;
 
@@ -1012,7 +1001,9 @@ rxi_WritevAlloc(struct rx_call *call, struct iovec *iov, int *nio, int maxio,
            && (call->mode == RX_MODE_RECEIVING)) {
            call->mode = RX_MODE_SENDING;
            if (cp) {
+#ifdef RX_TRACK_PACKETS
                cp->flags &= ~RX_PKTFLAG_CP;
+#endif
                rxi_FreePacket(cp);
                cp = call->currentPacket = (struct rx_packet *)0;
                call->nLeft = 0;
@@ -1029,7 +1020,7 @@ rxi_WritevAlloc(struct rx_call *call, struct iovec *iov, int *nio, int maxio,
     tcurpos = call->curpos;
     tcurlen = call->curlen;
     do {
-       unsigned int t;
+       int t;
 
        if (tnFree == 0) {
            /* current packet is full, allocate a new one */
@@ -1039,7 +1030,9 @@ rxi_WritevAlloc(struct rx_call *call, struct iovec *iov, int *nio, int maxio,
                *nio = nextio;
                return requestCount - nbytes;
            }
+#ifdef RX_TRACK_PACKETS
            cp->flags |= RX_PKTFLAG_IOVQ;
+#endif
            queue_Append(&call->iovq, cp);
 #ifdef RXDEBUG_PACKET
             call->iovqc++;
@@ -1121,7 +1114,9 @@ int
 rxi_WritevProc(struct rx_call *call, struct iovec *iov, int nio, int nbytes)
 {
     struct rx_packet *cp = NULL;
+#ifdef RX_TRACK_PACKETS
     struct rx_packet *p, *np;
+#endif
     int nextio;
     int requestCount;
     struct rx_queue tmpq;
@@ -1140,11 +1135,15 @@ rxi_WritevProc(struct rx_call *call, struct iovec *iov, int nio, int nbytes)
      * packets to the transmit queue.  */
     while (!call->error && call->flags & RX_CALL_TQ_BUSY) {
        call->flags |= RX_CALL_TQ_WAIT;
+        call->tqWaiters++;
 #ifdef RX_ENABLE_LOCKS
        CV_WAIT(&call->cv_tq, &call->lock);
 #else /* RX_ENABLE_LOCKS */
        osi_rxSleep(&call->tq);
 #endif /* RX_ENABLE_LOCKS */
+        call->tqWaiters--;
+        if (call->tqWaiters == 0)
+            call->flags &= ~RX_CALL_TQ_WAIT;
     }
 #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
     /* cp is no longer valid since we may have given up the lock */
@@ -1152,8 +1151,10 @@ rxi_WritevProc(struct rx_call *call, struct iovec *iov, int nio, int nbytes)
 
     if (call->error) {
        if (cp) {
+#ifdef RX_TRACK_PACKETS
             cp->flags &= ~RX_PKTFLAG_CP;
             cp->flags |= RX_PKTFLAG_IOVQ;
+#endif
            queue_Prepend(&call->iovq, cp);
 #ifdef RXDEBUG_PACKET
             call->iovqc++;
@@ -1180,7 +1181,7 @@ rxi_WritevProc(struct rx_call *call, struct iovec *iov, int nio, int nbytes)
     do {
        if (call->nFree == 0 && cp) {
            clock_NewTime();    /* Bogus:  need new time package */
-           /* The 0, below, specifies that it is not the last packet: 
+           /* The 0, below, specifies that it is not the last packet:
             * there will be others. PrepareSendPacket may
             * alter the packet length by up to
             * conn->securityMaxTrailerSize */
@@ -1204,11 +1205,15 @@ rxi_WritevProc(struct rx_call *call, struct iovec *iov, int nio, int nbytes)
                }
                cp = queue_First(&call->iovq, rx_packet);
                queue_Remove(cp);
+#ifdef RX_TRACK_PACKETS
                 cp->flags &= ~RX_PKTFLAG_IOVQ;
+#endif
 #ifdef RXDEBUG_PACKET
                 call->iovqc--;
 #endif /* RXDEBUG_PACKET */
+#ifdef RX_TRACK_PACKETS
                 cp->flags |= RX_PKTFLAG_CP;
+#endif
                call->currentPacket = cp;
                call->nFree = cp->length;
                call->curvec = 1;
@@ -1226,7 +1231,9 @@ rxi_WritevProc(struct rx_call *call, struct iovec *iov, int nio, int nbytes)
                || iov[nextio].iov_len > (int)call->curlen) {
                call->error = RX_PROTOCOL_ERROR;
                if (cp) {
+#ifdef RX_TRACK_PACKETS
                    cp->flags &= ~RX_PKTFLAG_CP;
+#endif
                     queue_Prepend(&tmpq, cp);
 #ifdef RXDEBUG_PACKET
                     tmpqc++;
@@ -1257,11 +1264,13 @@ rxi_WritevProc(struct rx_call *call, struct iovec *iov, int nio, int nbytes)
 
     /* Move the packets from the temporary queue onto the transmit queue.
      * We may end up with more than call->twind packets on the queue. */
-    
+
+#ifdef RX_TRACK_PACKETS
     for (queue_Scan(&tmpq, p, np, rx_packet))
     {
         p->flags |= RX_PKTFLAG_TQ;
     }
+#endif
     queue_SpliceAppend(&call->tq, &tmpq);
 
     if (!(call->flags & (RX_CALL_FAST_RECOVER | RX_CALL_FAST_RECOVER_WAIT))) {
@@ -1285,7 +1294,9 @@ rxi_WritevProc(struct rx_call *call, struct iovec *iov, int nio, int nbytes)
 
     if (call->error) {
        if (cp) {
+#ifdef RX_TRACK_PACKETS
            cp->flags &= ~RX_PKTFLAG_CP;
+#endif
            rxi_FreePacket(cp);
             cp = call->currentPacket = (struct rx_packet *)0;
        }
@@ -1349,11 +1360,15 @@ rxi_FlushWrite(struct rx_call *call)
         */
        while (call->flags & RX_CALL_TQ_BUSY) {
            call->flags |= RX_CALL_TQ_WAIT;
+            call->tqWaiters++;
 #ifdef RX_ENABLE_LOCKS
            CV_WAIT(&call->cv_tq, &call->lock);
 #else /* RX_ENABLE_LOCKS */
            osi_rxSleep(&call->tq);
 #endif /* RX_ENABLE_LOCKS */
+            call->tqWaiters--;
+            if (call->tqWaiters == 0)
+                call->flags &= ~RX_CALL_TQ_WAIT;
        }
 #endif /* AFS_GLOBAL_RXLOCK_KERNEL */
 
@@ -1362,9 +1377,11 @@ rxi_FlushWrite(struct rx_call *call)
 
        if (cp) {
            /* cp->length is only supposed to be the user's data */
-           /* cp->length was already set to (then-current) 
+           /* cp->length was already set to (then-current)
             * MaxUserDataSize or less. */
+#ifdef RX_TRACK_PACKETS
            cp->flags &= ~RX_PKTFLAG_CP;
+#endif
            cp->length -= call->nFree;
            call->currentPacket = (struct rx_packet *)0;
            call->nFree = 0;
@@ -1382,7 +1399,9 @@ rxi_FlushWrite(struct rx_call *call)
        /* The 1 specifies that this is the last packet */
        hadd32(call->bytesSent, cp->length);
        rxi_PrepareSendPacket(call, cp, 1);
+#ifdef RX_TRACK_PACKETS
        cp->flags |= RX_PKTFLAG_TQ;
+#endif
        queue_Append(&call->tq, cp);
 #ifdef RXDEBUG_PACKET
         call->tqc++;