Commit 751ec6f5 authored by James Morris's avatar James Morris Committed by David S. Miller

[IPSEC]: Move xfrm type destructor out of spinlock.

parent e2635a88
......@@ -84,6 +84,7 @@ extern struct semaphore xfrm_cfg_sem;
/* Full description of state of transformer. */
struct xfrm_state
{
/* Note: bydst is re-used during gc */
struct list_head bydst;
struct list_head byspi;
......
......@@ -13,6 +13,7 @@
*
*/
#include <linux/workqueue.h>
#include <net/xfrm.h>
#include <linux/pfkeyv2.h>
#include <linux/ipsec.h>
......@@ -41,8 +42,45 @@ DECLARE_WAIT_QUEUE_HEAD(km_waitq);
static rwlock_t xfrm_state_afinfo_lock = RW_LOCK_UNLOCKED;
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_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)
{
if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
......@@ -149,19 +187,11 @@ struct xfrm_state *xfrm_state_alloc(void)
void __xfrm_state_destroy(struct xfrm_state *x)
{
BUG_TRAP(x->km.state == XFRM_STATE_DEAD);
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);
spin_lock_bh(&xfrm_state_gc_lock);
list_add(&x->bydst, &xfrm_state_gc_list);
spin_unlock_bh(&xfrm_state_gc_lock);
schedule_work(&xfrm_state_gc_work);
}
static void __xfrm_state_delete(struct xfrm_state *x)
......@@ -773,5 +803,6 @@ void __init xfrm_state_init(void)
INIT_LIST_HEAD(&xfrm_state_bydst[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