Commit d6e164e3 authored by Richard Alpe's avatar Richard Alpe Committed by David S. Miller

tipc: fix socket list regression in new nl api

Commit 07f6c4bc (tipc: convert tipc reference table to use generic
rhashtable) introduced a problem with port listing in the new netlink
API. It broke the resume functionality resulting in a never ending
loop. This was caused by starting with the first hash table every time
subsequently never returning an empty skb (terminating).

This patch fixes the resume mechanism by keeping a logical reference
to the last hash table along with a logical reference to the socket
(port) that didn't fit in the previous message.
Signed-off-by: default avatarRichard Alpe <richard.alpe@ericsson.com>
Reviewed-by: default avatarErik Hugne <erik.hugne@ericsson.com>
Reviewed-by: default avatarYing Xue <ying.xue@windriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e445dd5f
...@@ -2749,29 +2749,35 @@ int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -2749,29 +2749,35 @@ int tipc_nl_sk_dump(struct sk_buff *skb, struct netlink_callback *cb)
struct tipc_sock *tsk; struct tipc_sock *tsk;
const struct bucket_table *tbl; const struct bucket_table *tbl;
struct rhash_head *pos; struct rhash_head *pos;
u32 prev_portid = cb->args[0];
u32 portid = prev_portid;
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_net *tn = net_generic(net, tipc_net_id);
int i; u32 tbl_id = cb->args[0];
u32 prev_portid = cb->args[1];
rcu_read_lock(); rcu_read_lock();
tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht); tbl = rht_dereference_rcu((&tn->sk_rht)->tbl, &tn->sk_rht);
for (i = 0; i < tbl->size; i++) { for (; tbl_id < tbl->size; tbl_id++) {
rht_for_each_entry_rcu(tsk, pos, tbl, i, node) { rht_for_each_entry_rcu(tsk, pos, tbl, tbl_id, node) {
spin_lock_bh(&tsk->sk.sk_lock.slock); spin_lock_bh(&tsk->sk.sk_lock.slock);
portid = tsk->portid; if (prev_portid && prev_portid != tsk->portid) {
spin_unlock_bh(&tsk->sk.sk_lock.slock);
continue;
}
err = __tipc_nl_add_sk(skb, cb, tsk); err = __tipc_nl_add_sk(skb, cb, tsk);
if (err) {
prev_portid = tsk->portid;
spin_unlock_bh(&tsk->sk.sk_lock.slock);
goto out;
}
prev_portid = 0;
spin_unlock_bh(&tsk->sk.sk_lock.slock); spin_unlock_bh(&tsk->sk.sk_lock.slock);
if (err)
break;
prev_portid = portid;
} }
} }
out:
rcu_read_unlock(); rcu_read_unlock();
cb->args[0] = tbl_id;
cb->args[0] = prev_portid; cb->args[1] = prev_portid;
return skb->len; return skb->len;
} }
......
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