diff options
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/discover.c | 19 | ||||
-rw-r--r-- | net/tipc/link.c | 11 | ||||
-rw-r--r-- | net/tipc/net.c | 45 | ||||
-rw-r--r-- | net/tipc/net.h | 2 | ||||
-rw-r--r-- | net/tipc/node.c | 7 | ||||
-rw-r--r-- | net/tipc/socket.c | 15 |
6 files changed, 71 insertions, 28 deletions
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 2830709957bd..c138d68e8a69 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
@@ -166,7 +166,8 @@ static bool tipc_disc_addr_trial_msg(struct tipc_discoverer *d, | |||
166 | 166 | ||
167 | /* Apply trial address if we just left trial period */ | 167 | /* Apply trial address if we just left trial period */ |
168 | if (!trial && !self) { | 168 | if (!trial && !self) { |
169 | tipc_net_finalize(net, tn->trial_addr); | 169 | tipc_sched_net_finalize(net, tn->trial_addr); |
170 | msg_set_prevnode(buf_msg(d->skb), tn->trial_addr); | ||
170 | msg_set_type(buf_msg(d->skb), DSC_REQ_MSG); | 171 | msg_set_type(buf_msg(d->skb), DSC_REQ_MSG); |
171 | } | 172 | } |
172 | 173 | ||
@@ -300,14 +301,12 @@ static void tipc_disc_timeout(struct timer_list *t) | |||
300 | goto exit; | 301 | goto exit; |
301 | } | 302 | } |
302 | 303 | ||
303 | /* Trial period over ? */ | 304 | /* Did we just leave trial period ? */ |
304 | if (!time_before(jiffies, tn->addr_trial_end)) { | 305 | if (!time_before(jiffies, tn->addr_trial_end) && !tipc_own_addr(net)) { |
305 | /* Did we just leave it ? */ | 306 | mod_timer(&d->timer, jiffies + TIPC_DISC_INIT); |
306 | if (!tipc_own_addr(net)) | 307 | spin_unlock_bh(&d->lock); |
307 | tipc_net_finalize(net, tn->trial_addr); | 308 | tipc_sched_net_finalize(net, tn->trial_addr); |
308 | 309 | return; | |
309 | msg_set_type(buf_msg(d->skb), DSC_REQ_MSG); | ||
310 | msg_set_prevnode(buf_msg(d->skb), tipc_own_addr(net)); | ||
311 | } | 310 | } |
312 | 311 | ||
313 | /* Adjust timeout interval according to discovery phase */ | 312 | /* Adjust timeout interval according to discovery phase */ |
@@ -319,6 +318,8 @@ static void tipc_disc_timeout(struct timer_list *t) | |||
319 | d->timer_intv = TIPC_DISC_SLOW; | 318 | d->timer_intv = TIPC_DISC_SLOW; |
320 | else if (!d->num_nodes && d->timer_intv > TIPC_DISC_FAST) | 319 | else if (!d->num_nodes && d->timer_intv > TIPC_DISC_FAST) |
321 | d->timer_intv = TIPC_DISC_FAST; | 320 | d->timer_intv = TIPC_DISC_FAST; |
321 | msg_set_type(buf_msg(d->skb), DSC_REQ_MSG); | ||
322 | msg_set_prevnode(buf_msg(d->skb), tn->trial_addr); | ||
322 | } | 323 | } |
323 | 324 | ||
324 | mod_timer(&d->timer, jiffies + d->timer_intv); | 325 | mod_timer(&d->timer, jiffies + d->timer_intv); |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 201c3b5bc96b..836727e363c4 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -1594,14 +1594,17 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, | |||
1594 | if (in_range(peers_prio, l->priority + 1, TIPC_MAX_LINK_PRI)) | 1594 | if (in_range(peers_prio, l->priority + 1, TIPC_MAX_LINK_PRI)) |
1595 | l->priority = peers_prio; | 1595 | l->priority = peers_prio; |
1596 | 1596 | ||
1597 | /* ACTIVATE_MSG serves as PEER_RESET if link is already down */ | 1597 | /* If peer is going down we want full re-establish cycle */ |
1598 | if (msg_peer_stopping(hdr)) | 1598 | if (msg_peer_stopping(hdr)) { |
1599 | rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT); | 1599 | rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT); |
1600 | else if ((mtyp == RESET_MSG) || !link_is_up(l)) | 1600 | break; |
1601 | } | ||
1602 | /* ACTIVATE_MSG serves as PEER_RESET if link is already down */ | ||
1603 | if (mtyp == RESET_MSG || !link_is_up(l)) | ||
1601 | rc = tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT); | 1604 | rc = tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT); |
1602 | 1605 | ||
1603 | /* ACTIVATE_MSG takes up link if it was already locally reset */ | 1606 | /* ACTIVATE_MSG takes up link if it was already locally reset */ |
1604 | if ((mtyp == ACTIVATE_MSG) && (l->state == LINK_ESTABLISHING)) | 1607 | if (mtyp == ACTIVATE_MSG && l->state == LINK_ESTABLISHING) |
1605 | rc = TIPC_LINK_UP_EVT; | 1608 | rc = TIPC_LINK_UP_EVT; |
1606 | 1609 | ||
1607 | l->peer_session = msg_session(hdr); | 1610 | l->peer_session = msg_session(hdr); |
diff --git a/net/tipc/net.c b/net/tipc/net.c index 62199cf5a56c..f076edb74338 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
@@ -104,6 +104,14 @@ | |||
104 | * - A local spin_lock protecting the queue of subscriber events. | 104 | * - A local spin_lock protecting the queue of subscriber events. |
105 | */ | 105 | */ |
106 | 106 | ||
107 | struct tipc_net_work { | ||
108 | struct work_struct work; | ||
109 | struct net *net; | ||
110 | u32 addr; | ||
111 | }; | ||
112 | |||
113 | static void tipc_net_finalize(struct net *net, u32 addr); | ||
114 | |||
107 | int tipc_net_init(struct net *net, u8 *node_id, u32 addr) | 115 | int tipc_net_init(struct net *net, u8 *node_id, u32 addr) |
108 | { | 116 | { |
109 | if (tipc_own_id(net)) { | 117 | if (tipc_own_id(net)) { |
@@ -119,17 +127,38 @@ int tipc_net_init(struct net *net, u8 *node_id, u32 addr) | |||
119 | return 0; | 127 | return 0; |
120 | } | 128 | } |
121 | 129 | ||
122 | void tipc_net_finalize(struct net *net, u32 addr) | 130 | static void tipc_net_finalize(struct net *net, u32 addr) |
123 | { | 131 | { |
124 | struct tipc_net *tn = tipc_net(net); | 132 | struct tipc_net *tn = tipc_net(net); |
125 | 133 | ||
126 | if (!cmpxchg(&tn->node_addr, 0, addr)) { | 134 | if (cmpxchg(&tn->node_addr, 0, addr)) |
127 | tipc_set_node_addr(net, addr); | 135 | return; |
128 | tipc_named_reinit(net); | 136 | tipc_set_node_addr(net, addr); |
129 | tipc_sk_reinit(net); | 137 | tipc_named_reinit(net); |
130 | tipc_nametbl_publish(net, TIPC_CFG_SRV, addr, addr, | 138 | tipc_sk_reinit(net); |
131 | TIPC_CLUSTER_SCOPE, 0, addr); | 139 | tipc_nametbl_publish(net, TIPC_CFG_SRV, addr, addr, |
132 | } | 140 | TIPC_CLUSTER_SCOPE, 0, addr); |
141 | } | ||
142 | |||
143 | static void tipc_net_finalize_work(struct work_struct *work) | ||
144 | { | ||
145 | struct tipc_net_work *fwork; | ||
146 | |||
147 | fwork = container_of(work, struct tipc_net_work, work); | ||
148 | tipc_net_finalize(fwork->net, fwork->addr); | ||
149 | kfree(fwork); | ||
150 | } | ||
151 | |||
152 | void tipc_sched_net_finalize(struct net *net, u32 addr) | ||
153 | { | ||
154 | struct tipc_net_work *fwork = kzalloc(sizeof(*fwork), GFP_ATOMIC); | ||
155 | |||
156 | if (!fwork) | ||
157 | return; | ||
158 | INIT_WORK(&fwork->work, tipc_net_finalize_work); | ||
159 | fwork->net = net; | ||
160 | fwork->addr = addr; | ||
161 | schedule_work(&fwork->work); | ||
133 | } | 162 | } |
134 | 163 | ||
135 | void tipc_net_stop(struct net *net) | 164 | void tipc_net_stop(struct net *net) |
diff --git a/net/tipc/net.h b/net/tipc/net.h index 09ad02b50bb1..b7f2e364eb99 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h | |||
@@ -42,7 +42,7 @@ | |||
42 | extern const struct nla_policy tipc_nl_net_policy[]; | 42 | extern const struct nla_policy tipc_nl_net_policy[]; |
43 | 43 | ||
44 | int tipc_net_init(struct net *net, u8 *node_id, u32 addr); | 44 | int tipc_net_init(struct net *net, u8 *node_id, u32 addr); |
45 | void tipc_net_finalize(struct net *net, u32 addr); | 45 | void tipc_sched_net_finalize(struct net *net, u32 addr); |
46 | void tipc_net_stop(struct net *net); | 46 | void tipc_net_stop(struct net *net); |
47 | int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb); | 47 | int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb); |
48 | int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info); | 48 | int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info); |
diff --git a/net/tipc/node.c b/net/tipc/node.c index 2afc4f8c37a7..488019766433 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -584,12 +584,15 @@ static void tipc_node_clear_links(struct tipc_node *node) | |||
584 | /* tipc_node_cleanup - delete nodes that does not | 584 | /* tipc_node_cleanup - delete nodes that does not |
585 | * have active links for NODE_CLEANUP_AFTER time | 585 | * have active links for NODE_CLEANUP_AFTER time |
586 | */ | 586 | */ |
587 | static int tipc_node_cleanup(struct tipc_node *peer) | 587 | static bool tipc_node_cleanup(struct tipc_node *peer) |
588 | { | 588 | { |
589 | struct tipc_net *tn = tipc_net(peer->net); | 589 | struct tipc_net *tn = tipc_net(peer->net); |
590 | bool deleted = false; | 590 | bool deleted = false; |
591 | 591 | ||
592 | spin_lock_bh(&tn->node_list_lock); | 592 | /* If lock held by tipc_node_stop() the node will be deleted anyway */ |
593 | if (!spin_trylock_bh(&tn->node_list_lock)) | ||
594 | return false; | ||
595 | |||
593 | tipc_node_write_lock(peer); | 596 | tipc_node_write_lock(peer); |
594 | 597 | ||
595 | if (!node_is_up(peer) && time_after(jiffies, peer->delete_at)) { | 598 | if (!node_is_up(peer) && time_after(jiffies, peer->delete_at)) { |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 636e6131769d..b57b1be7252b 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -1555,16 +1555,17 @@ static void tipc_sk_set_orig_addr(struct msghdr *m, struct sk_buff *skb) | |||
1555 | /** | 1555 | /** |
1556 | * tipc_sk_anc_data_recv - optionally capture ancillary data for received message | 1556 | * tipc_sk_anc_data_recv - optionally capture ancillary data for received message |
1557 | * @m: descriptor for message info | 1557 | * @m: descriptor for message info |
1558 | * @msg: received message header | 1558 | * @skb: received message buffer |
1559 | * @tsk: TIPC port associated with message | 1559 | * @tsk: TIPC port associated with message |
1560 | * | 1560 | * |
1561 | * Note: Ancillary data is not captured if not requested by receiver. | 1561 | * Note: Ancillary data is not captured if not requested by receiver. |
1562 | * | 1562 | * |
1563 | * Returns 0 if successful, otherwise errno | 1563 | * Returns 0 if successful, otherwise errno |
1564 | */ | 1564 | */ |
1565 | static int tipc_sk_anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | 1565 | static int tipc_sk_anc_data_recv(struct msghdr *m, struct sk_buff *skb, |
1566 | struct tipc_sock *tsk) | 1566 | struct tipc_sock *tsk) |
1567 | { | 1567 | { |
1568 | struct tipc_msg *msg; | ||
1568 | u32 anc_data[3]; | 1569 | u32 anc_data[3]; |
1569 | u32 err; | 1570 | u32 err; |
1570 | u32 dest_type; | 1571 | u32 dest_type; |
@@ -1573,6 +1574,7 @@ static int tipc_sk_anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
1573 | 1574 | ||
1574 | if (likely(m->msg_controllen == 0)) | 1575 | if (likely(m->msg_controllen == 0)) |
1575 | return 0; | 1576 | return 0; |
1577 | msg = buf_msg(skb); | ||
1576 | 1578 | ||
1577 | /* Optionally capture errored message object(s) */ | 1579 | /* Optionally capture errored message object(s) */ |
1578 | err = msg ? msg_errcode(msg) : 0; | 1580 | err = msg ? msg_errcode(msg) : 0; |
@@ -1583,6 +1585,9 @@ static int tipc_sk_anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | |||
1583 | if (res) | 1585 | if (res) |
1584 | return res; | 1586 | return res; |
1585 | if (anc_data[1]) { | 1587 | if (anc_data[1]) { |
1588 | if (skb_linearize(skb)) | ||
1589 | return -ENOMEM; | ||
1590 | msg = buf_msg(skb); | ||
1586 | res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], | 1591 | res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], |
1587 | msg_data(msg)); | 1592 | msg_data(msg)); |
1588 | if (res) | 1593 | if (res) |
@@ -1744,9 +1749,10 @@ static int tipc_recvmsg(struct socket *sock, struct msghdr *m, | |||
1744 | 1749 | ||
1745 | /* Collect msg meta data, including error code and rejected data */ | 1750 | /* Collect msg meta data, including error code and rejected data */ |
1746 | tipc_sk_set_orig_addr(m, skb); | 1751 | tipc_sk_set_orig_addr(m, skb); |
1747 | rc = tipc_sk_anc_data_recv(m, hdr, tsk); | 1752 | rc = tipc_sk_anc_data_recv(m, skb, tsk); |
1748 | if (unlikely(rc)) | 1753 | if (unlikely(rc)) |
1749 | goto exit; | 1754 | goto exit; |
1755 | hdr = buf_msg(skb); | ||
1750 | 1756 | ||
1751 | /* Capture data if non-error msg, otherwise just set return value */ | 1757 | /* Capture data if non-error msg, otherwise just set return value */ |
1752 | if (likely(!err)) { | 1758 | if (likely(!err)) { |
@@ -1856,9 +1862,10 @@ static int tipc_recvstream(struct socket *sock, struct msghdr *m, | |||
1856 | /* Collect msg meta data, incl. error code and rejected data */ | 1862 | /* Collect msg meta data, incl. error code and rejected data */ |
1857 | if (!copied) { | 1863 | if (!copied) { |
1858 | tipc_sk_set_orig_addr(m, skb); | 1864 | tipc_sk_set_orig_addr(m, skb); |
1859 | rc = tipc_sk_anc_data_recv(m, hdr, tsk); | 1865 | rc = tipc_sk_anc_data_recv(m, skb, tsk); |
1860 | if (rc) | 1866 | if (rc) |
1861 | break; | 1867 | break; |
1868 | hdr = buf_msg(skb); | ||
1862 | } | 1869 | } |
1863 | 1870 | ||
1864 | /* Copy data if msg ok, otherwise return error/partial data */ | 1871 | /* Copy data if msg ok, otherwise return error/partial data */ |