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;
/* 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,
*/
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);
}
/*
}
out:
spin_unlock(&qp->q.lock);
- ipq_put(qp, NULL);
+ ipq_put(qp);
}
/* Creation primitives. */
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;
}
}
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. */
ret = ip_frag_queue(qp, skb);
spin_unlock(&qp->q.lock);
- ipq_put(qp, NULL);
+ ipq_put(qp);
return ret;
}