Re: xfrm_state locking regression...

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Timo Teräs
Date: Tuesday, September 23, 2008 - 5:08 am

Herbert Xu wrote:

So the patch would look something like this. Compile tested.
Will test later when it becomes possible to reboot my box.

Cheers,
 Timo

ipsec: Fix up xfrm_state_walk.state on node deletion

Now that we track xfrm_state_walks, it makes more sense to
fix up the state pointer on deletion of the node if needed.

This allows accurately to delete all entries immediately,
instead of possibly waiting for userland.

Also fixed locking of xfrm_state_walks list handling.

Signed-off-by: Timo Teras <timo.teras@iki.fi>
---
 include/linux/netlink.h |    2 +-
 include/net/xfrm.h      |    3 +-
 net/xfrm/xfrm_state.c   |   77 +++++++++++++++++-----------------------------
 3 files changed, 31 insertions(+), 51 deletions(-)

diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index cbba776..9ff1b54 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -220,7 +220,7 @@ struct netlink_callback
 	int		(*dump)(struct sk_buff * skb, struct netlink_callback *cb);
 	int		(*done)(struct netlink_callback *cb);
 	int		family;
-	long		args[7];
+	long		args[6];
 };
 
 struct netlink_notify
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 48630b2..7f787c7 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -122,7 +122,7 @@ struct xfrm_state
 {
 	struct list_head	all;
 	union {
-		struct list_head	gclist;
+		struct hlist_node	gclist;
 		struct hlist_node	bydst;
 	};
 	struct hlist_node	bysrc;
@@ -1247,7 +1247,6 @@ struct xfrm6_tunnel {
 
 struct xfrm_state_walk {
 	struct list_head list;
-	unsigned long genid;
 	struct xfrm_state *state;
 	int count;
 	u8 proto;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 053970e..636f7ee 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -59,11 +59,6 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
 static unsigned int xfrm_state_num;
 static unsigned int xfrm_state_genid;
 
-/* Counter indicating ongoing walk, protected by xfrm_state_lock. */
-static unsigned long xfrm_state_walk_ongoing;
-/* Counter indicating walk completion, protected by xfrm_cfg_mutex. */
-static unsigned long xfrm_state_walk_completed;
-
 /* List of outstanding state walks used to set the completed counter.  */
 static LIST_HEAD(xfrm_state_walks);
 
@@ -199,8 +194,7 @@ static DEFINE_RWLOCK(xfrm_state_afinfo_lock);
 static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
 
 static struct work_struct xfrm_state_gc_work;
-static LIST_HEAD(xfrm_state_gc_leftovers);
-static LIST_HEAD(xfrm_state_gc_list);
+static HLIST_HEAD(xfrm_state_gc_list);
 static DEFINE_SPINLOCK(xfrm_state_gc_lock);
 
 int __xfrm_state_delete(struct xfrm_state *x);
@@ -412,23 +406,16 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
 
 static void xfrm_state_gc_task(struct work_struct *data)
 {
-	struct xfrm_state *x, *tmp;
-	unsigned long completed;
+	struct xfrm_state *x;
+	struct hlist_node *entry, *tmp;
+	struct hlist_head gc_list;
 
-	mutex_lock(&xfrm_cfg_mutex);
 	spin_lock_bh(&xfrm_state_gc_lock);
-	list_splice_tail_init(&xfrm_state_gc_list, &xfrm_state_gc_leftovers);
+	hlist_move_list(&xfrm_state_gc_list, &gc_list);
 	spin_unlock_bh(&xfrm_state_gc_lock);
 
-	completed = xfrm_state_walk_completed;
-	mutex_unlock(&xfrm_cfg_mutex);
-
-	list_for_each_entry_safe(x, tmp, &xfrm_state_gc_leftovers, gclist) {
-		if ((long)(x->lastused - completed) > 0)
-			break;
-		list_del(&x->gclist);
+	hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist)
 		xfrm_state_gc_destroy(x);
-	}
 
 	wake_up(&km_waitq);
 }
@@ -556,7 +543,7 @@ void __xfrm_state_destroy(struct xfrm_state *x)
 	WARN_ON(x->km.state != XFRM_STATE_DEAD);
 
 	spin_lock_bh(&xfrm_state_gc_lock);
-	list_add_tail(&x->gclist, &xfrm_state_gc_list);
+	hlist_add_head(&x->gclist, &xfrm_state_gc_list);
 	spin_unlock_bh(&xfrm_state_gc_lock);
 	schedule_work(&xfrm_state_gc_work);
 }
@@ -564,13 +551,22 @@ EXPORT_SYMBOL(__xfrm_state_destroy);
 
 int __xfrm_state_delete(struct xfrm_state *x)
 {
+	struct xfrm_state_walk *walk;
+	struct xfrm_state *next;
 	int err = -ESRCH;
 
 	if (x->km.state != XFRM_STATE_DEAD) {
 		x->km.state = XFRM_STATE_DEAD;
 		spin_lock(&xfrm_state_lock);
-		x->lastused = xfrm_state_walk_ongoing;
-		list_del_rcu(&x->all);
+		if (list_is_last(&x->all, &xfrm_state_walks))
+			next = NULL;
+		else
+			next = container_of(x->all.next, struct xfrm_state, all);
+		list_for_each_entry(walk, &xfrm_state_walks, list) {
+			if (walk->state == x)
+				walk->state = next;
+		}
+		list_del(&x->all);
 		hlist_del(&x->bydst);
 		hlist_del(&x->bysrc);
 		if (x->id.spi)
@@ -1566,15 +1562,16 @@ int xfrm_state_walk(struct xfrm_state_walk *walk,
 		    int (*func)(struct xfrm_state *, int, void*),
 		    void *data)
 {
-	struct xfrm_state *old, *x, *last = NULL;
+	struct xfrm_state *x, *last = NULL;
 	int err = 0;
 
 	if (walk->state == NULL && walk->count != 0)
 		return 0;
 
-	old = x = walk->state;
-	walk->state = NULL;
 	spin_lock_bh(&xfrm_state_lock);
+	x = walk->state;
+	walk->state = NULL;
+
 	if (x == NULL)
 		x = list_first_entry(&xfrm_state_all, struct xfrm_state, all);
 	list_for_each_entry_from(x, &xfrm_state_all, all) {
@@ -1585,7 +1582,6 @@ int xfrm_state_walk(struct xfrm_state_walk *walk,
 		if (last) {
 			err = func(last, walk->count, data);
 			if (err) {
-				xfrm_state_hold(last);
 				walk->state = last;
 				goto out;
 			}
@@ -1601,8 +1597,7 @@ int xfrm_state_walk(struct xfrm_state_walk *walk,
 		err = func(last, 0, data);
 out:
 	spin_unlock_bh(&xfrm_state_lock);
-	if (old != NULL)
-		xfrm_state_put(old);
+
 	return err;
 }
 EXPORT_SYMBOL(xfrm_state_walk);
@@ -1612,33 +1607,19 @@ void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto)
 	walk->proto = proto;
 	walk->state = NULL;
 	walk->count = 0;
+
+	spin_lock_bh(&xfrm_state_lock);
 	list_add_tail(&walk->list, &xfrm_state_walks);
-	walk->genid = ++xfrm_state_walk_ongoing;
+	spin_unlock_bh(&xfrm_state_lock);
 }
 EXPORT_SYMBOL(xfrm_state_walk_init);
 
 void xfrm_state_walk_done(struct xfrm_state_walk *walk)
 {
-	struct list_head *prev;
-
-	if (walk->state != NULL) {
-		xfrm_state_put(walk->state);
-		walk->state = NULL;
-	}
-
-	prev = walk->list.prev;
+	spin_lock_bh(&xfrm_state_lock);
 	list_del(&walk->list);
-
-	if (prev != &xfrm_state_walks) {
-		list_entry(prev, struct xfrm_state_walk, list)->genid =
-			walk->genid;
-		return;
-	}
-
-	xfrm_state_walk_completed = walk->genid;
-
-	if (!list_empty(&xfrm_state_gc_leftovers))
-		schedule_work(&xfrm_state_gc_work);
+	spin_unlock_bh(&xfrm_state_lock);
+	walk->state = NULL;
 }
 EXPORT_SYMBOL(xfrm_state_walk_done);
 
-- 
1.5.4.3
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
xfrm_state locking regression..., David Miller, (Tue Sep 2, 7:51 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 2, 8:00 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 2, 10:01 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 2, 10:07 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 2, 10:23 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 2, 10:39 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 2, 10:39 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 2, 10:40 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 2, 10:45 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 2, 10:50 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 2, 11:10 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 2, 11:14 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 2, 11:27 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 2, 11:35 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 2, 11:45 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 2, 11:47 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Wed Sep 3, 12:14 am)
Re: xfrm_state locking regression..., Herbert Xu, (Fri Sep 5, 4:55 am)
Re: xfrm_state locking regression..., David Miller, (Mon Sep 8, 5:09 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Mon Sep 8, 5:18 pm)
Re: xfrm_state locking regression..., David Miller, (Mon Sep 8, 5:20 pm)
Re: xfrm_state locking regression..., David Miller, (Mon Sep 8, 5:25 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 9, 5:25 am)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 9, 7:33 am)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 9, 1:20 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 9, 8:01 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 9, 8:04 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 9, 8:15 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 9, 8:22 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 9, 8:23 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 9, 8:38 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 9, 9:01 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 9, 9:06 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 9, 9:22 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 9, 9:24 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 9, 9:48 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 9, 9:52 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 9, 9:53 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 9, 10:16 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 9, 10:21 pm)
Re: xfrm_state locking regression..., David Miller, (Tue Sep 9, 10:23 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 9, 10:46 pm)
Re: xfrm_state locking regression..., Paul E. McKenney, (Thu Sep 11, 2:24 pm)
Re: xfrm_state locking regression..., David Miller, (Thu Sep 11, 3:00 pm)
Re: xfrm_state locking regression..., Paul E. McKenney, (Thu Sep 11, 4:22 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Fri Sep 12, 9:08 am)
Re: xfrm_state locking regression..., Paul E. McKenney, (Fri Sep 12, 10:37 am)
Re: xfrm_state locking regression..., Timo Teräs, (Sun Sep 21, 5:29 am)
Re: xfrm_state locking regression..., Timo Teräs, (Sun Sep 21, 8:21 am)
Re: xfrm_state locking regression..., Herbert Xu, (Mon Sep 22, 4:42 am)
Re: xfrm_state locking regression..., Timo Teräs, (Mon Sep 22, 6:01 am)
Re: xfrm_state locking regression..., Herbert Xu, (Mon Sep 22, 4:50 pm)
Re: xfrm_state locking regression..., David Miller, (Mon Sep 22, 7:48 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Mon Sep 22, 9:53 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Mon Sep 22, 9:59 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Mon Sep 22, 10:17 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Mon Sep 22, 10:22 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Mon Sep 22, 11:25 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Mon Sep 22, 11:47 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Mon Sep 22, 11:56 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 23, 2:39 am)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 23, 4:24 am)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 23, 5:08 am)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 23, 5:14 am)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 23, 5:25 am)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 23, 5:56 am)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 23, 6:01 am)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 23, 6:07 am)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 23, 6:30 am)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 23, 6:32 am)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 23, 6:46 am)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 23, 9:23 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 23, 10:14 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 23, 10:15 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 23, 10:46 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 23, 10:55 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 23, 11:04 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 23, 11:13 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Tue Sep 23, 11:20 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Tue Sep 23, 11:21 pm)
Re: xfrm_state locking regression..., Timo Teräs, (Wed Sep 24, 12:29 am)
Re: xfrm_state locking regression..., Herbert Xu, (Wed Sep 24, 12:54 am)
Re: xfrm_state locking regression..., Timo Teräs, (Wed Sep 24, 6:18 am)
Re: xfrm_state locking regression..., Herbert Xu, (Wed Sep 24, 7:08 am)
Re: xfrm_state locking regression..., Timo Teräs, (Wed Sep 24, 11:03 pm)
Re: xfrm_state locking regression..., Herbert Xu, (Thu Sep 25, 12:57 am)
Re: xfrm_state locking regression..., Timo Teräs, (Thu Sep 25, 1:42 am)
Re: xfrm_state locking regression..., Herbert Xu, (Thu Sep 25, 1:56 am)
Re: xfrm_state locking regression..., Timo Teräs, (Thu Sep 25, 2:01 am)
Re: xfrm_state locking regression..., Herbert Xu, (Thu Sep 25, 2:49 am)
Re: xfrm_state locking regression..., Timo Teräs, (Thu Sep 25, 5:12 am)
Re: xfrm_state locking regression..., Timo Teräs, (Thu Sep 25, 5:36 am)
Re: xfrm_state locking regression..., Herbert Xu, (Thu Sep 25, 7:08 pm)
Re: xfrm_state locking regression..., David Miller, (Wed Oct 1, 3:07 am)
Re: xfrm_state locking regression..., Herbert Xu, (Wed Oct 1, 7:05 am)