diff options
Diffstat (limited to 'net/ipv4/inet_fragment.c')
-rw-r--r-- | net/ipv4/inet_fragment.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 15fb2c4a36a..484cf512858 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 | } |
142 | EXPORT_SYMBOL(inet_frag_destroy); | 142 | EXPORT_SYMBOL(inet_frag_destroy); |
143 | |||
144 | int 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 | } | ||
174 | EXPORT_SYMBOL(inet_frag_evictor); | ||