diff options
| author | Ying Xue <ying.xue@windriver.com> | 2015-03-26 06:10:24 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-03-29 15:40:28 -0400 |
| commit | 8a0f6ebe8494c5c6ccfe12264385b64c280e3241 (patch) | |
| tree | 2f106a95ffda73b8e8f1596cc95152398cd5379b /net/tipc | |
| parent | b952b2befb6f6b009e91f087285b9a0a6beb1cc8 (diff) | |
tipc: involve reference counter for node structure
TIPC node hash node table is protected with rcu lock on read side.
tipc_node_find() is used to look for a node object with node address
through iterating the hash node table. As the entire process of what
tipc_node_find() traverses the table is guarded with rcu read lock,
it's safe for us. However, when callers use the node object returned
by tipc_node_find(), there is no rcu read lock applied. Therefore,
this is absolutely unsafe for callers of tipc_node_find().
Now we introduce a reference counter for node structure. Before
tipc_node_find() returns node object to its caller, it first increases
the reference counter. Accordingly, after its caller used it up,
it decreases the counter again. This can prevent a node being used by
one thread from being freed by another thread.
Reviewed-by: Erik Hugne <erik.hugne@ericsson.com>
Reviewed-by: Jon Maloy <jon.maloy@ericson.com>
Signed-off-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
| -rw-r--r-- | net/tipc/bcast.c | 5 | ||||
| -rw-r--r-- | net/tipc/discover.c | 1 | ||||
| -rw-r--r-- | net/tipc/link.c | 7 | ||||
| -rw-r--r-- | net/tipc/name_distr.c | 2 | ||||
| -rw-r--r-- | net/tipc/node.c | 85 | ||||
| -rw-r--r-- | net/tipc/node.h | 9 |
6 files changed, 79 insertions, 30 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 4289dd62f589..ae558dd7f8ee 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
| @@ -329,13 +329,12 @@ static void bclink_peek_nack(struct net *net, struct tipc_msg *msg) | |||
| 329 | return; | 329 | return; |
| 330 | 330 | ||
| 331 | tipc_node_lock(n_ptr); | 331 | tipc_node_lock(n_ptr); |
| 332 | |||
| 333 | if (n_ptr->bclink.recv_permitted && | 332 | if (n_ptr->bclink.recv_permitted && |
| 334 | (n_ptr->bclink.last_in != n_ptr->bclink.last_sent) && | 333 | (n_ptr->bclink.last_in != n_ptr->bclink.last_sent) && |
| 335 | (n_ptr->bclink.last_in == msg_bcgap_after(msg))) | 334 | (n_ptr->bclink.last_in == msg_bcgap_after(msg))) |
| 336 | n_ptr->bclink.oos_state = 2; | 335 | n_ptr->bclink.oos_state = 2; |
| 337 | |||
| 338 | tipc_node_unlock(n_ptr); | 336 | tipc_node_unlock(n_ptr); |
| 337 | tipc_node_put(n_ptr); | ||
| 339 | } | 338 | } |
| 340 | 339 | ||
| 341 | /* tipc_bclink_xmit - deliver buffer chain to all nodes in cluster | 340 | /* tipc_bclink_xmit - deliver buffer chain to all nodes in cluster |
| @@ -466,6 +465,7 @@ void tipc_bclink_rcv(struct net *net, struct sk_buff *buf) | |||
| 466 | tipc_node_unlock(node); | 465 | tipc_node_unlock(node); |
| 467 | bclink_peek_nack(net, msg); | 466 | bclink_peek_nack(net, msg); |
| 468 | } | 467 | } |
| 468 | tipc_node_put(node); | ||
| 469 | goto exit; | 469 | goto exit; |
| 470 | } | 470 | } |
| 471 | 471 | ||
| @@ -570,6 +570,7 @@ receive: | |||
| 570 | 570 | ||
| 571 | unlock: | 571 | unlock: |
| 572 | tipc_node_unlock(node); | 572 | tipc_node_unlock(node); |
| 573 | tipc_node_put(node); | ||
| 573 | exit: | 574 | exit: |
| 574 | kfree_skb(buf); | 575 | kfree_skb(buf); |
| 575 | } | 576 | } |
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 169f3dd038b9..967e292f53c8 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
| @@ -260,6 +260,7 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *buf, | |||
| 260 | } | 260 | } |
| 261 | } | 261 | } |
| 262 | tipc_node_unlock(node); | 262 | tipc_node_unlock(node); |
| 263 | tipc_node_put(node); | ||
| 263 | } | 264 | } |
| 264 | 265 | ||
| 265 | /** | 266 | /** |
diff --git a/net/tipc/link.c b/net/tipc/link.c index f5e086c5f724..514466efc25c 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -854,6 +854,7 @@ int tipc_link_xmit(struct net *net, struct sk_buff_head *list, u32 dnode, | |||
| 854 | if (link) | 854 | if (link) |
| 855 | rc = __tipc_link_xmit(net, link, list); | 855 | rc = __tipc_link_xmit(net, link, list); |
| 856 | tipc_node_unlock(node); | 856 | tipc_node_unlock(node); |
| 857 | tipc_node_put(node); | ||
| 857 | } | 858 | } |
| 858 | if (link) | 859 | if (link) |
| 859 | return rc; | 860 | return rc; |
| @@ -1116,8 +1117,8 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) | |||
| 1116 | n_ptr = tipc_node_find(net, msg_prevnode(msg)); | 1117 | n_ptr = tipc_node_find(net, msg_prevnode(msg)); |
| 1117 | if (unlikely(!n_ptr)) | 1118 | if (unlikely(!n_ptr)) |
| 1118 | goto discard; | 1119 | goto discard; |
| 1119 | tipc_node_lock(n_ptr); | ||
| 1120 | 1120 | ||
| 1121 | tipc_node_lock(n_ptr); | ||
| 1121 | /* Locate unicast link endpoint that should handle message */ | 1122 | /* Locate unicast link endpoint that should handle message */ |
| 1122 | l_ptr = n_ptr->links[b_ptr->identity]; | 1123 | l_ptr = n_ptr->links[b_ptr->identity]; |
| 1123 | if (unlikely(!l_ptr)) | 1124 | if (unlikely(!l_ptr)) |
| @@ -1205,6 +1206,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b_ptr) | |||
| 1205 | skb = NULL; | 1206 | skb = NULL; |
| 1206 | unlock: | 1207 | unlock: |
| 1207 | tipc_node_unlock(n_ptr); | 1208 | tipc_node_unlock(n_ptr); |
| 1209 | tipc_node_put(n_ptr); | ||
| 1208 | discard: | 1210 | discard: |
| 1209 | if (unlikely(skb)) | 1211 | if (unlikely(skb)) |
| 1210 | kfree_skb(skb); | 1212 | kfree_skb(skb); |
| @@ -2236,7 +2238,6 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 2236 | msg.seq = cb->nlh->nlmsg_seq; | 2238 | msg.seq = cb->nlh->nlmsg_seq; |
| 2237 | 2239 | ||
| 2238 | rcu_read_lock(); | 2240 | rcu_read_lock(); |
| 2239 | |||
| 2240 | if (prev_node) { | 2241 | if (prev_node) { |
| 2241 | node = tipc_node_find(net, prev_node); | 2242 | node = tipc_node_find(net, prev_node); |
| 2242 | if (!node) { | 2243 | if (!node) { |
| @@ -2249,6 +2250,7 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 2249 | cb->prev_seq = 1; | 2250 | cb->prev_seq = 1; |
| 2250 | goto out; | 2251 | goto out; |
| 2251 | } | 2252 | } |
| 2253 | tipc_node_put(node); | ||
| 2252 | 2254 | ||
| 2253 | list_for_each_entry_continue_rcu(node, &tn->node_list, | 2255 | list_for_each_entry_continue_rcu(node, &tn->node_list, |
| 2254 | list) { | 2256 | list) { |
| @@ -2256,6 +2258,7 @@ int tipc_nl_link_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 2256 | err = __tipc_nl_add_node_links(net, &msg, node, | 2258 | err = __tipc_nl_add_node_links(net, &msg, node, |
| 2257 | &prev_link); | 2259 | &prev_link); |
| 2258 | tipc_node_unlock(node); | 2260 | tipc_node_unlock(node); |
| 2261 | tipc_node_put(node); | ||
| 2259 | if (err) | 2262 | if (err) |
| 2260 | goto out; | 2263 | goto out; |
| 2261 | 2264 | ||
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 506aaa565da7..41e7b7e4dda0 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
| @@ -244,6 +244,7 @@ static void tipc_publ_subscribe(struct net *net, struct publication *publ, | |||
| 244 | tipc_node_lock(node); | 244 | tipc_node_lock(node); |
| 245 | list_add_tail(&publ->nodesub_list, &node->publ_list); | 245 | list_add_tail(&publ->nodesub_list, &node->publ_list); |
| 246 | tipc_node_unlock(node); | 246 | tipc_node_unlock(node); |
| 247 | tipc_node_put(node); | ||
| 247 | } | 248 | } |
| 248 | 249 | ||
| 249 | static void tipc_publ_unsubscribe(struct net *net, struct publication *publ, | 250 | static void tipc_publ_unsubscribe(struct net *net, struct publication *publ, |
| @@ -258,6 +259,7 @@ static void tipc_publ_unsubscribe(struct net *net, struct publication *publ, | |||
| 258 | tipc_node_lock(node); | 259 | tipc_node_lock(node); |
| 259 | list_del_init(&publ->nodesub_list); | 260 | list_del_init(&publ->nodesub_list); |
| 260 | tipc_node_unlock(node); | 261 | tipc_node_unlock(node); |
| 262 | tipc_node_put(node); | ||
| 261 | } | 263 | } |
| 262 | 264 | ||
| 263 | /** | 265 | /** |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 5cc43d34ad0a..3e4f04897c03 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | 42 | ||
| 43 | static void node_lost_contact(struct tipc_node *n_ptr); | 43 | static void node_lost_contact(struct tipc_node *n_ptr); |
| 44 | static void node_established_contact(struct tipc_node *n_ptr); | 44 | static void node_established_contact(struct tipc_node *n_ptr); |
| 45 | static void tipc_node_delete(struct tipc_node *node); | ||
| 45 | 46 | ||
| 46 | struct tipc_sock_conn { | 47 | struct tipc_sock_conn { |
| 47 | u32 port; | 48 | u32 port; |
| @@ -67,6 +68,23 @@ static unsigned int tipc_hashfn(u32 addr) | |||
| 67 | return addr & (NODE_HTABLE_SIZE - 1); | 68 | return addr & (NODE_HTABLE_SIZE - 1); |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 71 | static void tipc_node_kref_release(struct kref *kref) | ||
| 72 | { | ||
| 73 | struct tipc_node *node = container_of(kref, struct tipc_node, kref); | ||
| 74 | |||
| 75 | tipc_node_delete(node); | ||
| 76 | } | ||
| 77 | |||
| 78 | void tipc_node_put(struct tipc_node *node) | ||
| 79 | { | ||
| 80 | kref_put(&node->kref, tipc_node_kref_release); | ||
| 81 | } | ||
| 82 | |||
| 83 | static void tipc_node_get(struct tipc_node *node) | ||
| 84 | { | ||
| 85 | kref_get(&node->kref); | ||
| 86 | } | ||
| 87 | |||
| 70 | /* | 88 | /* |
| 71 | * tipc_node_find - locate specified node object, if it exists | 89 | * tipc_node_find - locate specified node object, if it exists |
| 72 | */ | 90 | */ |
| @@ -82,6 +100,7 @@ struct tipc_node *tipc_node_find(struct net *net, u32 addr) | |||
| 82 | hlist_for_each_entry_rcu(node, &tn->node_htable[tipc_hashfn(addr)], | 100 | hlist_for_each_entry_rcu(node, &tn->node_htable[tipc_hashfn(addr)], |
| 83 | hash) { | 101 | hash) { |
| 84 | if (node->addr == addr) { | 102 | if (node->addr == addr) { |
| 103 | tipc_node_get(node); | ||
| 85 | rcu_read_unlock(); | 104 | rcu_read_unlock(); |
| 86 | return node; | 105 | return node; |
| 87 | } | 106 | } |
| @@ -106,6 +125,7 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr) | |||
| 106 | } | 125 | } |
| 107 | n_ptr->addr = addr; | 126 | n_ptr->addr = addr; |
| 108 | n_ptr->net = net; | 127 | n_ptr->net = net; |
| 128 | kref_init(&n_ptr->kref); | ||
| 109 | spin_lock_init(&n_ptr->lock); | 129 | spin_lock_init(&n_ptr->lock); |
| 110 | INIT_HLIST_NODE(&n_ptr->hash); | 130 | INIT_HLIST_NODE(&n_ptr->hash); |
| 111 | INIT_LIST_HEAD(&n_ptr->list); | 131 | INIT_LIST_HEAD(&n_ptr->list); |
| @@ -120,16 +140,17 @@ struct tipc_node *tipc_node_create(struct net *net, u32 addr) | |||
| 120 | list_add_tail_rcu(&n_ptr->list, &temp_node->list); | 140 | list_add_tail_rcu(&n_ptr->list, &temp_node->list); |
| 121 | n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN; | 141 | n_ptr->action_flags = TIPC_WAIT_PEER_LINKS_DOWN; |
| 122 | n_ptr->signature = INVALID_NODE_SIG; | 142 | n_ptr->signature = INVALID_NODE_SIG; |
| 143 | tipc_node_get(n_ptr); | ||
| 123 | exit: | 144 | exit: |
| 124 | spin_unlock_bh(&tn->node_list_lock); | 145 | spin_unlock_bh(&tn->node_list_lock); |
| 125 | return n_ptr; | 146 | return n_ptr; |
| 126 | } | 147 | } |
| 127 | 148 | ||
| 128 | static void tipc_node_delete(struct tipc_net *tn, struct tipc_node *n_ptr) | 149 | static void tipc_node_delete(struct tipc_node *node) |
| 129 | { | 150 | { |
| 130 | list_del_rcu(&n_ptr->list); | 151 | list_del_rcu(&node->list); |
| 131 | hlist_del_rcu(&n_ptr->hash); | 152 | hlist_del_rcu(&node->hash); |
| 132 | kfree_rcu(n_ptr, rcu); | 153 | kfree_rcu(node, rcu); |
| 133 | } | 154 | } |
| 134 | 155 | ||
| 135 | void tipc_node_stop(struct net *net) | 156 | void tipc_node_stop(struct net *net) |
| @@ -139,7 +160,7 @@ void tipc_node_stop(struct net *net) | |||
| 139 | 160 | ||
| 140 | spin_lock_bh(&tn->node_list_lock); | 161 | spin_lock_bh(&tn->node_list_lock); |
| 141 | list_for_each_entry_safe(node, t_node, &tn->node_list, list) | 162 | list_for_each_entry_safe(node, t_node, &tn->node_list, list) |
| 142 | tipc_node_delete(tn, node); | 163 | tipc_node_put(node); |
| 143 | spin_unlock_bh(&tn->node_list_lock); | 164 | spin_unlock_bh(&tn->node_list_lock); |
| 144 | } | 165 | } |
| 145 | 166 | ||
| @@ -147,6 +168,7 @@ int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port) | |||
| 147 | { | 168 | { |
| 148 | struct tipc_node *node; | 169 | struct tipc_node *node; |
| 149 | struct tipc_sock_conn *conn; | 170 | struct tipc_sock_conn *conn; |
| 171 | int err = 0; | ||
| 150 | 172 | ||
| 151 | if (in_own_node(net, dnode)) | 173 | if (in_own_node(net, dnode)) |
| 152 | return 0; | 174 | return 0; |
| @@ -157,8 +179,10 @@ int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port) | |||
| 157 | return -EHOSTUNREACH; | 179 | return -EHOSTUNREACH; |
| 158 | } | 180 | } |
| 159 | conn = kmalloc(sizeof(*conn), GFP_ATOMIC); | 181 | conn = kmalloc(sizeof(*conn), GFP_ATOMIC); |
| 160 | if (!conn) | 182 | if (!conn) { |
| 161 | return -EHOSTUNREACH; | 183 | err = -EHOSTUNREACH; |
| 184 | goto exit; | ||
| 185 | } | ||
| 162 | conn->peer_node = dnode; | 186 | conn->peer_node = dnode; |
| 163 | conn->port = port; | 187 | conn->port = port; |
| 164 | conn->peer_port = peer_port; | 188 | conn->peer_port = peer_port; |
| @@ -166,7 +190,9 @@ int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 peer_port) | |||
| 166 | tipc_node_lock(node); | 190 | tipc_node_lock(node); |
| 167 | list_add_tail(&conn->list, &node->conn_sks); | 191 | list_add_tail(&conn->list, &node->conn_sks); |
| 168 | tipc_node_unlock(node); | 192 | tipc_node_unlock(node); |
| 169 | return 0; | 193 | exit: |
| 194 | tipc_node_put(node); | ||
| 195 | return err; | ||
| 170 | } | 196 | } |
| 171 | 197 | ||
| 172 | void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port) | 198 | void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port) |
| @@ -189,6 +215,7 @@ void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port) | |||
| 189 | kfree(conn); | 215 | kfree(conn); |
| 190 | } | 216 | } |
| 191 | tipc_node_unlock(node); | 217 | tipc_node_unlock(node); |
| 218 | tipc_node_put(node); | ||
| 192 | } | 219 | } |
| 193 | 220 | ||
| 194 | /** | 221 | /** |
| @@ -417,19 +444,25 @@ int tipc_node_get_linkname(struct net *net, u32 bearer_id, u32 addr, | |||
| 417 | char *linkname, size_t len) | 444 | char *linkname, size_t len) |
| 418 | { | 445 | { |
| 419 | struct tipc_link *link; | 446 | struct tipc_link *link; |
| 447 | int err = -EINVAL; | ||
| 420 | struct tipc_node *node = tipc_node_find(net, addr); | 448 | struct tipc_node *node = tipc_node_find(net, addr); |
| 421 | 449 | ||
| 422 | if ((bearer_id >= MAX_BEARERS) || !node) | 450 | if (!node) |
| 423 | return -EINVAL; | 451 | return err; |
| 452 | |||
| 453 | if (bearer_id >= MAX_BEARERS) | ||
| 454 | goto exit; | ||
| 455 | |||
| 424 | tipc_node_lock(node); | 456 | tipc_node_lock(node); |
| 425 | link = node->links[bearer_id]; | 457 | link = node->links[bearer_id]; |
| 426 | if (link) { | 458 | if (link) { |
| 427 | strncpy(linkname, link->name, len); | 459 | strncpy(linkname, link->name, len); |
| 428 | tipc_node_unlock(node); | 460 | err = 0; |
| 429 | return 0; | ||
| 430 | } | 461 | } |
| 462 | exit: | ||
| 431 | tipc_node_unlock(node); | 463 | tipc_node_unlock(node); |
| 432 | return -EINVAL; | 464 | tipc_node_put(node); |
| 465 | return err; | ||
| 433 | } | 466 | } |
| 434 | 467 | ||
| 435 | void tipc_node_unlock(struct tipc_node *node) | 468 | void tipc_node_unlock(struct tipc_node *node) |
| @@ -545,17 +578,21 @@ int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 545 | msg.seq = cb->nlh->nlmsg_seq; | 578 | msg.seq = cb->nlh->nlmsg_seq; |
| 546 | 579 | ||
| 547 | rcu_read_lock(); | 580 | rcu_read_lock(); |
| 548 | 581 | if (last_addr) { | |
| 549 | if (last_addr && !tipc_node_find(net, last_addr)) { | 582 | node = tipc_node_find(net, last_addr); |
| 550 | rcu_read_unlock(); | 583 | if (!node) { |
| 551 | /* We never set seq or call nl_dump_check_consistent() this | 584 | rcu_read_unlock(); |
| 552 | * means that setting prev_seq here will cause the consistence | 585 | /* We never set seq or call nl_dump_check_consistent() |
| 553 | * check to fail in the netlink callback handler. Resulting in | 586 | * this means that setting prev_seq here will cause the |
| 554 | * the NLMSG_DONE message having the NLM_F_DUMP_INTR flag set if | 587 | * consistence check to fail in the netlink callback |
| 555 | * the node state changed while we released the lock. | 588 | * handler. Resulting in the NLMSG_DONE message having |
| 556 | */ | 589 | * the NLM_F_DUMP_INTR flag set if the node state |
| 557 | cb->prev_seq = 1; | 590 | * changed while we released the lock. |
| 558 | return -EPIPE; | 591 | */ |
| 592 | cb->prev_seq = 1; | ||
| 593 | return -EPIPE; | ||
| 594 | } | ||
| 595 | tipc_node_put(node); | ||
| 559 | } | 596 | } |
| 560 | 597 | ||
| 561 | list_for_each_entry_rcu(node, &tn->node_list, list) { | 598 | list_for_each_entry_rcu(node, &tn->node_list, list) { |
diff --git a/net/tipc/node.h b/net/tipc/node.h index 9629ecd2bdd8..02d5c20dc551 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
| @@ -94,6 +94,7 @@ struct tipc_node_bclink { | |||
| 94 | /** | 94 | /** |
| 95 | * struct tipc_node - TIPC node structure | 95 | * struct tipc_node - TIPC node structure |
| 96 | * @addr: network address of node | 96 | * @addr: network address of node |
| 97 | * @ref: reference counter to node object | ||
| 97 | * @lock: spinlock governing access to structure | 98 | * @lock: spinlock governing access to structure |
| 98 | * @net: the applicable net namespace | 99 | * @net: the applicable net namespace |
| 99 | * @hash: links to adjacent nodes in unsorted hash chain | 100 | * @hash: links to adjacent nodes in unsorted hash chain |
| @@ -115,6 +116,7 @@ struct tipc_node_bclink { | |||
| 115 | */ | 116 | */ |
| 116 | struct tipc_node { | 117 | struct tipc_node { |
| 117 | u32 addr; | 118 | u32 addr; |
| 119 | struct kref kref; | ||
| 118 | spinlock_t lock; | 120 | spinlock_t lock; |
| 119 | struct net *net; | 121 | struct net *net; |
| 120 | struct hlist_node hash; | 122 | struct hlist_node hash; |
| @@ -137,6 +139,7 @@ struct tipc_node { | |||
| 137 | }; | 139 | }; |
| 138 | 140 | ||
| 139 | struct tipc_node *tipc_node_find(struct net *net, u32 addr); | 141 | struct tipc_node *tipc_node_find(struct net *net, u32 addr); |
| 142 | void tipc_node_put(struct tipc_node *node); | ||
| 140 | struct tipc_node *tipc_node_create(struct net *net, u32 addr); | 143 | struct tipc_node *tipc_node_create(struct net *net, u32 addr); |
| 141 | void tipc_node_stop(struct net *net); | 144 | void tipc_node_stop(struct net *net); |
| 142 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | 145 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); |
| @@ -171,10 +174,12 @@ static inline uint tipc_node_get_mtu(struct net *net, u32 addr, u32 selector) | |||
| 171 | 174 | ||
| 172 | node = tipc_node_find(net, addr); | 175 | node = tipc_node_find(net, addr); |
| 173 | 176 | ||
| 174 | if (likely(node)) | 177 | if (likely(node)) { |
| 175 | mtu = node->act_mtus[selector & 1]; | 178 | mtu = node->act_mtus[selector & 1]; |
| 176 | else | 179 | tipc_node_put(node); |
| 180 | } else { | ||
| 177 | mtu = MAX_MSG_SIZE; | 181 | mtu = MAX_MSG_SIZE; |
| 182 | } | ||
| 178 | 183 | ||
| 179 | return mtu; | 184 | return mtu; |
| 180 | } | 185 | } |
