aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/discover.c
diff options
context:
space:
mode:
authorErik Hugne <erik.hugne@ericsson.com>2013-12-06 10:08:00 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-09 20:30:29 -0500
commit512137eeff00f73a8a62e481a6575f1556cf962c (patch)
treec588e741a1587dc34835871110949ef92b5faab7 /net/tipc/discover.c
parentb73e9e3cf06ef8180c75a6bd28cdd1b833d22a3a (diff)
tipc: remove interface state mirroring in bearer
struct 'tipc_bearer' is a generic representation of the underlying media type, and exists in a one-to-one relationship to each interface TIPC is using. The struct contains a 'blocked' flag that mirrors the operational and execution state of the represented interface, and is updated through notification calls from the latter. The users of tipc_bearer are checking this flag before each attempt to send a packet via the interface. This state mirroring serves no purpose in the current code base. TIPC links will not discover a media failure any faster through this mechanism, and in reality the flag only adds overhead at packet sending and reception. Furthermore, the fact that the flag needs to be protected by a spinlock aggregated into tipc_bearer has turned out to cause a serious and completely unnecessary deadlock problem. CPU0 CPU1 ---- ---- Time 0: bearer_disable() link_timeout() Time 1: spin_lock_bh(&b_ptr->lock) tipc_link_push_queue() Time 2: tipc_link_delete() tipc_bearer_blocked(b_ptr) Time 3: k_cancel_timer(&req->timer) spin_lock_bh(&b_ptr->lock) Time 4: del_timer_sync(&req->timer) I.e., del_timer_sync() on CPU0 never returns, because the timer handler on CPU1 is waiting for the bearer lock. We eliminate the 'blocked' flag from struct tipc_bearer, along with all tests on this flag. This not only resolves the deadlock, but also simplifies and speeds up the data path execution of TIPC. It also fits well into our ongoing effort to make the locking policy simpler and more manageable. An effect of this change is that we can get rid of functions such as tipc_bearer_blocked(), tipc_continue() and tipc_block_bearer(). We replace the latter with a new function, tipc_reset_bearer(), which resets all links associated to the bearer immediately after an interface goes down. A user might notice one slight change in link behaviour after this change. When an interface goes down, (e.g. through a NETDEV_DOWN event) all attached links will be reset immediately, instead of leaving it to each link to detect the failure through a timer-driven mechanism. We consider this an improvement, and see no obvious risks with the new behavior. Signed-off-by: Erik Hugne <erik.hugne@ericsson.com> Reviewed-by: Ying Xue <ying.xue@windriver.com> Reviewed-by: Paul Gortmaker <Paul.Gortmaker@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/discover.c')
-rw-r--r--net/tipc/discover.c17
1 files changed, 4 insertions, 13 deletions
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index ecc758c6eacf..bc849f1efa16 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -239,7 +239,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
239 /* Accept discovery message & send response, if necessary */ 239 /* Accept discovery message & send response, if necessary */
240 link_fully_up = link_working_working(link); 240 link_fully_up = link_working_working(link);
241 241
242 if ((type == DSC_REQ_MSG) && !link_fully_up && !b_ptr->blocked) { 242 if ((type == DSC_REQ_MSG) && !link_fully_up) {
243 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr); 243 rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
244 if (rbuf) { 244 if (rbuf) {
245 tipc_bearer_send(b_ptr, rbuf, &media_addr); 245 tipc_bearer_send(b_ptr, rbuf, &media_addr);
@@ -288,16 +288,6 @@ void tipc_disc_remove_dest(struct tipc_link_req *req)
288} 288}
289 289
290/** 290/**
291 * disc_send_msg - send link setup request message
292 * @req: ptr to link request structure
293 */
294static void disc_send_msg(struct tipc_link_req *req)
295{
296 if (!req->bearer->blocked)
297 tipc_bearer_send(req->bearer, req->buf, &req->dest);
298}
299
300/**
301 * disc_timeout - send a periodic link setup request 291 * disc_timeout - send a periodic link setup request
302 * @req: ptr to link request structure 292 * @req: ptr to link request structure
303 * 293 *
@@ -322,7 +312,8 @@ static void disc_timeout(struct tipc_link_req *req)
322 * hold at fast polling rate if don't have any associated nodes, 312 * hold at fast polling rate if don't have any associated nodes,
323 * otherwise hold at slow polling rate 313 * otherwise hold at slow polling rate
324 */ 314 */
325 disc_send_msg(req); 315 tipc_bearer_send(req->bearer, req->buf, &req->dest);
316
326 317
327 req->timer_intv *= 2; 318 req->timer_intv *= 2;
328 if (req->num_nodes) 319 if (req->num_nodes)
@@ -368,7 +359,7 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest,
368 k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); 359 k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req);
369 k_start_timer(&req->timer, req->timer_intv); 360 k_start_timer(&req->timer, req->timer_intv);
370 b_ptr->link_req = req; 361 b_ptr->link_req = req;
371 disc_send_msg(req); 362 tipc_bearer_send(req->bearer, req->buf, &req->dest);
372 return 0; 363 return 0;
373} 364}
374 365