|
@@ -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 name_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) {
|