patch-2.3.4 linux/net/ipv4/ip_fragment.c
Next file: linux/net/ipv4/ip_input.c
Previous file: linux/net/ipv4/igmp.c
Back to the patch index
Back to the overall index
- Lines: 108
- Date:
Wed May 26 18:14:37 1999
- Orig file:
v2.3.3/linux/net/ipv4/ip_fragment.c
- Orig date:
Sun Mar 21 07:22:00 1999
diff -u --recursive --new-file v2.3.3/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c
@@ -5,7 +5,7 @@
*
* The IP fragmentation functionality.
*
- * Version: $Id: ip_fragment.c,v 1.40 1999/03/20 23:58:34 davem Exp $
+ * Version: $Id: ip_fragment.c,v 1.41 1999/05/27 00:38:07 davem Exp $
*
* Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
* Alan Cox <Alan.Cox@linux.org>
@@ -71,7 +71,8 @@
#define IPQ_HASHSZ 64
-struct ipq *ipq_hash[IPQ_HASHSZ];
+static struct ipq *ipq_hash[IPQ_HASHSZ];
+static spinlock_t ipfrag_lock = SPIN_LOCK_UNLOCKED;
#define ipqhashfn(id, saddr, daddr, prot) \
((((id) >> 1) ^ (saddr) ^ (daddr) ^ (prot)) & (IPQ_HASHSZ - 1))
@@ -141,7 +142,9 @@
unsigned int hash = ipqhashfn(id, saddr, daddr, protocol);
struct ipq *qp;
- /* Always, we are in a BH context, so no locking. -DaveM */
+ /* We are always in BH context, and protected by the
+ * ipfrag lock.
+ */
for(qp = ipq_hash[hash]; qp; qp = qp->next) {
if(qp->iph->id == id &&
qp->iph->saddr == saddr &&
@@ -158,8 +161,9 @@
* because we completed, reassembled and processed it, or because
* it timed out.
*
- * This is called _only_ from BH contexts, on packet reception
- * processing and from frag queue expiration timers. -DaveM
+ * This is called _only_ from BH contexts with the ipfrag lock held,
+ * on packet reception processing and from frag queue expiration
+ * timers. -DaveM
*/
static void ip_free(struct ipq *qp)
{
@@ -197,6 +201,7 @@
{
struct ipq *qp = (struct ipq *) arg;
+ spin_lock(&ipfrag_lock);
if(!qp->fragments)
{
#ifdef IP_EXPIRE_DEBUG
@@ -213,10 +218,13 @@
out:
/* Nuke the fragment queue. */
ip_free(qp);
+ spin_lock(&ipfrag_lock);
}
/* Memory limiting on fragments. Evictor trashes the oldest
* fragment queue until we are back under the low threshold.
+ *
+ * We are always called in BH with the ipfrag lock held.
*/
static void ip_evictor(void)
{
@@ -229,9 +237,6 @@
struct ipq *qp;
if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh)
return;
- /* We are in a BH context, so these queue
- * accesses are safe. -DaveM
- */
qp = ipq_hash[i];
if (qp) {
/* find the oldest queue for this hash bucket */
@@ -283,7 +288,7 @@
/* Add this entry to the queue. */
hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
- /* We are in a BH context, no locking necessary. -DaveM */
+ /* In a BH context and ipfrag lock is held. -DaveM */
if((qp->next = ipq_hash[hash]) != NULL)
qp->next->pprev = &qp->next;
ipq_hash[hash] = qp;
@@ -421,6 +426,8 @@
ip_statistics.IpReasmReqds++;
+ spin_lock(&ipfrag_lock);
+
/* Start by cleaning up the memory. */
if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh)
ip_evictor();
@@ -565,6 +572,7 @@
out_freequeue:
ip_free(qp);
out_skb:
+ spin_unlock(&ipfrag_lock);
return skb;
}
@@ -574,6 +582,7 @@
out_timer:
mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time); /* ~ 30 seconds */
out:
+ spin_unlock(&ipfrag_lock);
return NULL;
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)