From: Jon M. <jon...@er...> - 2015-01-07 15:47:25
|
> -----Original Message----- > From: Ying Xue [mailto:yin...@wi...] > Sent: December-30-14 10:02 PM > To: ma...@do...; Erik Hugne; Pau...@wi... > Cc: Jon Maloy; Richard Alpe; Ter...@co...; > yin...@wi...; tip...@li... > Subject: [PATCH net-next v2 11/16] tipc: make tipc socket support net > namespace > > Now tipc socket table is statically allocated as a global variable. > Through it, we can look up one socket instance with port ID, insert a new > socket instance to the talbe, /talbe/table/ ///jon >and delete a socket from the table. But when > tipc supports net namespace, each namespace must own its specific socket > table. So the global variable of socket table must be redefined in tipc_net > structure. As a concequence, a new socket table will be allocated when a > new namespace is created, and a socket table will be deallocated when > namespace is destroyed. > > Signed-off-by: Ying Xue <yin...@wi...> > Tested-by: Tero Aho <Ter...@co...> > --- > net/tipc/config.c | 2 +- > net/tipc/core.c | 12 ++++------ > net/tipc/core.h | 5 ++++ > net/tipc/net.c | 2 +- > net/tipc/socket.c | 69 +++++++++++++++++++++++++++++++--------------- > ------- > net/tipc/socket.h | 8 +++---- > 6 files changed, 55 insertions(+), 43 deletions(-) > > diff --git a/net/tipc/config.c b/net/tipc/config.c index ac73291..20b1c58 > 100644 > --- a/net/tipc/config.c > +++ b/net/tipc/config.c > @@ -257,7 +257,7 @@ struct sk_buff *tipc_cfg_do_cmd(struct net *net, u32 > orig_node, u16 cmd, > rep_tlv_buf = tipc_media_get_names(); > break; > case TIPC_CMD_SHOW_PORTS: > - rep_tlv_buf = tipc_sk_socks_show(); > + rep_tlv_buf = tipc_sk_socks_show(net); > break; > case TIPC_CMD_SHOW_STATS: > rep_tlv_buf = tipc_show_stats(); > diff --git a/net/tipc/core.c b/net/tipc/core.c index 7b84439..23ff3ca 100644 > --- a/net/tipc/core.c > +++ b/net/tipc/core.c > @@ -55,17 +55,20 @@ int sysctl_tipc_rmem[3] __read_mostly; /* > min/default/max */ > static int __net_init tipc_init_net(struct net *net) { > struct tipc_net *tn = net_generic(net, tipc_net_id); > + int err; > > tn->net_id = 4711; > INIT_LIST_HEAD(&tn->node_list); > spin_lock_init(&tn->node_list_lock); > > - return 0; > + err = tipc_sk_rht_init(net); > + return err; > } > > static void __net_exit tipc_exit_net(struct net *net) { > tipc_net_stop(net); > + tipc_sk_rht_destroy(net); > } > > static struct pernet_operations tipc_net_ops = { @@ -95,10 +98,6 @@ static > int __init tipc_init(void) > if (err) > goto out_pernet; > > - err = tipc_sk_rht_init(); > - if (err) > - goto out_reftbl; > - > err = tipc_nametbl_init(); > if (err) > goto out_nametbl; > @@ -136,8 +135,6 @@ out_socket: > out_netlink: > tipc_nametbl_stop(); > out_nametbl: > - tipc_sk_rht_destroy(); > -out_reftbl: > unregister_pernet_subsys(&tipc_net_ops); > out_pernet: > pr_err("Unable to start in single node mode\n"); @@ -153,7 +150,6 > @@ static void __exit tipc_exit(void) > tipc_nametbl_stop(); > tipc_socket_stop(); > tipc_unregister_sysctl(); > - tipc_sk_rht_destroy(); > > pr_info("Deactivated\n"); > } > diff --git a/net/tipc/core.h b/net/tipc/core.h index 3f6f9e0..b2e9caae 100644 > --- a/net/tipc/core.h > +++ b/net/tipc/core.h > @@ -58,6 +58,7 @@ > #include <linux/rtnetlink.h> > #include <linux/etherdevice.h> > #include <net/netns/generic.h> > +#include <linux/rhashtable.h> > > #include "node.h" > #include "bearer.h" > @@ -101,6 +102,10 @@ struct tipc_net { > struct tipc_bcbearer *bcbearer; > struct tipc_bclink *bclink; > struct tipc_link *bcl; > + > + /* Socket hash table */ > + struct mutex sk_rht_lock; > + struct rhashtable sk_rht; > }; > > #ifdef CONFIG_SYSCTL > diff --git a/net/tipc/net.c b/net/tipc/net.c index 7548ba8..44ccf47 100644 > --- a/net/tipc/net.c > +++ b/net/tipc/net.c > @@ -117,7 +117,7 @@ int tipc_net_start(struct net *net, u32 addr) > > tipc_own_addr = addr; > tipc_named_reinit(); > - tipc_sk_reinit(); > + tipc_sk_reinit(net); > res = tipc_bclink_init(net); > if (res) > return res; > diff --git a/net/tipc/socket.c b/net/tipc/socket.c index c9957c5..79ca08f > 100644 > --- a/net/tipc/socket.c > +++ b/net/tipc/socket.c > @@ -115,7 +115,7 @@ static int tipc_sk_publish(struct tipc_sock *tsk, uint > scope, > struct tipc_name_seq const *seq); static int > tipc_sk_withdraw(struct tipc_sock *tsk, uint scope, > struct tipc_name_seq const *seq); -static struct > tipc_sock *tipc_sk_lookup(u32 portid); > +static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid); > static int tipc_sk_insert(struct tipc_sock *tsk); static void > tipc_sk_remove(struct tipc_sock *tsk); > > @@ -179,14 +179,10 @@ static const struct nla_policy > tipc_nl_sock_policy[TIPC_NLA_SOCK_MAX + 1] = { > * - port reference > */ > > -/* Protects tipc socket hash table mutations */ -static > DEFINE_MUTEX(tipc_sk_hash_lock); -static struct rhashtable tipc_sk_rht; > - > #ifdef CONFIG_PROVE_LOCKING > static int lockdep_tipc_sk_hash_is_held(void *parent) { > - return (debug_locks) ? lockdep_is_held(&tipc_sk_hash_lock) : 1; > + return 1; > } > #endif > > @@ -1774,7 +1770,7 @@ int tipc_sk_rcv(struct net *net, struct sk_buff *skb) > u32 dnode; > > /* Validate destination and message */ > - tsk = tipc_sk_lookup(dport); > + tsk = tipc_sk_lookup(net, dport); > if (unlikely(!tsk)) { > rc = tipc_msg_eval(skb, &dnode); > goto exit; > @@ -2253,8 +2249,9 @@ static int tipc_sk_show(struct tipc_sock *tsk, char > *buf, > return ret; > } > > -struct sk_buff *tipc_sk_socks_show(void) > +struct sk_buff *tipc_sk_socks_show(struct net *net) > { > + struct tipc_net *tn = net_generic(net, tipc_net_id); > const struct bucket_table *tbl; > struct sk_buff *buf; > struct tlv_desc *rep_tlv; > @@ -2272,7 +2269,7 @@ struct sk_buff *tipc_sk_socks_show(void) > pb_len = ULTRA_STRING_MAX_LEN; > > rcu_read_lock(); > - tbl = rht_dereference_rcu((&tipc_sk_rht)->tbl, &tipc_sk_rht); > + tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); > for (i = 0; i < tbl->size; i++) { > rht_for_each_entry_rcu(tsk, tbl->buckets[i], node) { > spin_lock_bh(&tsk->sk.sk_lock.slock); > @@ -2293,15 +2290,16 @@ struct sk_buff *tipc_sk_socks_show(void) > /* tipc_sk_reinit: set non-zero address in all existing sockets > * when we go from standalone to network mode. > */ > -void tipc_sk_reinit(void) > +void tipc_sk_reinit(struct net *net) > { > + struct tipc_net *tn = net_generic(net, tipc_net_id); > const struct bucket_table *tbl; > struct tipc_sock *tsk; > struct tipc_msg *msg; > int i; > > rcu_read_lock(); > - tbl = rht_dereference_rcu((&tipc_sk_rht)->tbl, &tipc_sk_rht); > + tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); > for (i = 0; i < tbl->size; i++) { > rht_for_each_entry_rcu(tsk, tbl->buckets[i], node) { > spin_lock_bh(&tsk->sk.sk_lock.slock); > @@ -2314,12 +2312,13 @@ void tipc_sk_reinit(void) > rcu_read_unlock(); > } > > -static struct tipc_sock *tipc_sk_lookup(u32 portid) > +static struct tipc_sock *tipc_sk_lookup(struct net *net, u32 portid) > { > + struct tipc_net *tn = net_generic(net, tipc_net_id); > struct tipc_sock *tsk; > > rcu_read_lock(); > - tsk = rhashtable_lookup(&tipc_sk_rht, &portid); > + tsk = rhashtable_lookup(&tn->sk_rht, &portid); > if (tsk) > sock_hold(&tsk->sk); > rcu_read_unlock(); > @@ -2327,9 +2326,10 @@ static struct tipc_sock *tipc_sk_lookup(u32 portid) > return tsk; > } > > -static u32 tipc_sk_get_port(void) > +static u32 tipc_sk_get_port(struct net *net) > { > - struct rhashtable *ht = &tipc_sk_rht; > + struct tipc_net *tn = net_generic(net, tipc_net_id); > + struct rhashtable *ht = &tn->sk_rht; > struct bucket_table *tbl = rht_dereference(ht->tbl, ht); > u32 remaining = (TIPC_MAX_PORT - TIPC_MIN_PORT) + 1; > struct tipc_sock *tsk; > @@ -2363,35 +2363,40 @@ static u32 tipc_sk_get_port(void) > > static int tipc_sk_insert(struct tipc_sock *tsk) { > + struct sock *sk = &tsk->sk; > + struct net *net = sock_net(sk); > + struct tipc_net *tn = net_generic(net, tipc_net_id); > u32 portid; > > - mutex_lock(&tipc_sk_hash_lock); > - portid = tipc_sk_get_port(); > + mutex_lock(&tn->sk_rht_lock); > + portid = tipc_sk_get_port(net); > if (!portid) { > - mutex_unlock(&tipc_sk_hash_lock); > + mutex_unlock(&tn->sk_rht_lock); > return -1; > } > tsk->portid = portid; > sock_hold(&tsk->sk); > - rhashtable_insert(&tipc_sk_rht, &tsk->node); > - mutex_unlock(&tipc_sk_hash_lock); > + rhashtable_insert(&tn->sk_rht, &tsk->node); > + mutex_unlock(&tn->sk_rht_lock); > return 0; > } > > static void tipc_sk_remove(struct tipc_sock *tsk) { > struct sock *sk = &tsk->sk; > + struct tipc_net *tn = net_generic(sock_net(sk), tipc_net_id); > > - mutex_lock(&tipc_sk_hash_lock); > - if (rhashtable_remove(&tipc_sk_rht, &tsk->node)) { > + mutex_lock(&tn->sk_rht_lock); > + if (rhashtable_remove(&tn->sk_rht, &tsk->node)) { > WARN_ON(atomic_read(&sk->sk_refcnt) == 1); > __sock_put(sk); > } > - mutex_unlock(&tipc_sk_hash_lock); > + mutex_unlock(&tn->sk_rht_lock); > } > > -int tipc_sk_rht_init(void) > +int tipc_sk_rht_init(struct net *net) > { > + struct tipc_net *tn = net_generic(net, tipc_net_id); > struct rhashtable_params rht_params = { > .nelem_hint = 256, > .head_offset = offsetof(struct tipc_sock, node), @@ - > 2407,15 +2412,18 @@ int tipc_sk_rht_init(void) #endif > }; > > - return rhashtable_init(&tipc_sk_rht, &rht_params); > + mutex_init(&tn->sk_rht_lock); > + return rhashtable_init(&tn->sk_rht, &rht_params); > } > > -void tipc_sk_rht_destroy(void) > +void tipc_sk_rht_destroy(struct net *net) > { > + struct tipc_net *tn = net_generic(net, tipc_net_id); > + > /* Wait for socket readers to complete */ > synchronize_net(); > > - rhashtable_destroy(&tipc_sk_rht); > + rhashtable_destroy(&tn->sk_rht); > } > > /** > @@ -2772,10 +2780,12 @@ int tipc_nl_sk_dump(struct sk_buff *skb, struct > netlink_callback *cb) > const struct bucket_table *tbl; > u32 prev_portid = cb->args[0]; > u32 portid = prev_portid; > + struct net *net = sock_net(skb->sk); > + struct tipc_net *tn = net_generic(net, tipc_net_id); > int i; > > rcu_read_lock(); > - tbl = rht_dereference_rcu((&tipc_sk_rht)->tbl, &tipc_sk_rht); > + tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); > for (i = 0; i < tbl->size; i++) { > rht_for_each_entry_rcu(tsk, tbl->buckets[i], node) { > spin_lock_bh(&tsk->sk.sk_lock.slock); > @@ -2881,6 +2891,7 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct > netlink_callback *cb) > u32 tsk_portid = cb->args[0]; > u32 last_publ = cb->args[1]; > u32 done = cb->args[2]; > + struct net *net = sock_net(skb->sk); > struct tipc_sock *tsk; > > if (!tsk_portid) { > @@ -2906,7 +2917,7 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct > netlink_callback *cb) > if (done) > return 0; > > - tsk = tipc_sk_lookup(tsk_portid); > + tsk = tipc_sk_lookup(net, tsk_portid); > if (!tsk) > return -EINVAL; > > diff --git a/net/tipc/socket.h b/net/tipc/socket.h index eb15c31..c15c4e1 > 100644 > --- a/net/tipc/socket.h > +++ b/net/tipc/socket.h > @@ -50,11 +50,11 @@ void tipc_sock_release_local(struct socket *sock); int > tipc_sock_accept_local(struct socket *sock, struct socket **newsock, > int flags); > int tipc_sk_rcv(struct net *net, struct sk_buff *buf); -struct sk_buff > *tipc_sk_socks_show(void); > +struct sk_buff *tipc_sk_socks_show(struct net *net); > void tipc_sk_mcast_rcv(struct net *net, struct sk_buff *buf); -void > tipc_sk_reinit(void); -int tipc_sk_rht_init(void); -void > tipc_sk_rht_destroy(void); > +void tipc_sk_reinit(struct net *net); > +int tipc_sk_rht_init(struct net *net); > +void tipc_sk_rht_destroy(struct net *net); > int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb); int > tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb); > > -- > 1.7.9.5 |