Commit 10c3c022 authored by David S. Miller's avatar David S. Miller

Merge branch 'tipc-fixes'

Jon Maloy says:

====================
tipc: name distributor pernet queue

Commit #1 fixes a potential issue with deferred binding table
updates being pushed to the wrong namespace.

Commit #2 solves a problem with deferred binding table updates
remaining in the the defer queue after the issuing node has gone
down.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ebf4dc2b ddb1d339
...@@ -69,6 +69,7 @@ static int __net_init tipc_init_net(struct net *net) ...@@ -69,6 +69,7 @@ static int __net_init tipc_init_net(struct net *net)
if (err) if (err)
goto out_nametbl; goto out_nametbl;
INIT_LIST_HEAD(&tn->dist_queue);
err = tipc_topsrv_start(net); err = tipc_topsrv_start(net);
if (err) if (err)
goto out_subscr; goto out_subscr;
......
...@@ -103,6 +103,9 @@ struct tipc_net { ...@@ -103,6 +103,9 @@ struct tipc_net {
spinlock_t nametbl_lock; spinlock_t nametbl_lock;
struct name_table *nametbl; struct name_table *nametbl;
/* Name dist queue */
struct list_head dist_queue;
/* Topology subscription server */ /* Topology subscription server */
struct tipc_server *topsrv; struct tipc_server *topsrv;
atomic_t subscription_count; atomic_t subscription_count;
......
...@@ -40,11 +40,6 @@ ...@@ -40,11 +40,6 @@
int sysctl_tipc_named_timeout __read_mostly = 2000; int sysctl_tipc_named_timeout __read_mostly = 2000;
/**
* struct tipc_dist_queue - queue holding deferred name table updates
*/
static struct list_head tipc_dist_queue = LIST_HEAD_INIT(tipc_dist_queue);
struct distr_queue_item { struct distr_queue_item {
struct distr_item i; struct distr_item i;
u32 dtype; u32 dtype;
...@@ -229,12 +224,31 @@ static void tipc_publ_purge(struct net *net, struct publication *publ, u32 addr) ...@@ -229,12 +224,31 @@ static void tipc_publ_purge(struct net *net, struct publication *publ, u32 addr)
kfree_rcu(p, rcu); kfree_rcu(p, rcu);
} }
/**
* tipc_dist_queue_purge - remove deferred updates from a node that went down
*/
static void tipc_dist_queue_purge(struct net *net, u32 addr)
{
struct tipc_net *tn = net_generic(net, tipc_net_id);
struct distr_queue_item *e, *tmp;
spin_lock_bh(&tn->nametbl_lock);
list_for_each_entry_safe(e, tmp, &tn->dist_queue, next) {
if (e->node != addr)
continue;
list_del(&e->next);
kfree(e);
}
spin_unlock_bh(&tn->nametbl_lock);
}
void tipc_publ_notify(struct net *net, struct list_head *nsub_list, u32 addr) void tipc_publ_notify(struct net *net, struct list_head *nsub_list, u32 addr)
{ {
struct publication *publ, *tmp; struct publication *publ, *tmp;
list_for_each_entry_safe(publ, tmp, nsub_list, nodesub_list) list_for_each_entry_safe(publ, tmp, nsub_list, nodesub_list)
tipc_publ_purge(net, publ, addr); tipc_publ_purge(net, publ, addr);
tipc_dist_queue_purge(net, addr);
} }
/** /**
...@@ -279,9 +293,11 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i, ...@@ -279,9 +293,11 @@ static bool tipc_update_nametbl(struct net *net, struct distr_item *i,
* tipc_named_add_backlog - add a failed name table update to the backlog * tipc_named_add_backlog - add a failed name table update to the backlog
* *
*/ */
static void tipc_named_add_backlog(struct distr_item *i, u32 type, u32 node) static void tipc_named_add_backlog(struct net *net, struct distr_item *i,
u32 type, u32 node)
{ {
struct distr_queue_item *e; struct distr_queue_item *e;
struct tipc_net *tn = net_generic(net, tipc_net_id);
unsigned long now = get_jiffies_64(); unsigned long now = get_jiffies_64();
e = kzalloc(sizeof(*e), GFP_ATOMIC); e = kzalloc(sizeof(*e), GFP_ATOMIC);
...@@ -291,7 +307,7 @@ static void tipc_named_add_backlog(struct distr_item *i, u32 type, u32 node) ...@@ -291,7 +307,7 @@ static void tipc_named_add_backlog(struct distr_item *i, u32 type, u32 node)
e->node = node; e->node = node;
e->expires = now + msecs_to_jiffies(sysctl_tipc_named_timeout); e->expires = now + msecs_to_jiffies(sysctl_tipc_named_timeout);
memcpy(e, i, sizeof(*i)); memcpy(e, i, sizeof(*i));
list_add_tail(&e->next, &tipc_dist_queue); list_add_tail(&e->next, &tn->dist_queue);
} }
/** /**
...@@ -301,10 +317,11 @@ static void tipc_named_add_backlog(struct distr_item *i, u32 type, u32 node) ...@@ -301,10 +317,11 @@ static void tipc_named_add_backlog(struct distr_item *i, u32 type, u32 node)
void tipc_named_process_backlog(struct net *net) void tipc_named_process_backlog(struct net *net)
{ {
struct distr_queue_item *e, *tmp; struct distr_queue_item *e, *tmp;
struct tipc_net *tn = net_generic(net, tipc_net_id);
char addr[16]; char addr[16];
unsigned long now = get_jiffies_64(); unsigned long now = get_jiffies_64();
list_for_each_entry_safe(e, tmp, &tipc_dist_queue, next) { list_for_each_entry_safe(e, tmp, &tn->dist_queue, next) {
if (time_after(e->expires, now)) { if (time_after(e->expires, now)) {
if (!tipc_update_nametbl(net, &e->i, e->node, e->dtype)) if (!tipc_update_nametbl(net, &e->i, e->node, e->dtype))
continue; continue;
...@@ -344,7 +361,7 @@ void tipc_named_rcv(struct net *net, struct sk_buff_head *inputq) ...@@ -344,7 +361,7 @@ void tipc_named_rcv(struct net *net, struct sk_buff_head *inputq)
node = msg_orignode(msg); node = msg_orignode(msg);
while (count--) { while (count--) {
if (!tipc_update_nametbl(net, item, node, mtype)) if (!tipc_update_nametbl(net, item, node, mtype))
tipc_named_add_backlog(item, mtype, node); tipc_named_add_backlog(net, item, mtype, node);
item++; item++;
} }
kfree_skb(skb); kfree_skb(skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment