Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial
[platform/kernel/linux-rpi.git] / net / ipv6 / netfilter / nf_conntrack_reasm.c
index 4dc8805..13ef5bc 100644 (file)
@@ -114,10 +114,8 @@ static void nf_skb_free(struct sk_buff *skb)
 }
 
 /* Memory Tracking Functions. */
-static inline void frag_kfree_skb(struct sk_buff *skb, unsigned int *work)
+static void frag_kfree_skb(struct sk_buff *skb)
 {
-       if (work)
-               *work -= skb->truesize;
        atomic_sub(skb->truesize, &nf_init_frags.mem);
        nf_skb_free(skb);
        kfree_skb(skb);
@@ -271,6 +269,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
         * in the chain of fragments so far.  We must know where to put
         * this fragment, right?
         */
+       prev = fq->q.fragments_tail;
+       if (!prev || NFCT_FRAG6_CB(prev)->offset < offset) {
+               next = NULL;
+               goto found;
+       }
        prev = NULL;
        for (next = fq->q.fragments; next != NULL; next = next->next) {
                if (NFCT_FRAG6_CB(next)->offset >= offset)
@@ -278,6 +281,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
                prev = next;
        }
 
+found:
        /* We found where to put this one.  Check for overlap with
         * preceding fragment, and, if needed, align things so that
         * any overlaps are eliminated.
@@ -335,7 +339,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
                                fq->q.fragments = next;
 
                        fq->q.meat -= free_it->len;
-                       frag_kfree_skb(free_it, NULL);
+                       frag_kfree_skb(free_it);
                }
        }
 
@@ -343,6 +347,8 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
 
        /* Insert this fragment in the chain of fragments. */
        skb->next = next;
+       if (!next)
+               fq->q.fragments_tail = skb;
        if (prev)
                prev->next = skb;
        else
@@ -442,7 +448,6 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
        skb_shinfo(head)->frag_list = head->next;
        skb_reset_transport_header(head);
        skb_push(head, head->data - skb_network_header(head));
-       atomic_sub(head->truesize, &nf_init_frags.mem);
 
        for (fp=head->next; fp; fp = fp->next) {
                head->data_len += fp->len;
@@ -452,8 +457,8 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
                else if (head->ip_summed == CHECKSUM_COMPLETE)
                        head->csum = csum_add(head->csum, fp->csum);
                head->truesize += fp->truesize;
-               atomic_sub(fp->truesize, &nf_init_frags.mem);
        }
+       atomic_sub(head->truesize, &nf_init_frags.mem);
 
        head->next = NULL;
        head->dev = dev;
@@ -467,6 +472,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
                                          head->csum);
 
        fq->q.fragments = NULL;
+       fq->q.fragments_tail = NULL;
 
        /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */
        fp = skb_shinfo(head)->frag_list;