]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
STABLE14-freepackets-cbuf-leak-20051130
authorTom Keiser <tkeiser@gmail.com>
Thu, 1 Dec 2005 04:00:39 +0000 (04:00 +0000)
committerDerrick Brashear <shadow@dementia.org>
Thu, 1 Dec 2005 04:00:39 +0000 (04:00 +0000)
FIXES 23143

at least i'm guessing it fixes that one
fix memory leak for multilevel packet queue stuff

(cherry picked from commit 421e063d9b6500299b5e02b999b22c01dcc7c496)

src/rx/rx_packet.c

index 33eed2402fff9c3622df7f3921e3d461dd56e4d9..4963667e41eff92d6e84795febad71c2862d69a2 100644 (file)
@@ -114,6 +114,9 @@ static void rxi_SendDebugPacket(struct rx_packet *apacket, osi_socket asocket,
                                afs_int32 ahost, short aport,
                                afs_int32 istack);
 
+static int rxi_FreeDataBufsToQueue(struct rx_packet *p, int first, 
+                                  struct rx_queue * q);
+
 /* some rules about packets:
  * 1.  When a packet is allocated, the final iov_buf contains room for
  * a security trailer, but iov_len masks that fact.  If the security
@@ -381,14 +384,22 @@ rxi_FreePackets(int num_pkts, struct rx_queue * q)
     register struct rx_packet *c, *nc;
     SPLVAR;
 
+    osi_Assert(num_pkts >= 0);
+    RX_TS_INFO_GET(rx_ts_info);
+
     if (!num_pkts) {
-       queue_Count(q, c, nc, rx_packet, num_pkts);
-       if (!num_pkts)
-           return 0;
+       for (queue_Scan(q, c, nc, rx_packet), num_pkts++) {
+           rxi_FreeDataBufsTSFPQ(c, 1, 0);
+       }
+    } else {
+       for (queue_Scan(q, c, nc, rx_packet)) {
+           rxi_FreeDataBufsTSFPQ(c, 1, 0);
+       }
     }
 
-    RX_TS_INFO_GET(rx_ts_info);
-    RX_TS_FPQ_CHECKIN2(rx_ts_info, num_pkts, q);
+    if (num_pkts) {
+       RX_TS_FPQ_CHECKIN2(rx_ts_info, num_pkts, q);
+    }
 
     if (rx_ts_info->_FPQ.len > rx_TSFPQLocalMax) {
         NETPRI;
@@ -410,26 +421,43 @@ rxi_FreePackets(int num_pkts, struct rx_queue * q)
 int
 rxi_FreePackets(int num_pkts, struct rx_queue *q)
 {
+    struct rx_queue cbs;
     register struct rx_packet *p, *np;
+    int qlen = 0;
     SPLVAR;
 
+    osi_Assert(num_pkts >= 0);
+    queue_Init(&cbs);
+
     if (!num_pkts) {
         for (queue_Scan(q, p, np, rx_packet), num_pkts++) {
+           if (p->niovecs > 2) {
+               qlen += rxi_FreeDataBufsToQueue(p, 2, &cbs);
+           }
             RX_FPQ_MARK_FREE(p);
        }
        if (!num_pkts)
            return 0;
     } else {
         for (queue_Scan(q, p, np, rx_packet)) {
+           if (p->niovecs > 2) {
+               qlen += rxi_FreeDataBufsToQueue(p, 2, &cbs);
+           }
             RX_FPQ_MARK_FREE(p);
        }
     }
 
+    if (qlen) {
+       queue_SpliceAppend(q, &cbs);
+       qlen += num_pkts;
+    } else
+       qlen = num_pkts;
+
     NETPRI;
     MUTEX_ENTER(&rx_freePktQ_lock);
 
     queue_SpliceAppend(&rx_freePacketQueue, q);
-    rx_nFreePackets += num_pkts;
+    rx_nFreePackets += qlen;
 
     /* Wakeup anyone waiting for packets */
     rxi_PacketsUnWait();
@@ -777,6 +805,27 @@ rxi_FreePacketTSFPQ(struct rx_packet *p, int flush_global)
 }
 #endif /* RX_ENABLE_TSFPQ */
 
+/* free continuation buffers off a packet into a queue of buffers */
+static int
+rxi_FreeDataBufsToQueue(struct rx_packet *p, int first, struct rx_queue * q)
+{
+    struct iovec *iov;
+    int count = 0;
+
+    if (first < 2)
+       first = 2;
+    for (; first < p->niovecs; first++, count++) {
+       iov = &p->wirevec[first];
+       if (!iov->iov_base)
+           osi_Panic("rxi_PacketIOVToQueue: unexpected NULL iov");
+       queue_Append(q, RX_CBUF_TO_PACKET(iov->iov_base, p));
+    }
+    p->length = 0;
+    p->niovecs = 0;
+
+    return count;
+}
+
 int
 rxi_FreeDataBufsNoLock(struct rx_packet *p, int first)
 {