[PATCH v3 11/17] net,l2tp: use new hashtable implementation

2012-08-21 Thread Sasha Levin
Switch l2tp to use the new hashtable implementation. This reduces the amount of
generic unrelated code in l2tp.

Signed-off-by: Sasha Levin 
---
 net/l2tp/l2tp_core.c|  134 +-
 net/l2tp/l2tp_core.h|8 ++--
 net/l2tp/l2tp_debugfs.c |   19 +++
 3 files changed, 61 insertions(+), 100 deletions(-)

diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 393355d..1d395ce 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -44,6 +44,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -107,8 +108,8 @@ static unsigned int l2tp_net_id;
 struct l2tp_net {
struct list_head l2tp_tunnel_list;
spinlock_t l2tp_tunnel_list_lock;
-   struct hlist_head l2tp_session_hlist[L2TP_HASH_SIZE_2];
-   spinlock_t l2tp_session_hlist_lock;
+   DEFINE_HASHTABLE(l2tp_session_hash, L2TP_HASH_BITS_2)
+   spinlock_t l2tp_session_hash_lock;
 };
 
 static void l2tp_session_set_header_len(struct l2tp_session *session, int 
version);
@@ -156,30 +157,17 @@ do {  
\
 #define l2tp_tunnel_dec_refcount(t) l2tp_tunnel_dec_refcount_1(t)
 #endif
 
-/* Session hash global list for L2TPv3.
- * The session_id SHOULD be random according to RFC3931, but several
- * L2TP implementations use incrementing session_ids.  So we do a real
- * hash on the session_id, rather than a simple bitmask.
- */
-static inline struct hlist_head *
-l2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id)
-{
-   return >l2tp_session_hlist[hash_32(session_id, L2TP_HASH_BITS_2)];
-
-}
-
 /* Lookup a session by id in the global session list
  */
 static struct l2tp_session *l2tp_session_find_2(struct net *net, u32 
session_id)
 {
struct l2tp_net *pn = l2tp_pernet(net);
-   struct hlist_head *session_list =
-   l2tp_session_id_hash_2(pn, session_id);
struct l2tp_session *session;
struct hlist_node *walk;
 
rcu_read_lock_bh();
-   hlist_for_each_entry_rcu(session, walk, session_list, global_hlist) {
+   hash_for_each_possible_rcu(pn->l2tp_session_hash, session, walk,
+   global_hlist, session_id) {
if (session->session_id == session_id) {
rcu_read_unlock_bh();
return session;
@@ -190,23 +178,10 @@ static struct l2tp_session *l2tp_session_find_2(struct 
net *net, u32 session_id)
return NULL;
 }
 
-/* Session hash list.
- * The session_id SHOULD be random according to RFC2661, but several
- * L2TP implementations (Cisco and Microsoft) use incrementing
- * session_ids.  So we do a real hash on the session_id, rather than a
- * simple bitmask.
- */
-static inline struct hlist_head *
-l2tp_session_id_hash(struct l2tp_tunnel *tunnel, u32 session_id)
-{
-   return >session_hlist[hash_32(session_id, L2TP_HASH_BITS)];
-}
-
 /* Lookup a session by id
  */
 struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel 
*tunnel, u32 session_id)
 {
-   struct hlist_head *session_list;
struct l2tp_session *session;
struct hlist_node *walk;
 
@@ -217,15 +192,14 @@ struct l2tp_session *l2tp_session_find(struct net *net, 
struct l2tp_tunnel *tunn
if (tunnel == NULL)
return l2tp_session_find_2(net, session_id);
 
-   session_list = l2tp_session_id_hash(tunnel, session_id);
-   read_lock_bh(>hlist_lock);
-   hlist_for_each_entry(session, walk, session_list, hlist) {
+   read_lock_bh(>hash_lock);
+   hash_for_each_possible(tunnel->session_hash, session, walk, hlist, 
session_id) {
if (session->session_id == session_id) {
-   read_unlock_bh(>hlist_lock);
+   read_unlock_bh(>hash_lock);
return session;
}
}
-   read_unlock_bh(>hlist_lock);
+   read_unlock_bh(>hash_lock);
 
return NULL;
 }
@@ -238,17 +212,15 @@ struct l2tp_session *l2tp_session_find_nth(struct 
l2tp_tunnel *tunnel, int nth)
struct l2tp_session *session;
int count = 0;
 
-   read_lock_bh(>hlist_lock);
-   for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
-   hlist_for_each_entry(session, walk, 
>session_hlist[hash], hlist) {
-   if (++count > nth) {
-   read_unlock_bh(>hlist_lock);
-   return session;
-   }
+   read_lock_bh(>hash_lock);
+   hash_for_each(tunnel->session_hash, hash, walk, session, hlist) {
+   if (++count > nth) {
+   read_unlock_bh(>hash_lock);
+   return session;
}
}
 
-   read_unlock_bh(>hlist_lock);
+   read_unlock_bh(>hash_lock);
 
return NULL;
 }
@@ -265,12 +237,10 @@ struct l2tp_session 

[PATCH v3 11/17] net,l2tp: use new hashtable implementation

2012-08-21 Thread Sasha Levin
Switch l2tp to use the new hashtable implementation. This reduces the amount of
generic unrelated code in l2tp.

Signed-off-by: Sasha Levin levinsasha...@gmail.com
---
 net/l2tp/l2tp_core.c|  134 +-
 net/l2tp/l2tp_core.h|8 ++--
 net/l2tp/l2tp_debugfs.c |   19 +++
 3 files changed, 61 insertions(+), 100 deletions(-)

diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 393355d..1d395ce 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -44,6 +44,7 @@
 #include linux/udp.h
 #include linux/l2tp.h
 #include linux/hash.h
+#include linux/hashtable.h
 #include linux/sort.h
 #include linux/file.h
 #include linux/nsproxy.h
@@ -107,8 +108,8 @@ static unsigned int l2tp_net_id;
 struct l2tp_net {
struct list_head l2tp_tunnel_list;
spinlock_t l2tp_tunnel_list_lock;
-   struct hlist_head l2tp_session_hlist[L2TP_HASH_SIZE_2];
-   spinlock_t l2tp_session_hlist_lock;
+   DEFINE_HASHTABLE(l2tp_session_hash, L2TP_HASH_BITS_2)
+   spinlock_t l2tp_session_hash_lock;
 };
 
 static void l2tp_session_set_header_len(struct l2tp_session *session, int 
version);
@@ -156,30 +157,17 @@ do {  
\
 #define l2tp_tunnel_dec_refcount(t) l2tp_tunnel_dec_refcount_1(t)
 #endif
 
-/* Session hash global list for L2TPv3.
- * The session_id SHOULD be random according to RFC3931, but several
- * L2TP implementations use incrementing session_ids.  So we do a real
- * hash on the session_id, rather than a simple bitmask.
- */
-static inline struct hlist_head *
-l2tp_session_id_hash_2(struct l2tp_net *pn, u32 session_id)
-{
-   return pn-l2tp_session_hlist[hash_32(session_id, L2TP_HASH_BITS_2)];
-
-}
-
 /* Lookup a session by id in the global session list
  */
 static struct l2tp_session *l2tp_session_find_2(struct net *net, u32 
session_id)
 {
struct l2tp_net *pn = l2tp_pernet(net);
-   struct hlist_head *session_list =
-   l2tp_session_id_hash_2(pn, session_id);
struct l2tp_session *session;
struct hlist_node *walk;
 
rcu_read_lock_bh();
-   hlist_for_each_entry_rcu(session, walk, session_list, global_hlist) {
+   hash_for_each_possible_rcu(pn-l2tp_session_hash, session, walk,
+   global_hlist, session_id) {
if (session-session_id == session_id) {
rcu_read_unlock_bh();
return session;
@@ -190,23 +178,10 @@ static struct l2tp_session *l2tp_session_find_2(struct 
net *net, u32 session_id)
return NULL;
 }
 
-/* Session hash list.
- * The session_id SHOULD be random according to RFC2661, but several
- * L2TP implementations (Cisco and Microsoft) use incrementing
- * session_ids.  So we do a real hash on the session_id, rather than a
- * simple bitmask.
- */
-static inline struct hlist_head *
-l2tp_session_id_hash(struct l2tp_tunnel *tunnel, u32 session_id)
-{
-   return tunnel-session_hlist[hash_32(session_id, L2TP_HASH_BITS)];
-}
-
 /* Lookup a session by id
  */
 struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel 
*tunnel, u32 session_id)
 {
-   struct hlist_head *session_list;
struct l2tp_session *session;
struct hlist_node *walk;
 
@@ -217,15 +192,14 @@ struct l2tp_session *l2tp_session_find(struct net *net, 
struct l2tp_tunnel *tunn
if (tunnel == NULL)
return l2tp_session_find_2(net, session_id);
 
-   session_list = l2tp_session_id_hash(tunnel, session_id);
-   read_lock_bh(tunnel-hlist_lock);
-   hlist_for_each_entry(session, walk, session_list, hlist) {
+   read_lock_bh(tunnel-hash_lock);
+   hash_for_each_possible(tunnel-session_hash, session, walk, hlist, 
session_id) {
if (session-session_id == session_id) {
-   read_unlock_bh(tunnel-hlist_lock);
+   read_unlock_bh(tunnel-hash_lock);
return session;
}
}
-   read_unlock_bh(tunnel-hlist_lock);
+   read_unlock_bh(tunnel-hash_lock);
 
return NULL;
 }
@@ -238,17 +212,15 @@ struct l2tp_session *l2tp_session_find_nth(struct 
l2tp_tunnel *tunnel, int nth)
struct l2tp_session *session;
int count = 0;
 
-   read_lock_bh(tunnel-hlist_lock);
-   for (hash = 0; hash  L2TP_HASH_SIZE; hash++) {
-   hlist_for_each_entry(session, walk, 
tunnel-session_hlist[hash], hlist) {
-   if (++count  nth) {
-   read_unlock_bh(tunnel-hlist_lock);
-   return session;
-   }
+   read_lock_bh(tunnel-hash_lock);
+   hash_for_each(tunnel-session_hash, hash, walk, session, hlist) {
+   if (++count  nth) {
+   read_unlock_bh(tunnel-hash_lock);
+   return session;
}