node.c 15.2 KB
Newer Older
P
Per Liden 已提交
1 2
/*
 * net/tipc/node.c: TIPC node management routines
3
 *
4
 * Copyright (c) 2000-2006, 2012-2014, 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"
P
Per Liden 已提交
42

43 44
static void node_lost_contact(struct tipc_node *n_ptr);
static void node_established_contact(struct tipc_node *n_ptr);
P
Per Liden 已提交
45

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

53 54 55 56 57 58
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 }
};

59 60 61 62 63 64
/*
 * 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).
 */
65
static unsigned int tipc_hashfn(u32 addr)
66 67 68 69
{
	return addr & (NODE_HTABLE_SIZE - 1);
}

70
/*
71 72
 * tipc_node_find - locate specified node object, if it exists
 */
73
struct tipc_node *tipc_node_find(struct net *net, u32 addr)
74
{
75
	struct tipc_net *tn = net_generic(net, tipc_net_id);
76 77
	struct tipc_node *node;

78
	if (unlikely(!in_own_cluster_exact(net, addr)))
79 80
		return NULL;

81
	rcu_read_lock();
82 83
	hlist_for_each_entry_rcu(node, &tn->node_htable[tipc_hashfn(addr)],
				 hash) {
84
		if (node->addr == addr) {
85
			rcu_read_unlock();
86
			return node;
87
		}
88
	}
89
	rcu_read_unlock();
90 91 92
	return NULL;
}

93
struct tipc_node *tipc_node_create(struct net *net, u32 addr)
P
Per Liden 已提交
94
{
95
	struct tipc_net *tn = net_generic(net, tipc_net_id);
96
	struct tipc_node *n_ptr, *temp_node;
P
Per Liden 已提交
97

98
	spin_lock_bh(&tn->node_list_lock);
99 100 101
	n_ptr = tipc_node_find(net, addr);
	if (n_ptr)
		goto exit;
102
	n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC);
103
	if (!n_ptr) {
104
		pr_warn("Node creation failed, no memory\n");
105
		goto exit;
106 107
	}
	n_ptr->addr = addr;
108
	n_ptr->net = net;
109
	spin_lock_init(&n_ptr->lock);
110 111
	INIT_HLIST_NODE(&n_ptr->hash);
	INIT_LIST_HEAD(&n_ptr->list);
112
	INIT_LIST_HEAD(&n_ptr->publ_list);
113
	INIT_LIST_HEAD(&n_ptr->conn_sks);
J
Jon Paul Maloy 已提交
114
	__skb_queue_head_init(&n_ptr->bclink.deferdq);
115 116
	hlist_add_head_rcu(&n_ptr->hash, &tn->node_htable[tipc_hashfn(addr)]);
	list_for_each_entry_rcu(temp_node, &tn->node_list, list) {
117 118 119
		if (n_ptr->addr < temp_node->addr)
			break;
	}
120
	list_add_tail_rcu(&n_ptr->list, &temp_node->list);
Y
Ying Xue 已提交
121
	n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN;
122
	n_ptr->signature = INVALID_NODE_SIG;
123
exit:
124
	spin_unlock_bh(&tn->node_list_lock);
P
Per Liden 已提交
125 126 127
	return n_ptr;
}

128
static void tipc_node_delete(struct tipc_net *tn, struct tipc_node *n_ptr)
P
Per Liden 已提交
129
{
130 131 132
	list_del_rcu(&n_ptr->list);
	hlist_del_rcu(&n_ptr->hash);
	kfree_rcu(n_ptr, rcu);
P
Per Liden 已提交
133 134
}

135
void tipc_node_stop(struct net *net)
136
{
137
	struct tipc_net *tn = net_generic(net, tipc_net_id);
138 139
	struct tipc_node *node, *t_node;

140 141 142 143
	spin_lock_bh(&tn->node_list_lock);
	list_for_each_entry_safe(node, t_node, &tn->node_list, list)
		tipc_node_delete(tn, node);
	spin_unlock_bh(&tn->node_list_lock);
144 145
}

146
int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port)
147 148 149 150
{
	struct tipc_node *node;
	struct tipc_sock_conn *conn;

151
	if (in_own_node(net, dnode))
152 153
		return 0;

154
	node = tipc_node_find(net, dnode);
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
	if (!node) {
		pr_warn("Connecting sock to node 0x%x failed\n", dnode);
		return -EHOSTUNREACH;
	}
	conn = kmalloc(sizeof(*conn), GFP_ATOMIC);
	if (!conn)
		return -EHOSTUNREACH;
	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);
	return 0;
}

172
void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port)
173 174 175 176
{
	struct tipc_node *node;
	struct tipc_sock_conn *conn, *safe;

177
	if (in_own_node(net, dnode))
178 179
		return;

180
	node = tipc_node_find(net, dnode);
181 182 183 184 185 186 187 188 189 190 191 192 193
	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);
}

P
Per Liden 已提交
194
/**
195
 * tipc_node_link_up - handle addition of link
196
 *
P
Per Liden 已提交
197 198
 * Link becomes active (alone or shared) or standby, depending on its priority.
 */
199
void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
P
Per Liden 已提交
200
{
201
	struct tipc_link **active = &n_ptr->active_links[0];
P
Per Liden 已提交
202

203
	n_ptr->working_links++;
Y
Ying Xue 已提交
204 205 206
	n_ptr->action_flags |= TIPC_NOTIFY_LINK_UP;
	n_ptr->link_id = l_ptr->peer_bearer_id << 16 | l_ptr->bearer_id;

207 208
	pr_debug("Established link <%s> on network plane %c\n",
		 l_ptr->name, l_ptr->net_plane);
209

P
Per Liden 已提交
210 211 212
	if (!active[0]) {
		active[0] = active[1] = l_ptr;
		node_established_contact(n_ptr);
213
		goto exit;
P
Per Liden 已提交
214
	}
215
	if (l_ptr->priority < active[0]->priority) {
216
		pr_debug("New link <%s> becomes standby\n", l_ptr->name);
217
		goto exit;
P
Per Liden 已提交
218
	}
219
	tipc_link_dup_queue_xmit(active[0], l_ptr);
220
	if (l_ptr->priority == active[0]->priority) {
P
Per Liden 已提交
221
		active[0] = l_ptr;
222
		goto exit;
P
Per Liden 已提交
223
	}
224
	pr_debug("Old link <%s> becomes standby\n", active[0]->name);
225
	if (active[1] != active[0])
226
		pr_debug("Old link <%s> becomes standby\n", active[1]->name);
P
Per Liden 已提交
227
	active[0] = active[1] = l_ptr;
228 229 230 231
exit:
	/* Leave room for changeover header when returning 'mtu' to users: */
	n_ptr->act_mtus[0] = active[0]->max_pkt - INT_H_SIZE;
	n_ptr->act_mtus[1] = active[1]->max_pkt - INT_H_SIZE;
P
Per Liden 已提交
232 233 234 235 236
}

/**
 * node_select_active_links - select active link
 */
237
static void node_select_active_links(struct tipc_node *n_ptr)
P
Per Liden 已提交
238
{
239
	struct tipc_link **active = &n_ptr->active_links[0];
P
Per Liden 已提交
240 241 242
	u32 i;
	u32 highest_prio = 0;

243
	active[0] = active[1] = NULL;
P
Per Liden 已提交
244 245

	for (i = 0; i < MAX_BEARERS; i++) {
246
		struct tipc_link *l_ptr = n_ptr->links[i];
P
Per Liden 已提交
247

248
		if (!l_ptr || !tipc_link_is_up(l_ptr) ||
P
Per Liden 已提交
249 250 251 252
		    (l_ptr->priority < highest_prio))
			continue;

		if (l_ptr->priority > highest_prio) {
253
			highest_prio = l_ptr->priority;
P
Per Liden 已提交
254 255 256 257 258 259 260 261
			active[0] = active[1] = l_ptr;
		} else {
			active[1] = l_ptr;
		}
	}
}

/**
262
 * tipc_node_link_down - handle loss of link
P
Per Liden 已提交
263
 */
264
void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
P
Per Liden 已提交
265
{
266
	struct tipc_net *tn = net_generic(n_ptr->net, tipc_net_id);
267
	struct tipc_link **active;
P
Per Liden 已提交
268

269
	n_ptr->working_links--;
Y
Ying Xue 已提交
270 271
	n_ptr->action_flags |= TIPC_NOTIFY_LINK_DOWN;
	n_ptr->link_id = l_ptr->peer_bearer_id << 16 | l_ptr->bearer_id;
272

273
	if (!tipc_link_is_active(l_ptr)) {
274 275
		pr_debug("Lost standby link <%s> on network plane %c\n",
			 l_ptr->name, l_ptr->net_plane);
P
Per Liden 已提交
276 277
		return;
	}
278 279
	pr_debug("Lost link <%s> on network plane %c\n",
		 l_ptr->name, l_ptr->net_plane);
P
Per Liden 已提交
280 281 282 283 284 285 286 287

	active = &n_ptr->active_links[0];
	if (active[0] == l_ptr)
		active[0] = active[1];
	if (active[1] == l_ptr)
		active[1] = active[0];
	if (active[0] == l_ptr)
		node_select_active_links(n_ptr);
288
	if (tipc_node_is_up(n_ptr))
289
		tipc_link_failover_send_queue(l_ptr);
290
	else
P
Per Liden 已提交
291
		node_lost_contact(n_ptr);
292 293 294 295 296 297 298 299 300

	/* Leave room for changeover header when returning 'mtu' to users: */
	if (active[0]) {
		n_ptr->act_mtus[0] = active[0]->max_pkt - INT_H_SIZE;
		n_ptr->act_mtus[1] = active[1]->max_pkt - INT_H_SIZE;
		return;
	}

	/* Loopback link went down? No fragmentation needed from now on. */
301
	if (n_ptr->addr == tn->own_addr) {
302 303 304
		n_ptr->act_mtus[0] = MAX_MSG_SIZE;
		n_ptr->act_mtus[1] = MAX_MSG_SIZE;
	}
P
Per Liden 已提交
305 306
}

307
int tipc_node_active_links(struct tipc_node *n_ptr)
P
Per Liden 已提交
308
{
309
	return n_ptr->active_links[0] != NULL;
P
Per Liden 已提交
310 311
}

312
int tipc_node_is_up(struct tipc_node *n_ptr)
P
Per Liden 已提交
313
{
314
	return tipc_node_active_links(n_ptr);
P
Per Liden 已提交
315 316
}

317
void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
P
Per Liden 已提交
318
{
319
	n_ptr->links[l_ptr->bearer_id] = l_ptr;
320
	n_ptr->link_cnt++;
P
Per Liden 已提交
321 322
}

323
void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
P
Per Liden 已提交
324
{
325 326 327
	int i;

	for (i = 0; i < MAX_BEARERS; i++) {
J
Jon Paul Maloy 已提交
328 329 330 331
		if (l_ptr != n_ptr->links[i])
			continue;
		n_ptr->links[i] = NULL;
		n_ptr->link_cnt--;
332
	}
P
Per Liden 已提交
333 334
}

335
static void node_established_contact(struct tipc_node *n_ptr)
P
Per Liden 已提交
336
{
Y
Ying Xue 已提交
337
	n_ptr->action_flags |= TIPC_NOTIFY_NODE_UP;
338
	n_ptr->bclink.oos_state = 0;
339 340
	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 已提交
341 342
}

343
static void node_lost_contact(struct tipc_node *n_ptr)
P
Per Liden 已提交
344 345
{
	char addr_string[16];
346 347 348 349 350
	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 已提交
351

352 353
	pr_debug("Lost contact with %s\n",
		 tipc_addr_string_fill(addr_string, n_ptr->addr));
354 355

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

359 360 361
		if (n_ptr->bclink.reasm_buf) {
			kfree_skb(n_ptr->bclink.reasm_buf);
			n_ptr->bclink.reasm_buf = NULL;
362 363
		}

364
		tipc_bclink_remove_node(n_ptr->net, n_ptr->addr);
365
		tipc_bclink_acknowledge(n_ptr, INVALID_LINK_SEQ);
P
Per Liden 已提交
366

367
		n_ptr->bclink.recv_permitted = false;
368
	}
P
Per Liden 已提交
369 370 371

	/* Abort link changeover */
	for (i = 0; i < MAX_BEARERS; i++) {
372
		struct tipc_link *l_ptr = n_ptr->links[i];
373
		if (!l_ptr)
P
Per Liden 已提交
374 375 376
			continue;
		l_ptr->reset_checkpoint = l_ptr->next_in_no;
		l_ptr->exp_msg_count = 0;
377
		tipc_link_reset_fragments(l_ptr);
378 379 380 381

		/* Link marked for deletion after failover? => do it now */
		if (l_ptr->flags & LINK_STOPPED)
			tipc_link_delete(l_ptr);
P
Per Liden 已提交
382 383
	}

384 385
	n_ptr->action_flags &= ~TIPC_WAIT_OWN_LINKS_DOWN;

386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
	/* 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 已提交
405 406
}

E
Erik Hugne 已提交
407 408 409 410 411 412 413 414 415
/**
 * 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
 */
416 417
int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 addr,
			   char *linkname, size_t len)
E
Erik Hugne 已提交
418 419
{
	struct tipc_link *link;
420
	struct tipc_node *node = tipc_node_find(net, addr);
E
Erik Hugne 已提交
421

E
Erik Hugne 已提交
422
	if ((bearer_id >= MAX_BEARERS) || !node)
E
Erik Hugne 已提交
423 424 425 426 427 428 429 430 431 432 433
		return -EINVAL;
	tipc_node_lock(node);
	link = node->links[bearer_id];
	if (link) {
		strncpy(linkname, link->name, len);
		tipc_node_unlock(node);
		return 0;
	}
	tipc_node_unlock(node);
	return -EINVAL;
}
434 435 436

void tipc_node_unlock(struct tipc_node *node)
{
437
	struct net *net = node->net;
438
	u32 addr = 0;
439
	u32 flags = node->action_flags;
Y
Ying Xue 已提交
440
	u32 link_id = 0;
441
	struct list_head *publ_list;
442
	struct sk_buff_head *inputq = node->inputq;
443
	struct sk_buff_head *namedq;
444

445 446
	if (likely(!flags || (flags == TIPC_MSG_EVT))) {
		node->action_flags = 0;
447
		spin_unlock_bh(&node->lock);
448 449
		if (flags == TIPC_MSG_EVT)
			tipc_sk_rcv(net, inputq);
450 451 452
		return;
	}

Y
Ying Xue 已提交
453 454
	addr = node->addr;
	link_id = node->link_id;
455
	namedq = node->namedq;
456
	publ_list = &node->publ_list;
Y
Ying Xue 已提交
457

458 459 460 461
	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 |
462
				TIPC_NAMED_MSG_EVT);
Y
Ying Xue 已提交
463

464 465
	spin_unlock_bh(&node->lock);

466 467
	if (flags & TIPC_NOTIFY_NODE_DOWN)
		tipc_publ_notify(net, publ_list, addr);
468

469
	if (flags & TIPC_WAKEUP_BCAST_USERS)
470
		tipc_bclink_wakeup_users(net);
471

Y
Ying Xue 已提交
472
	if (flags & TIPC_NOTIFY_NODE_UP)
473
		tipc_named_node_up(net, addr);
Y
Ying Xue 已提交
474 475

	if (flags & TIPC_NOTIFY_LINK_UP)
476
		tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr,
Y
Ying Xue 已提交
477 478 479
				     TIPC_NODE_SCOPE, link_id, addr);

	if (flags & TIPC_NOTIFY_LINK_DOWN)
480
		tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr,
Y
Ying Xue 已提交
481
				      link_id, addr);
482 483 484 485 486 487

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

	if (flags & TIPC_NAMED_MSG_EVT)
		tipc_named_rcv(net, namedq);
488 489 490

	if (flags & TIPC_BCAST_MSG_EVT)
		tipc_bclink_input(net);
491
}
492 493

/* Caller should hold node lock for the passed node */
494
static int __tipc_nl_add_node(struct tipc_nl_msg *msg, struct tipc_node *node)
495 496 497 498
{
	void *hdr;
	struct nlattr *attrs;

499
	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
			  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;
530 531
	struct net *net = sock_net(skb->sk);
	struct tipc_net *tn = net_generic(net, tipc_net_id);
532 533 534 535 536 537 538 539 540 541 542 543 544 545
	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();

546
	if (last_addr && !tipc_node_find(net, last_addr)) {
547 548 549 550 551 552 553 554 555 556 557
		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;
	}

558
	list_for_each_entry_rcu(node, &tn->node_list, list) {
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
		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;
}