]> err.no Git - linux-2.6/blobdiff - net/ipv4/ip_fragment.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6] / net / ipv4 / ip_fragment.c
index e8736632094ad25443be5ec1e6b5aa5c2471ead9..443b3f89192f5841f78e7783874f9c8b9b479020 100644 (file)
@@ -144,7 +144,7 @@ static __inline__ void ip4_frag_free(struct inet_frag_queue *q)
 
 static __inline__ struct ipq *frag_alloc_queue(void)
 {
-       struct ipq *qp = kmalloc(sizeof(struct ipq), GFP_ATOMIC);
+       struct ipq *qp = kzalloc(sizeof(struct ipq), GFP_ATOMIC);
 
        if (!qp)
                return NULL;
@@ -155,10 +155,9 @@ static __inline__ struct ipq *frag_alloc_queue(void)
 
 /* Destruction primitives. */
 
-static __inline__ void ipq_put(struct ipq *ipq, int *work)
+static __inline__ void ipq_put(struct ipq *ipq)
 {
-       if (atomic_dec_and_test(&ipq->q.refcnt))
-               inet_frag_destroy(&ipq->q, &ip4_frags, work);
+       inet_frag_put(&ipq->q, &ip4_frags);
 }
 
 /* Kill ipq entry. It is not destroyed immediately,
@@ -174,33 +173,11 @@ static void ipq_kill(struct ipq *ipq)
  */
 static void ip_evictor(void)
 {
-       struct ipq *qp;
-       struct list_head *tmp;
-       int work;
-
-       work = atomic_read(&ip4_frags.mem) - ip4_frags_ctl.low_thresh;
-       if (work <= 0)
-               return;
-
-       while (work > 0) {
-               read_lock(&ip4_frags.lock);
-               if (list_empty(&ip4_frags.lru_list)) {
-                       read_unlock(&ip4_frags.lock);
-                       return;
-               }
-               tmp = ip4_frags.lru_list.next;
-               qp = list_entry(tmp, struct ipq, q.lru_list);
-               atomic_inc(&qp->q.refcnt);
-               read_unlock(&ip4_frags.lock);
-
-               spin_lock(&qp->q.lock);
-               if (!(qp->q.last_in&COMPLETE))
-                       ipq_kill(qp);
-               spin_unlock(&qp->q.lock);
+       int evicted;
 
-               ipq_put(qp, &work);
-               IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
-       }
+       evicted = inet_frag_evictor(&ip4_frags);
+       if (evicted)
+               IP_ADD_STATS_BH(IPSTATS_MIB_REASMFAILS, evicted);
 }
 
 /*
@@ -230,7 +207,7 @@ static void ip_expire(unsigned long arg)
        }
 out:
        spin_unlock(&qp->q.lock);
-       ipq_put(qp, NULL);
+       ipq_put(qp);
 }
 
 /* Creation primitives. */
@@ -260,7 +237,7 @@ static struct ipq *ip_frag_intern(struct ipq *qp_in)
                        atomic_inc(&qp->q.refcnt);
                        write_unlock(&ip4_frags.lock);
                        qp_in->q.last_in |= COMPLETE;
-                       ipq_put(qp_in, NULL);
+                       ipq_put(qp_in);
                        return qp;
                }
        }
@@ -288,15 +265,10 @@ static struct ipq *ip_frag_create(struct iphdr *iph, u32 user)
                goto out_nomem;
 
        qp->protocol = iph->protocol;
-       qp->q.last_in = 0;
        qp->id = iph->id;
        qp->saddr = iph->saddr;
        qp->daddr = iph->daddr;
        qp->user = user;
-       qp->q.len = 0;
-       qp->q.meat = 0;
-       qp->q.fragments = NULL;
-       qp->iif = 0;
        qp->peer = sysctl_ipfrag_max_dist ? inet_getpeer(iph->saddr, 1) : NULL;
 
        /* Initialize a timer for this entry. */
@@ -686,7 +658,7 @@ int ip_defrag(struct sk_buff *skb, u32 user)
                ret = ip_frag_queue(qp, skb);
 
                spin_unlock(&qp->q.lock);
-               ipq_put(qp, NULL);
+               ipq_put(qp);
                return ret;
        }