@ -34,6 +34,7 @@
* POSSIBILITY OF SUCH DAMAGE .
*/
# include <net/sock.h>
# include "core.h"
# include "config.h"
# include "name_table.h"
@ -106,9 +107,6 @@ struct name_seq {
struct rcu_head rcu ;
} ;
struct name_table * tipc_nametbl ;
DEFINE_SPINLOCK ( tipc_nametbl_lock ) ;
static int hash ( int x )
{
return x & ( TIPC_NAMETBL_SIZE - 1 ) ;
@ -448,12 +446,13 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq,
}
}
static struct name_seq * nametbl_find_seq ( u32 type )
static struct name_seq * nametbl_find_seq ( struct net * net , u32 type )
{
struct tipc_net * tn = net_generic ( net , tipc_net_id ) ;
struct hlist_head * seq_head ;
struct name_seq * ns ;
seq_head = & tipc_ nametbl - > seq_hlist [ hash ( type ) ] ;
seq_head = & tn - > nametbl - > seq_hlist [ hash ( type ) ] ;
hlist_for_each_entry_rcu ( ns , seq_head , ns_list ) {
if ( ns - > type = = type )
return ns ;
@ -462,11 +461,13 @@ static struct name_seq *nametbl_find_seq(u32 type)
return NULL ;
} ;
struct publication * tipc_nametbl_insert_publ ( u32 type , u32 lower , u32 upper ,
u32 scope , u32 node , u32 port , u32 key )
struct publication * tipc_nametbl_insert_publ ( struct net * net , u32 type ,
u32 lower , u32 upper , u32 scope ,
u32 node , u32 port , u32 key )
{
struct tipc_net * tn = net_generic ( net , tipc_net_id ) ;
struct publication * publ ;
struct name_seq * seq = nametbl_find_seq ( type ) ;
struct name_seq * seq = nametbl_find_seq ( net , type ) ;
int index = hash ( type ) ;
if ( ( scope < TIPC_ZONE_SCOPE ) | | ( scope > TIPC_NODE_SCOPE ) | |
@ -477,8 +478,7 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
}
if ( ! seq )
seq = tipc_nameseq_create ( type ,
& tipc_nametbl - > seq_hlist [ index ] ) ;
seq = tipc_nameseq_create ( type , & tn - > nametbl - > seq_hlist [ index ] ) ;
if ( ! seq )
return NULL ;
@ -489,11 +489,12 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
return publ ;
}
struct publication * tipc_nametbl_remove_publ ( u32 type , u32 lower ,
u32 node , u32 ref , u32 key )
struct publication * tipc_nametbl_remove_publ ( struct net * net , u32 type ,
u32 lower , u32 node , u32 ref ,
u32 key )
{
struct publication * publ ;
struct name_seq * seq = nametbl_find_seq ( type ) ;
struct name_seq * seq = nametbl_find_seq ( net , type ) ;
if ( ! seq )
return NULL ;
@ -524,7 +525,8 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
* - if name translation is attempted and fails , sets ' destnode ' to 0
* and returns 0
*/
u32 tipc_nametbl_translate ( u32 type , u32 instance , u32 * destnode )
u32 tipc_nametbl_translate ( struct net * net , u32 type , u32 instance ,
u32 * destnode )
{
struct sub_seq * sseq ;
struct name_info * info ;
@ -537,7 +539,7 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
return 0 ;
rcu_read_lock ( ) ;
seq = nametbl_find_seq ( type ) ;
seq = nametbl_find_seq ( net , type ) ;
if ( unlikely ( ! seq ) )
goto not_found ;
spin_lock_bh ( & seq - > lock ) ;
@ -610,8 +612,8 @@ not_found:
*
* Returns non - zero if any off - node ports overlap
*/
int tipc_nametbl_mc_translate ( u32 type , u32 lower , u32 upper , u32 limit ,
struct tipc_port_list * dports )
int tipc_nametbl_mc_translate ( struct net * net , u32 type , u32 lower , u32 upper ,
u32 limit , struct tipc_port_list * dports )
{
struct name_seq * seq ;
struct sub_seq * sseq ;
@ -620,7 +622,7 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
int res = 0 ;
rcu_read_lock ( ) ;
seq = nametbl_find_seq ( type ) ;
seq = nametbl_find_seq ( net , type ) ;
if ( ! seq )
goto exit ;
@ -657,24 +659,25 @@ struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower,
{
struct publication * publ ;
struct sk_buff * buf = NULL ;
struct tipc_net * tn = net_generic ( net , tipc_net_id ) ;
spin_lock_bh ( & tipc_ nametbl_lock ) ;
if ( tipc_ nametbl - > local_publ_count > = TIPC_MAX_PUBLICATIONS ) {
spin_lock_bh ( & tn - > nametbl_lock ) ;
if ( tn - > nametbl - > local_publ_count > = TIPC_MAX_PUBLICATIONS ) {
pr_warn ( " Publication failed, local publication limit reached (%u) \n " ,
TIPC_MAX_PUBLICATIONS ) ;
spin_unlock_bh ( & tipc_ nametbl_lock ) ;
spin_unlock_bh ( & tn - > nametbl_lock ) ;
return NULL ;
}
publ = tipc_nametbl_insert_publ ( type , lower , upper , scope ,
tipc_own_addr , port_ref , key ) ;
publ = tipc_nametbl_insert_publ ( net , type , lower , upper , scope ,
tipc_own_addr , port_ref , key ) ;
if ( likely ( publ ) ) {
tipc_ nametbl - > local_publ_count + + ;
buf = tipc_named_publish ( publ ) ;
tn - > nametbl - > local_publ_count + + ;
buf = tipc_named_publish ( net , publ ) ;
/* Any pending external events? */
tipc_named_process_backlog ( net ) ;
}
spin_unlock_bh ( & tipc_ nametbl_lock ) ;
spin_unlock_bh ( & tn - > nametbl_lock ) ;
if ( buf )
named_cluster_distribute ( net , buf ) ;
@ -689,11 +692,13 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref,
{
struct publication * publ ;
struct sk_buff * skb = NULL ;
struct tipc_net * tn = net_generic ( net , tipc_net_id ) ;
spin_lock_bh ( & tipc_nametbl_lock ) ;
publ = tipc_nametbl_remove_publ ( type , lower , tipc_own_addr , ref , key ) ;
spin_lock_bh ( & tn - > nametbl_lock ) ;
publ = tipc_nametbl_remove_publ ( net , type , lower , tipc_own_addr ,
ref , key ) ;
if ( likely ( publ ) ) {
tipc_ nametbl - > local_publ_count - - ;
tn - > nametbl - > local_publ_count - - ;
skb = tipc_named_withdraw ( publ ) ;
/* Any pending external events? */
tipc_named_process_backlog ( net ) ;
@ -704,7 +709,7 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref,
" (type=%u, lower=%u, ref=%u, key=%u) \n " ,
type , lower , ref , key ) ;
}
spin_unlock_bh ( & tipc_ nametbl_lock ) ;
spin_unlock_bh ( & tn - > nametbl_lock ) ;
if ( skb ) {
named_cluster_distribute ( net , skb ) ;
@ -718,15 +723,15 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref,
*/
void tipc_nametbl_subscribe ( struct tipc_subscription * s )
{
struct tipc_net * tn = net_generic ( s - > net , tipc_net_id ) ;
u32 type = s - > seq . type ;
int index = hash ( type ) ;
struct name_seq * seq ;
spin_lock_bh ( & tipc_ nametbl_lock ) ;
seq = nametbl_find_seq ( type ) ;
spin_lock_bh ( & tn - > nametbl_lock ) ;
seq = nametbl_find_seq ( s - > net , type ) ;
if ( ! seq )
seq = tipc_nameseq_create ( type ,
& tipc_nametbl - > seq_hlist [ index ] ) ;
seq = tipc_nameseq_create ( type , & tn - > nametbl - > seq_hlist [ index ] ) ;
if ( seq ) {
spin_lock_bh ( & seq - > lock ) ;
tipc_nameseq_subscribe ( seq , s ) ;
@ -735,7 +740,7 @@ void tipc_nametbl_subscribe(struct tipc_subscription *s)
pr_warn ( " Failed to create subscription for {%u,%u,%u} \n " ,
s - > seq . type , s - > seq . lower , s - > seq . upper ) ;
}
spin_unlock_bh ( & tipc_ nametbl_lock ) ;
spin_unlock_bh ( & tn - > nametbl_lock ) ;
}
/**
@ -743,10 +748,11 @@ void tipc_nametbl_subscribe(struct tipc_subscription *s)
*/
void tipc_nametbl_unsubscribe ( struct tipc_subscription * s )
{
struct tipc_net * tn = net_generic ( s - > net , tipc_net_id ) ;
struct name_seq * seq ;
spin_lock_bh ( & tipc_ nametbl_lock ) ;
seq = nametbl_find_seq ( s - > seq . type ) ;
spin_lock_bh ( & tn - > nametbl_lock ) ;
seq = nametbl_find_seq ( s - > net , s - > seq . type ) ;
if ( seq ! = NULL ) {
spin_lock_bh ( & seq - > lock ) ;
list_del_init ( & s - > nameseq_list ) ;
@ -759,7 +765,7 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s)
spin_unlock_bh ( & seq - > lock ) ;
}
}
spin_unlock_bh ( & tipc_ nametbl_lock ) ;
spin_unlock_bh ( & tn - > nametbl_lock ) ;
}
/**
@ -861,9 +867,10 @@ static int nametbl_header(char *buf, int len, u32 depth)
/**
* nametbl_list - print specified name table contents into the given buffer
*/
static int nametbl_list ( char * buf , int len , u32 depth_info ,
static int nametbl_list ( struct net * net , char * buf , int len , u32 depth_info ,
u32 type , u32 lowbound , u32 upbound )
{
struct tipc_net * tn = net_generic ( net , tipc_net_id ) ;
struct hlist_head * seq_head ;
struct name_seq * seq ;
int all_types ;
@ -883,7 +890,7 @@ static int nametbl_list(char *buf, int len, u32 depth_info,
lowbound = 0 ;
upbound = ~ 0 ;
for ( i = 0 ; i < TIPC_NAMETBL_SIZE ; i + + ) {
seq_head = & tipc_ nametbl - > seq_hlist [ i ] ;
seq_head = & tn - > nametbl - > seq_hlist [ i ] ;
hlist_for_each_entry_rcu ( seq , seq_head , ns_list ) {
ret + = nameseq_list ( seq , buf + ret , len - ret ,
depth , seq - > type ,
@ -899,7 +906,7 @@ static int nametbl_list(char *buf, int len, u32 depth_info,
}
ret + = nametbl_header ( buf + ret , len - ret , depth ) ;
i = hash ( type ) ;
seq_head = & tipc_ nametbl - > seq_hlist [ i ] ;
seq_head = & tn - > nametbl - > seq_hlist [ i ] ;
hlist_for_each_entry_rcu ( seq , seq_head , ns_list ) {
if ( seq - > type = = type ) {
ret + = nameseq_list ( seq , buf + ret , len - ret ,
@ -912,7 +919,8 @@ static int nametbl_list(char *buf, int len, u32 depth_info,
return ret ;
}
struct sk_buff * tipc_nametbl_get ( const void * req_tlv_area , int req_tlv_space )
struct sk_buff * tipc_nametbl_get ( struct net * net , const void * req_tlv_area ,
int req_tlv_space )
{
struct sk_buff * buf ;
struct tipc_name_table_query * argv ;
@ -933,7 +941,7 @@ struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
pb_len = ULTRA_STRING_MAX_LEN ;
argv = ( struct tipc_name_table_query * ) TLV_DATA ( req_tlv_area ) ;
rcu_read_lock ( ) ;
str_len = nametbl_list ( pb , pb_len , ntohl ( argv - > depth ) ,
str_len = nametbl_list ( net , pb , pb_len , ntohl ( argv - > depth ) ,
ntohl ( argv - > type ) ,
ntohl ( argv - > lowbound ) , ntohl ( argv - > upbound ) ) ;
rcu_read_unlock ( ) ;
@ -944,8 +952,10 @@ struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
return buf ;
}
int tipc_nametbl_init ( void )
int tipc_nametbl_init ( struct net * net )
{
struct tipc_net * tn = net_generic ( net , tipc_net_id ) ;
struct name_table * tipc_nametbl ;
int i ;
tipc_nametbl = kzalloc ( sizeof ( * tipc_nametbl ) , GFP_ATOMIC ) ;
@ -958,6 +968,8 @@ int tipc_nametbl_init(void)
INIT_LIST_HEAD ( & tipc_nametbl - > publ_list [ TIPC_ZONE_SCOPE ] ) ;
INIT_LIST_HEAD ( & tipc_nametbl - > publ_list [ TIPC_CLUSTER_SCOPE ] ) ;
INIT_LIST_HEAD ( & tipc_nametbl - > publ_list [ TIPC_NODE_SCOPE ] ) ;
tn - > nametbl = tipc_nametbl ;
spin_lock_init ( & tn - > nametbl_lock ) ;
return 0 ;
}
@ -966,7 +978,7 @@ int tipc_nametbl_init(void)
*
* tipc_nametbl_lock must be held when calling this function
*/
static void tipc_purge_publications ( struct name_seq * seq )
static void tipc_purge_publications ( struct net * net , struct n ame_seq * seq )
{
struct publication * publ , * safe ;
struct sub_seq * sseq ;
@ -976,8 +988,8 @@ static void tipc_purge_publications(struct name_seq *seq)
sseq = seq - > sseqs ;
info = sseq - > info ;
list_for_each_entry_safe ( publ , safe , & info - > zone_list , zone_list ) {
tipc_nametbl_remove_publ ( publ - > type , publ - > lower , publ - > node ,
publ - > ref , publ - > key ) ;
tipc_nametbl_remove_publ ( net , publ - > type , publ - > lower ,
publ - > node , publ - > ref , publ - > key ) ;
kfree_rcu ( publ , rcu ) ;
}
hlist_del_init_rcu ( & seq - > ns_list ) ;
@ -987,25 +999,27 @@ static void tipc_purge_publications(struct name_seq *seq)
kfree_rcu ( seq , rcu ) ;
}
void tipc_nametbl_stop ( void )
void tipc_nametbl_stop ( struct net * net )
{
u32 i ;
struct name_seq * seq ;
struct hlist_head * seq_head ;
struct tipc_net * tn = net_generic ( net , tipc_net_id ) ;
struct name_table * tipc_nametbl = tn - > nametbl ;
/* Verify name table is empty and purge any lingering
* publications , then release the name table
*/
spin_lock_bh ( & tipc_ nametbl_lock ) ;
spin_lock_bh ( & tn - > nametbl_lock ) ;
for ( i = 0 ; i < TIPC_NAMETBL_SIZE ; i + + ) {
if ( hlist_empty ( & tipc_nametbl - > seq_hlist [ i ] ) )
continue ;
seq_head = & tipc_nametbl - > seq_hlist [ i ] ;
hlist_for_each_entry_rcu ( seq , seq_head , ns_list ) {
tipc_purge_publications ( seq ) ;
tipc_purge_publications ( net , seq ) ;
}
}
spin_unlock_bh ( & tipc_ nametbl_lock ) ;
spin_unlock_bh ( & tn - > nametbl_lock ) ;
synchronize_net ( ) ;
kfree ( tipc_nametbl ) ;
@ -1109,9 +1123,10 @@ static int __tipc_nl_subseq_list(struct tipc_nl_msg *msg, struct name_seq *seq,
return 0 ;
}
static int __ tipc_nl_seq_list( struct tipc_nl_msg * msg , u32 * last_type ,
u32 * last_lower , u32 * last_publ )
static int tipc_nl_seq_list ( struct net * net , struct tipc_nl_msg * msg ,
u32 * last_type , u32 * last_lower , u32 * last_publ )
{
struct tipc_net * tn = net_generic ( net , tipc_net_id ) ;
struct hlist_head * seq_head ;
struct name_seq * seq = NULL ;
int err ;
@ -1123,10 +1138,10 @@ static int __tipc_nl_seq_list(struct tipc_nl_msg *msg, u32 *last_type,
i = 0 ;
for ( ; i < TIPC_NAMETBL_SIZE ; i + + ) {
seq_head = & tipc_ nametbl - > seq_hlist [ i ] ;
seq_head = & tn - > nametbl - > seq_hlist [ i ] ;
if ( * last_type ) {
seq = nametbl_find_seq ( * last_type ) ;
seq = nametbl_find_seq ( net , * last_type ) ;
if ( ! seq )
return - EPIPE ;
} else {
@ -1160,6 +1175,7 @@ int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb)
u32 last_type = cb - > args [ 0 ] ;
u32 last_lower = cb - > args [ 1 ] ;
u32 last_publ = cb - > args [ 2 ] ;
struct net * net = sock_net ( skb - > sk ) ;
struct tipc_nl_msg msg ;
if ( done )
@ -1170,7 +1186,7 @@ int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb)
msg . seq = cb - > nlh - > nlmsg_seq ;
rcu_read_lock ( ) ;
err = __ tipc_nl_seq_list( & msg , & last_type , & last_lower , & last_publ ) ;
err = tipc_nl_seq_list ( net , & msg , & last_type , & last_lower , & last_publ ) ;
if ( ! err ) {
done = 1 ;
} else if ( err ! = - EMSGSIZE ) {