rx-rdwr-writeproc-race-20081228
[openafs.git] / src / rx / rx_rdwr.c
index 1417144..2c3b37b 100644 (file)
@@ -58,6 +58,7 @@ RCSID
 #include "rx/rx_kernel.h"
 #include "rx/rx_clock.h"
 #include "rx/rx_queue.h"
+#include "rx/rx_internal.h"
 #include "rx/rx.h"
 #include "rx/rx_globals.h"
 #include "afs/lock.h"
@@ -88,6 +89,7 @@ RCSID
 # include "rx_user.h"
 # include "rx_clock.h"
 # include "rx_queue.h"
+# include "rx_internal.h"
 # include "rx.h"
 # include "rx_globals.h"
 #endif /* KERNEL */
@@ -387,7 +389,7 @@ rx_ReadProc32(struct rx_call *call, afs_int32 * value)
        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) {
+        if (!call->nLeft && call->currentPacket != NULL) {
             /* out of packet.  Get another one. */
             NETPRI;
             MUTEX_ENTER(&call->lock);
@@ -698,6 +700,13 @@ rxi_WriteProc(register struct rx_call *call, register char *buf,
     do {
        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 
+                 * cannot be freed.
+                 */
+                cp->flags &= ~RX_PKTFLAG_CP;
+               call->currentPacket = (struct rx_packet *)0;
 #ifdef AFS_GLOBAL_RXLOCK_KERNEL
                /* Wait until TQ_BUSY is reset before adding any
                 * packets to the transmit queue
@@ -718,17 +727,16 @@ rxi_WriteProc(register struct rx_call *call, register char *buf,
                 * conn->securityMaxTrailerSize */
                hadd32(call->bytesSent, cp->length);
                rxi_PrepareSendPacket(call, cp, 0);
-               cp->flags &= ~RX_PKTFLAG_CP;
                cp->flags |= RX_PKTFLAG_TQ;
                queue_Append(&call->tq, cp);
-               cp = call->currentPacket = (struct rx_packet *)0;
+               cp = (struct rx_packet *)0;
                if (!
                    (call->
                     flags & (RX_CALL_FAST_RECOVER |
                              RX_CALL_FAST_RECOVER_WAIT))) {
                    rxi_Start(0, call, 0, 0);
                }
-           } else else if (cp) {
+           } else if (cp) {
                cp->flags &= ~RX_PKTFLAG_CP;
                rxi_FreePacket(cp);
                cp = call->currentPacket = (struct rx_packet *)0;
@@ -1121,6 +1129,7 @@ rxi_WritevProc(struct rx_call *call, struct iovec *iov, int nio, int nbytes)
            rxi_PrepareSendPacket(call, cp, 0);
            cp->flags |= RX_PKTFLAG_TQ;
            queue_Append(&tmpq, cp);
+            cp = call->currentPacket = (struct rx_packet *)0;
 
            /* The head of the iovq is now the current packet */
            if (nbytes) {
@@ -1152,6 +1161,7 @@ rxi_WritevProc(struct rx_call *call, struct iovec *iov, int nio, int nbytes)
                if (cp) {
                    cp->flags &= ~RX_PKTFLAG_CP;
                    queue_Prepend(&tmpq, cp);
+                    cp = call->currentPacket = (struct rx_packet *)0;
                }
                rxi_FreePackets(0, &tmpq);
                return 0;
@@ -1197,6 +1207,7 @@ rxi_WritevProc(struct rx_call *call, struct iovec *iov, int nio, int nbytes)
        if (cp) {
            cp->flags &= ~RX_PKTFLAG_CP;
            rxi_FreePacket(cp);
+            cp = call->currentPacket = (struct rx_packet *)0;
        }
        return 0;
     }