diff options
Diffstat (limited to 'net/tipc/name_table.c')
| -rw-r--r-- | net/tipc/name_table.c | 55 | 
1 files changed, 45 insertions, 10 deletions
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 09dcd54b04e..9d7d37d9518 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -148,8 +148,7 @@ static struct publication *publ_create(u32 type, u32 lower, u32 upper,   */  static struct sub_seq *tipc_subseq_alloc(u32 cnt)  { -	struct sub_seq *sseq = kcalloc(cnt, sizeof(struct sub_seq), GFP_ATOMIC); -	return sseq; +	return kcalloc(cnt, sizeof(struct sub_seq), GFP_ATOMIC);  }  /** @@ -665,6 +664,7 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,  					 u32 scope, u32 port_ref, u32 key)  {  	struct publication *publ; +	struct sk_buff *buf = NULL;  	if (table.local_publ_count >= TIPC_MAX_PUBLICATIONS) {  		pr_warn("Publication failed, local publication limit reached (%u)\n", @@ -677,9 +677,12 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,  				   tipc_own_addr, port_ref, key);  	if (likely(publ)) {  		table.local_publ_count++; -		tipc_named_publish(publ); +		buf = tipc_named_publish(publ);  	}  	write_unlock_bh(&tipc_nametbl_lock); + +	if (buf) +		named_cluster_distribute(buf);  	return publ;  } @@ -689,15 +692,19 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,  int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key)  {  	struct publication *publ; +	struct sk_buff *buf;  	write_lock_bh(&tipc_nametbl_lock);  	publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key);  	if (likely(publ)) {  		table.local_publ_count--; -		tipc_named_withdraw(publ); +		buf = tipc_named_withdraw(publ);  		write_unlock_bh(&tipc_nametbl_lock);  		list_del_init(&publ->pport_list);  		kfree(publ); + +		if (buf) +			named_cluster_distribute(buf);  		return 1;  	}  	write_unlock_bh(&tipc_nametbl_lock); @@ -942,20 +949,48 @@ int tipc_nametbl_init(void)  	return 0;  } -void tipc_nametbl_stop(void) +/** + * tipc_purge_publications - remove all publications for a given type + * + * tipc_nametbl_lock must be held when calling this function + */ +static void tipc_purge_publications(struct name_seq *seq)  { -	u32 i; +	struct publication *publ, *safe; +	struct sub_seq *sseq; +	struct name_info *info; -	if (!table.types) +	if (!seq->sseqs) { +		nameseq_delete_empty(seq);  		return; +	} +	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); +		kfree(publ); +	} +} + +void tipc_nametbl_stop(void) +{ +	u32 i; +	struct name_seq *seq; +	struct hlist_head *seq_head; +	struct hlist_node *safe; -	/* Verify name table is empty, then release it */ +	/* Verify name table is empty and purge any lingering +	 * publications, then release the name table +	 */  	write_lock_bh(&tipc_nametbl_lock);  	for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {  		if (hlist_empty(&table.types[i]))  			continue; -		pr_err("nametbl_stop(): orphaned hash chain detected\n"); -		break; +		seq_head = &table.types[i]; +		hlist_for_each_entry_safe(seq, safe, seq_head, ns_list) { +			tipc_purge_publications(seq); +		}  	}  	kfree(table.types);  	table.types = NULL;  | 
