aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/inet_fragment.c32
-rw-r--r--net/ipv4/ip_fragment.c30
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c29
-rw-r--r--net/ipv6/reassembly.c30
4 files changed, 41 insertions, 80 deletions
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index 15fb2c4a36a7..484cf512858f 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -140,3 +140,35 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f,
140 140
141} 141}
142EXPORT_SYMBOL(inet_frag_destroy); 142EXPORT_SYMBOL(inet_frag_destroy);
143
144int inet_frag_evictor(struct inet_frags *f)
145{
146 struct inet_frag_queue *q;
147 int work, evicted = 0;
148
149 work = atomic_read(&f->mem) - f->ctl->low_thresh;
150 while (work > 0) {
151 read_lock(&f->lock);
152 if (list_empty(&f->lru_list)) {
153 read_unlock(&f->lock);
154 break;
155 }
156
157 q = list_first_entry(&f->lru_list,
158 struct inet_frag_queue, lru_list);
159 atomic_inc(&q->refcnt);
160 read_unlock(&f->lock);
161
162 spin_lock(&q->lock);
163 if (!(q->last_in & COMPLETE))
164 inet_frag_kill(q, f);
165 spin_unlock(&q->lock);
166
167 if (atomic_dec_and_test(&q->refcnt))
168 inet_frag_destroy(q, f, &work);
169 evicted++;
170 }
171
172 return evicted;
173}
174EXPORT_SYMBOL(inet_frag_evictor);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index e8736632094a..ee6e04159627 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -174,33 +174,11 @@ static void ipq_kill(struct ipq *ipq)
174 */ 174 */
175static void ip_evictor(void) 175static void ip_evictor(void)
176{ 176{
177 struct ipq *qp; 177 int evicted;
178 struct list_head *tmp;
179 int work;
180
181 work = atomic_read(&ip4_frags.mem) - ip4_frags_ctl.low_thresh;
182 if (work <= 0)
183 return;
184
185 while (work > 0) {
186 read_lock(&ip4_frags.lock);
187 if (list_empty(&ip4_frags.lru_list)) {
188 read_unlock(&ip4_frags.lock);
189 return;
190 }
191 tmp = ip4_frags.lru_list.next;
192 qp = list_entry(tmp, struct ipq, q.lru_list);
193 atomic_inc(&qp->q.refcnt);
194 read_unlock(&ip4_frags.lock);
195 178
196 spin_lock(&qp->q.lock); 179 evicted = inet_frag_evictor(&ip4_frags);
197 if (!(qp->q.last_in&COMPLETE)) 180 if (evicted)
198 ipq_kill(qp); 181 IP_ADD_STATS_BH(IPSTATS_MIB_REASMFAILS, evicted);
199 spin_unlock(&qp->q.lock);
200
201 ipq_put(qp, &work);
202 IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS);
203 }
204} 182}
205 183
206/* 184/*
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 785f5cda188e..e4fbe5ba88f1 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -163,34 +163,7 @@ static __inline__ void fq_kill(struct nf_ct_frag6_queue *fq)
163 163
164static void nf_ct_frag6_evictor(void) 164static void nf_ct_frag6_evictor(void)
165{ 165{
166 struct nf_ct_frag6_queue *fq; 166 inet_frag_evictor(&nf_frags);
167 struct list_head *tmp;
168 unsigned int work;
169
170 work = atomic_read(&nf_frags.mem);
171 if (work <= nf_frags_ctl.low_thresh)
172 return;
173
174 work -= nf_frags_ctl.low_thresh;
175 while (work > 0) {
176 read_lock(&nf_frags.lock);
177 if (list_empty(&nf_frags.lru_list)) {
178 read_unlock(&nf_frags.lock);
179 return;
180 }
181 tmp = nf_frags.lru_list.next;
182 BUG_ON(tmp == NULL);
183 fq = list_entry(tmp, struct nf_ct_frag6_queue, q.lru_list);
184 atomic_inc(&fq->q.refcnt);
185 read_unlock(&nf_frags.lock);
186
187 spin_lock(&fq->q.lock);
188 if (!(fq->q.last_in&COMPLETE))
189 fq_kill(fq);
190 spin_unlock(&fq->q.lock);
191
192 fq_put(fq, &work);
193 }
194} 167}
195 168
196static void nf_ct_frag6_expire(unsigned long data) 169static void nf_ct_frag6_expire(unsigned long data)
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 940b7d2383ec..02e4e855b927 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -185,33 +185,11 @@ static __inline__ void fq_kill(struct frag_queue *fq)
185 185
186static void ip6_evictor(struct inet6_dev *idev) 186static void ip6_evictor(struct inet6_dev *idev)
187{ 187{
188 struct frag_queue *fq; 188 int evicted;
189 struct list_head *tmp;
190 int work;
191
192 work = atomic_read(&ip6_frags.mem) - ip6_frags_ctl.low_thresh;
193 if (work <= 0)
194 return;
195
196 while(work > 0) {
197 read_lock(&ip6_frags.lock);
198 if (list_empty(&ip6_frags.lru_list)) {
199 read_unlock(&ip6_frags.lock);
200 return;
201 }
202 tmp = ip6_frags.lru_list.next;
203 fq = list_entry(tmp, struct frag_queue, q.lru_list);
204 atomic_inc(&fq->q.refcnt);
205 read_unlock(&ip6_frags.lock);
206 189
207 spin_lock(&fq->q.lock); 190 evicted = inet_frag_evictor(&ip6_frags);
208 if (!(fq->q.last_in&COMPLETE)) 191 if (evicted)
209 fq_kill(fq); 192 IP6_ADD_STATS_BH(idev, IPSTATS_MIB_REASMFAILS, evicted);
210 spin_unlock(&fq->q.lock);
211
212 fq_put(fq, &work);
213 IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS);
214 }
215} 193}
216 194
217static void ip6_frag_expire(unsigned long data) 195static void ip6_frag_expire(unsigned long data)