Commit 4357947c authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/home/davem/src/BK/network-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents 2ba74897 751ec6f5
...@@ -84,6 +84,7 @@ extern struct semaphore xfrm_cfg_sem; ...@@ -84,6 +84,7 @@ extern struct semaphore xfrm_cfg_sem;
/* Full description of state of transformer. */ /* Full description of state of transformer. */
struct xfrm_state struct xfrm_state
{ {
/* Note: bydst is re-used during gc */
struct list_head bydst; struct list_head bydst;
struct list_head byspi; struct list_head byspi;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* *
*/ */
#include <linux/workqueue.h>
#include <net/xfrm.h> #include <net/xfrm.h>
#include <linux/pfkeyv2.h> #include <linux/pfkeyv2.h>
#include <linux/ipsec.h> #include <linux/ipsec.h>
...@@ -41,8 +42,45 @@ DECLARE_WAIT_QUEUE_HEAD(km_waitq); ...@@ -41,8 +42,45 @@ DECLARE_WAIT_QUEUE_HEAD(km_waitq);
static rwlock_t xfrm_state_afinfo_lock = RW_LOCK_UNLOCKED; static rwlock_t xfrm_state_afinfo_lock = RW_LOCK_UNLOCKED;
static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
static struct work_struct xfrm_state_gc_work;
static struct list_head xfrm_state_gc_list = LIST_HEAD_INIT(xfrm_state_gc_list);
static spinlock_t xfrm_state_gc_lock = SPIN_LOCK_UNLOCKED;
static void __xfrm_state_delete(struct xfrm_state *x); static void __xfrm_state_delete(struct xfrm_state *x);
static void xfrm_state_gc_destroy(struct xfrm_state *x)
{
if (del_timer(&x->timer))
BUG();
if (x->aalg)
kfree(x->aalg);
if (x->ealg)
kfree(x->ealg);
if (x->calg)
kfree(x->calg);
if (x->encap)
kfree(x->encap);
if (x->type)
xfrm_put_type(x->type);
kfree(x);
}
static void xfrm_state_gc_task(void *data)
{
struct xfrm_state *x;
struct list_head *entry, *tmp;
struct list_head gc_list = LIST_HEAD_INIT(gc_list);
spin_lock_bh(&xfrm_state_gc_lock);
list_splice_init(&xfrm_state_gc_list, &gc_list);
spin_unlock_bh(&xfrm_state_gc_lock);
list_for_each_safe(entry, tmp, &gc_list) {
x = list_entry(entry, struct xfrm_state, bydst);
xfrm_state_gc_destroy(x);
}
}
static inline unsigned long make_jiffies(long secs) static inline unsigned long make_jiffies(long secs)
{ {
if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ) if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
...@@ -149,19 +187,11 @@ struct xfrm_state *xfrm_state_alloc(void) ...@@ -149,19 +187,11 @@ struct xfrm_state *xfrm_state_alloc(void)
void __xfrm_state_destroy(struct xfrm_state *x) void __xfrm_state_destroy(struct xfrm_state *x)
{ {
BUG_TRAP(x->km.state == XFRM_STATE_DEAD); BUG_TRAP(x->km.state == XFRM_STATE_DEAD);
if (del_timer(&x->timer))
BUG(); spin_lock_bh(&xfrm_state_gc_lock);
if (x->aalg) list_add(&x->bydst, &xfrm_state_gc_list);
kfree(x->aalg); spin_unlock_bh(&xfrm_state_gc_lock);
if (x->ealg) schedule_work(&xfrm_state_gc_work);
kfree(x->ealg);
if (x->calg)
kfree(x->calg);
if (x->encap)
kfree(x->encap);
if (x->type)
xfrm_put_type(x->type);
kfree(x);
} }
static void __xfrm_state_delete(struct xfrm_state *x) static void __xfrm_state_delete(struct xfrm_state *x)
...@@ -773,5 +803,6 @@ void __init xfrm_state_init(void) ...@@ -773,5 +803,6 @@ void __init xfrm_state_init(void)
INIT_LIST_HEAD(&xfrm_state_bydst[i]); INIT_LIST_HEAD(&xfrm_state_bydst[i]);
INIT_LIST_HEAD(&xfrm_state_byspi[i]); INIT_LIST_HEAD(&xfrm_state_byspi[i]);
} }
INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment