node.c 15.5 KB
Newer Older
P
Per Liden 已提交
1 2
/*
 * net/tipc/node.c: TIPC node management routines
3
 *
4
 * Copyright (c) 2000-2006, 2012-2015, Ericsson AB
5
 * Copyright (c) 2005-2006, 2010-2014, Wind River Systems
P
Per Liden 已提交
6 7
 * All rights reserved.
 *
P
Per Liden 已提交
8
 * Redistribution and use in source and binary forms, with or without
P
Per Liden 已提交
9 10
 * modification, are permitted provided that the following conditions are met:
 *
P
Per Liden 已提交
11 12 13 14 15 16 17 18
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the names of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
P
Per Liden 已提交
19
 *
P
Per Liden 已提交
20 21 22 23 24 25 26 27 28 29 30 31 32 33
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
P
Per Liden 已提交
34 35 36 37
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "core.h"
38
#include "link.h"
P
Per Liden 已提交
39 40
#include "node.h"
#include "name_distr.h"
41
#include "socket.h"
42
#include "bcast.h"
P
Per Liden 已提交
43

44 45
static void node_lost_contact(struct tipc_node *n_ptr);
static void node_established_contact(struct tipc_node *n_ptr);
46
static void tipc_node_delete(struct tipc_node *node);
P
Per Liden 已提交
47

48 49 50 51 52 53 54
struct tipc_sock_conn {
	u32 port;
	u32 peer_port;
	u32 peer_node;
	struct list_head list;
};

55 56 57 58 59 60
static const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = {
	[TIPC_NLA_NODE_UNSPEC]		= { .type = NLA_UNSPEC },
	[TIPC_NLA_NODE_ADDR]		= { .type = NLA_U32 },
	[TIPC_NLA_NODE_UP]		= { .type = NLA_FLAG }
};

61 62 63 64 65 66
/*
 * A trivial power-of-two bitmask technique is used for speed, since this
 * operation is done for every incoming TIPC packet. The number of hash table
 * entries has been chosen so that no hash chain exceeds 8 nodes and will
 * usually be much smaller (typically only a single node).
 */
67
static unsigned int tipc_hashfn(u32 addr)
68 69 70 71
{
	return addr & (NODE_HTABLE_SIZE - 1);
}

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
static void tipc_node_kref_release(struct kref *kref)
{
	struct tipc_node *node = container_of(kref, struct tipc_node, kref);

	tipc_node_delete(node);
}

void tipc_node_put(struct tipc_node *node)
{
	kref_put(&node->kref, tipc_node_kref_release);
}

static void tipc_node_get(struct tipc_node *node)
{
	kref_get(&node->kref);
}

89
/*
90 91
 * tipc_node_find - locate specified node object, if it exists
 */
92
struct tipc_node *tipc_node_find(struct net *net, u32 addr)
93
{
94
	struct tipc_net *tn = net_generic(net, tipc_net_id);
95 96
	struct tipc_node *node;

97
	if (unlikely(!in_own_cluster_exact(net, addr)))
98 99
		return NULL;

100
	rcu_read_lock();
101 102
	hlist_for_each_entry_rcu(node, &tn->node_htable[tipc_hashfn(addr)],
				 hash) {
103
		if (node->addr == addr) {
104
			tipc_node_get(node);
105
			rcu_read_unlock();
106
			return node;
107
		}
108
	}
109
	rcu_read_unlock();
110 111 112
	return NULL;
}

113
struct tipc_node *tipc_node_create(struct net *net, u32 addr)
P
Per Liden 已提交
114
{
115
	struct tipc_net *tn = net_generic(net, tipc_net_id);
116
	struct tipc_node *n_ptr, *temp_node;
P
Per Liden 已提交
117

118
	spin_lock_bh(&tn->node_list_lock);
119 120 121
	n_ptr = tipc_node_find(net, addr);
	if (n_ptr)
		goto exit;
122
	n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC);
123
	if (!n_ptr) {
124
		pr_warn("Node creation failed, no memory\n");
125
		goto exit;
126 127
	}
	n_ptr->addr = addr;
128
	n_ptr->net = net;
129
	kref_init(&n_ptr->kref);
130
	spin_lock_init(&n_ptr->lock);
131 132
	INIT_HLIST_NODE(&n_ptr->hash);
	INIT_LIST_HEAD(&n_ptr->list);
133
	INIT_LIST_HEAD(&n_ptr->publ_list);
134
	INIT_LIST_HEAD(&n_ptr->conn_sks);
J
Jon Paul Maloy 已提交
135
	__skb_queue_head_init(&n_ptr->bclink.deferdq);
136 137
	hlist_add_head_rcu(&n_ptr->hash, &tn->node_htable[tipc_hashfn(addr)]);
	list_for_each_entry_rcu(temp_node, &tn->node_list, list) {
138 139 140
		if (n_ptr->addr < temp_node->addr)
			break;
	}
141
	list_add_tail_rcu(&n_ptr->list, &temp_node->list);
Y
Ying Xue 已提交
142
	n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN;
143
	n_ptr->signature = INVALID_NODE_SIG;
144
	tipc_node_get(n_ptr);
145
exit:
146
	spin_unlock_bh(&tn->node_list_lock);
P
Per Liden 已提交
147 148 149
	return n_ptr;
}

150
static void tipc_node_delete(struct tipc_node *node)
P
Per Liden 已提交
151
{
152 153 154
	list_del_rcu(&node->list);
	hlist_del_rcu(&node->hash);
	kfree_rcu(node, rcu);
P
Per Liden 已提交
155 156
}

157
void tipc_node_stop(struct net *net)
158
{
159
	struct tipc_net *tn = net_generic(net, tipc_net_id);
160 161
	struct tipc_node *node, *t_node;

162 163
	spin_lock_bh(&tn->node_list_lock);
	list_for_each_entry_safe(node, t_node, &tn->node_list, list)
164
		tipc_node_put(node);
165
	spin_unlock_bh(&tn->node_list_lock);
166 167
}

168
int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port)
169 170 171
{
	struct tipc_node *node;
	struct tipc_sock_conn *conn;
172
	int err = 0;
173

174
	if (in_own_node(net, dnode))
175 176
		return 0;

177
	node = tipc_node_find(net, dnode);
178 179 180 181 182
	if (!node) {
		pr_warn("Connecting sock to node 0x%x failed\n", dnode);
		return -EHOSTUNREACH;
	}
	conn = kmalloc(sizeof(*conn), GFP_ATOMIC);
183 184 185 186
	if (!conn) {
		err = -EHOSTUNREACH;
		goto exit;
	}
187 188 189 190 191 192 193
	conn->peer_node = dnode;
	conn->port = port;
	conn->peer_port = peer_port;

	tipc_node_lock(node);
	list_add_tail(&conn->list, &node->conn_sks);
	tipc_node_unlock(node);
194 195 196
exit:
	tipc_node_put(node);
	return err;
197 198
}

199
void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port)
200 201 202 203
{
	struct tipc_node *node;
	struct tipc_sock_conn *conn, *safe;

204
	if (in_own_node(net, dnode))
205 206
		return;

207
	node = tipc_node_find(net, dnode);
208 209 210 211 212 213 214 215 216 217 218
	if (!node)
		return;

	tipc_node_lock(node);
	list_for_each_entry_safe(conn, safe, &node->conn_sks, list) {
		if (port != conn->port)
			continue;
		list_del(&conn->list);
		kfree(conn);
	}
	tipc_node_unlock(node);
219
	tipc_node_put(node);
220 221
}

P
Per Liden 已提交
222
/**
223
 * tipc_node_link_up - handle addition of link
224
 *
P
Per Liden 已提交
225 226
 * Link becomes active (alone or shared) or standby, depending on its priority.
 */
227
void tipc_node_link_up(struct tipc_node *n, int bearer_id)
P
Per Liden 已提交
228
{
229 230 231
	struct tipc_link_entry **actv = &n->active_links[0];
	struct tipc_link_entry *le = &n->links[bearer_id];
	struct tipc_link *l = le->link;
P
Per Liden 已提交
232

233 234 235 236 237 238
	/* Leave room for tunnel header when returning 'mtu' to users: */
	n->links[bearer_id].mtu = l->mtu - INT_H_SIZE;

	n->working_links++;
	n->action_flags |= TIPC_NOTIFY_LINK_UP;
	n->link_id = l->peer_bearer_id << 16 | l->bearer_id;
Y
Ying Xue 已提交
239

240
	pr_debug("Established link <%s> on network plane %c\n",
241
		 l->name, l->net_plane);
242

243 244 245 246 247 248
	/* No active links ? => take both active slots */
	if (!actv[0]) {
		actv[0] = le;
		actv[1] = le;
		node_established_contact(n);
		return;
P
Per Liden 已提交
249
	}
250 251 252
	if (l->priority < actv[0]->link->priority) {
		pr_debug("New link <%s> becomes standby\n", l->name);
		return;
P
Per Liden 已提交
253
	}
254 255 256 257 258 259
	tipc_link_dup_queue_xmit(actv[0]->link, l);

	/* Take one active slot if applicable */
	if (l->priority == actv[0]->link->priority) {
		actv[0] = le;
		return;
P
Per Liden 已提交
260
	}
261 262 263 264 265 266
	/* Higher prio than current active? => take both active slots */
	pr_debug("Old l <%s> becomes standby\n", actv[0]->link->name);
	if (actv[1] != actv[0])
		pr_debug("Old link <%s> now standby\n", actv[1]->link->name);
	actv[0] = le;
	actv[1] = le;
P
Per Liden 已提交
267 268 269
}

/**
270
 * node_select_active_links - select which working links should be active
P
Per Liden 已提交
271
 */
272
static void node_select_active_links(struct tipc_node *n)
P
Per Liden 已提交
273
{
274 275 276
	struct tipc_link_entry **actv = &n->active_links[0];
	struct tipc_link *l;
	u32 b, highest = 0;
P
Per Liden 已提交
277

278 279
	actv[0] = NULL;
	actv[1] = NULL;
P
Per Liden 已提交
280

281 282 283 284 285 286 287 288
	for (b = 0; b < MAX_BEARERS; b++) {
		l = n->links[b].link;
		if (!l || !tipc_link_is_up(l) || (l->priority < highest))
			continue;
		if (l->priority > highest) {
			highest = l->priority;
			actv[0] = &n->links[b];
			actv[1] = &n->links[b];
P
Per Liden 已提交
289 290
			continue;
		}
291
		actv[1] = &n->links[b];
P
Per Liden 已提交
292 293 294 295
	}
}

/**
296
 * tipc_node_link_down - handle loss of link
P
Per Liden 已提交
297
 */
298
void tipc_node_link_down(struct tipc_node *n, int bearer_id)
P
Per Liden 已提交
299
{
300 301 302
	struct tipc_link_entry **actv = &n->active_links[0];
	struct tipc_link_entry *le = &n->links[bearer_id];
	struct tipc_link *l = le->link;
P
Per Liden 已提交
303

304 305 306
	n->working_links--;
	n->action_flags |= TIPC_NOTIFY_LINK_DOWN;
	n->link_id = l->peer_bearer_id << 16 | l->bearer_id;
307

308
	if (!tipc_link_is_active(l)) {
309
		pr_debug("Lost standby link <%s> on network plane %c\n",
310
			 l->name, l->net_plane);
P
Per Liden 已提交
311 312
		return;
	}
313
	pr_debug("Lost link <%s> on network plane %c\n",
314
		 l->name, l->net_plane);
315

316 317 318 319 320
	/* Resdistribute active slots if applicable */
	if (actv[0] == le)
		actv[0] = actv[1];
	if (actv[1] == le)
		actv[1] = actv[0];
P
Per Liden 已提交
321

322 323 324 325 326 327 328 329
	/* Last link of this priority? => select other ones if available */
	if (actv[0] == le)
		node_select_active_links(n);

	if (tipc_node_is_up(n))
		tipc_link_failover_send_queue(l);
	else
		node_lost_contact(n);
P
Per Liden 已提交
330 331
}

332
bool tipc_node_is_up(struct tipc_node *n)
P
Per Liden 已提交
333
{
334
	return n->active_links[0];
P
Per Liden 已提交
335 336
}

337
void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
P
Per Liden 已提交
338
{
339
	n_ptr->links[l_ptr->bearer_id].link = l_ptr;
340
	n_ptr->link_cnt++;
P
Per Liden 已提交
341 342
}

343
void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
P
Per Liden 已提交
344
{
345 346 347
	int i;

	for (i = 0; i < MAX_BEARERS; i++) {
348
		if (l_ptr != n_ptr->links[i].link)
J
Jon Paul Maloy 已提交
349
			continue;
350
		n_ptr->links[i].link = NULL;
J
Jon Paul Maloy 已提交
351
		n_ptr->link_cnt--;
352
	}
P
Per Liden 已提交
353 354
}

355
static void node_established_contact(struct tipc_node *n_ptr)
P
Per Liden 已提交
356
{
Y
Ying Xue 已提交
357
	n_ptr->action_flags |= TIPC_NOTIFY_NODE_UP;
358
	n_ptr->bclink.oos_state = 0;
359 360
	n_ptr->bclink.acked = tipc_bclink_get_last_sent(n_ptr->net);
	tipc_bclink_add_node(n_ptr->net, n_ptr->addr);
P
Per Liden 已提交
361 362
}

363
static void node_lost_contact(struct tipc_node *n_ptr)
P
Per Liden 已提交
364 365
{
	char addr_string[16];
366 367 368 369 370
	struct tipc_sock_conn *conn, *safe;
	struct list_head *conns = &n_ptr->conn_sks;
	struct sk_buff *skb;
	struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id);
	uint i;
P
Per Liden 已提交
371

372 373
	pr_debug("Lost contact with %s\n",
		 tipc_addr_string_fill(addr_string, n_ptr->addr));
374 375

	/* Flush broadcast link info associated with lost node */
376
	if (n_ptr->bclink.recv_permitted) {
J
Jon Paul Maloy 已提交
377
		__skb_queue_purge(&n_ptr->bclink.deferdq);
378

379 380 381
		if (n_ptr->bclink.reasm_buf) {
			kfree_skb(n_ptr->bclink.reasm_buf);
			n_ptr->bclink.reasm_buf = NULL;
382 383
		}

384
		tipc_bclink_remove_node(n_ptr->net, n_ptr->addr);
385
		tipc_bclink_acknowledge(n_ptr, INVALID_LINK_SEQ);
P
Per Liden 已提交
386

387
		n_ptr->bclink.recv_permitted = false;
388
	}
P
Per Liden 已提交
389

390
	/* Abort any ongoing link failover */
P
Per Liden 已提交
391
	for (i = 0; i < MAX_BEARERS; i++) {
392
		struct tipc_link *l_ptr = n_ptr->links[i].link;
393
		if (!l_ptr)
P
Per Liden 已提交
394
			continue;
395 396 397 398 399
		l_ptr->flags &= ~LINK_FAILINGOVER;
		l_ptr->failover_checkpt = 0;
		l_ptr->failover_pkts = 0;
		kfree_skb(l_ptr->failover_skb);
		l_ptr->failover_skb = NULL;
400
		tipc_link_reset_fragments(l_ptr);
P
Per Liden 已提交
401 402
	}

403 404
	n_ptr->action_flags &= ~TIPC_WAIT_OWN_LINKS_DOWN;

405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
	/* Prevent re-contact with node until cleanup is done */
	n_ptr->action_flags |= TIPC_WAIT_PEER_LINKS_DOWN;

	/* Notify publications from this node */
	n_ptr->action_flags |= TIPC_NOTIFY_NODE_DOWN;

	/* Notify sockets connected to node */
	list_for_each_entry_safe(conn, safe, conns, list) {
		skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE, TIPC_CONN_MSG,
				      SHORT_H_SIZE, 0, tn->own_addr,
				      conn->peer_node, conn->port,
				      conn->peer_port, TIPC_ERR_NO_NODE);
		if (likely(skb)) {
			skb_queue_tail(n_ptr->inputq, skb);
			n_ptr->action_flags |= TIPC_MSG_EVT;
		}
		list_del(&conn->list);
		kfree(conn);
	}
P
Per Liden 已提交
424 425
}

E
Erik Hugne 已提交
426 427 428 429 430 431 432 433 434
/**
 * tipc_node_get_linkname - get the name of a link
 *
 * @bearer_id: id of the bearer
 * @node: peer node address
 * @linkname: link name output buffer
 *
 * Returns 0 on success
 */
435 436
int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 addr,
			   char *linkname, size_t len)
E
Erik Hugne 已提交
437 438
{
	struct tipc_link *link;
439
	int err = -EINVAL;
440
	struct tipc_node *node = tipc_node_find(net, addr);
E
Erik Hugne 已提交
441

442 443 444 445 446 447
	if (!node)
		return err;

	if (bearer_id >= MAX_BEARERS)
		goto exit;

E
Erik Hugne 已提交
448
	tipc_node_lock(node);
449
	link = node->links[bearer_id].link;
E
Erik Hugne 已提交
450 451
	if (link) {
		strncpy(linkname, link->name, len);
452
		err = 0;
E
Erik Hugne 已提交
453
	}
454
exit:
E
Erik Hugne 已提交
455
	tipc_node_unlock(node);
456 457
	tipc_node_put(node);
	return err;
E
Erik Hugne 已提交
458
}
459 460 461

void tipc_node_unlock(struct tipc_node *node)
{
462
	struct net *net = node->net;
463
	u32 addr = 0;
464
	u32 flags = node->action_flags;
Y
Ying Xue 已提交
465
	u32 link_id = 0;
466
	struct list_head *publ_list;
467
	struct sk_buff_head *inputq = node->inputq;
468
	struct sk_buff_head *namedq;
469

470 471
	if (likely(!flags || (flags == TIPC_MSG_EVT))) {
		node->action_flags = 0;
472
		spin_unlock_bh(&node->lock);
473 474
		if (flags == TIPC_MSG_EVT)
			tipc_sk_rcv(net, inputq);
475 476 477
		return;
	}

Y
Ying Xue 已提交
478 479
	addr = node->addr;
	link_id = node->link_id;
480
	namedq = node->namedq;
481
	publ_list = &node->publ_list;
Y
Ying Xue 已提交
482

483 484 485 486
	node->action_flags &= ~(TIPC_MSG_EVT |
				TIPC_NOTIFY_NODE_DOWN | TIPC_NOTIFY_NODE_UP |
				TIPC_NOTIFY_LINK_DOWN | TIPC_NOTIFY_LINK_UP |
				TIPC_WAKEUP_BCAST_USERS | TIPC_BCAST_MSG_EVT |
487
				TIPC_NAMED_MSG_EVT | TIPC_BCAST_RESET);
Y
Ying Xue 已提交
488

489 490
	spin_unlock_bh(&node->lock);

491 492
	if (flags & TIPC_NOTIFY_NODE_DOWN)
		tipc_publ_notify(net, publ_list, addr);
493

494
	if (flags & TIPC_WAKEUP_BCAST_USERS)
495
		tipc_bclink_wakeup_users(net);
496

Y
Ying Xue 已提交
497
	if (flags & TIPC_NOTIFY_NODE_UP)
498
		tipc_named_node_up(net, addr);
Y
Ying Xue 已提交
499 500

	if (flags & TIPC_NOTIFY_LINK_UP)
501
		tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr,
Y
Ying Xue 已提交
502 503 504
				     TIPC_NODE_SCOPE, link_id, addr);

	if (flags & TIPC_NOTIFY_LINK_DOWN)
505
		tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr,
Y
Ying Xue 已提交
506
				      link_id, addr);
507 508 509 510 511 512

	if (flags & TIPC_MSG_EVT)
		tipc_sk_rcv(net, inputq);

	if (flags & TIPC_NAMED_MSG_EVT)
		tipc_named_rcv(net, namedq);
513 514 515

	if (flags & TIPC_BCAST_MSG_EVT)
		tipc_bclink_input(net);
516 517 518

	if (flags & TIPC_BCAST_RESET)
		tipc_link_reset_all(node);
519
}
520 521

/* Caller should hold node lock for the passed node */
522
static int __tipc_nl_add_node(struct tipc_nl_msg *msg, struct tipc_node *node)
523 524 525 526
{
	void *hdr;
	struct nlattr *attrs;

527
	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
			  NLM_F_MULTI, TIPC_NL_NODE_GET);
	if (!hdr)
		return -EMSGSIZE;

	attrs = nla_nest_start(msg->skb, TIPC_NLA_NODE);
	if (!attrs)
		goto msg_full;

	if (nla_put_u32(msg->skb, TIPC_NLA_NODE_ADDR, node->addr))
		goto attr_msg_full;
	if (tipc_node_is_up(node))
		if (nla_put_flag(msg->skb, TIPC_NLA_NODE_UP))
			goto attr_msg_full;

	nla_nest_end(msg->skb, attrs);
	genlmsg_end(msg->skb, hdr);

	return 0;

attr_msg_full:
	nla_nest_cancel(msg->skb, attrs);
msg_full:
	genlmsg_cancel(msg->skb, hdr);

	return -EMSGSIZE;
}

int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
	int err;
558 559
	struct net *net = sock_net(skb->sk);
	struct tipc_net *tn = net_generic(net, tipc_net_id);
560 561 562 563 564 565 566 567 568 569 570 571 572
	int done = cb->args[0];
	int last_addr = cb->args[1];
	struct tipc_node *node;
	struct tipc_nl_msg msg;

	if (done)
		return 0;

	msg.skb = skb;
	msg.portid = NETLINK_CB(cb->skb).portid;
	msg.seq = cb->nlh->nlmsg_seq;

	rcu_read_lock();
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
	if (last_addr) {
		node = tipc_node_find(net, last_addr);
		if (!node) {
			rcu_read_unlock();
			/* We never set seq or call nl_dump_check_consistent()
			 * this means that setting prev_seq here will cause the
			 * consistence check to fail in the netlink callback
			 * handler. Resulting in the NLMSG_DONE message having
			 * the NLM_F_DUMP_INTR flag set if the node state
			 * changed while we released the lock.
			 */
			cb->prev_seq = 1;
			return -EPIPE;
		}
		tipc_node_put(node);
588 589
	}

590
	list_for_each_entry_rcu(node, &tn->node_list, list) {
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
		if (last_addr) {
			if (node->addr == last_addr)
				last_addr = 0;
			else
				continue;
		}

		tipc_node_lock(node);
		err = __tipc_nl_add_node(&msg, node);
		if (err) {
			last_addr = node->addr;
			tipc_node_unlock(node);
			goto out;
		}

		tipc_node_unlock(node);
	}
	done = 1;
out:
	cb->args[0] = done;
	cb->args[1] = last_addr;
	rcu_read_unlock();

	return skb->len;
}