diff options
author | Allan Stephens <Allan.Stephens@windriver.com> | 2011-04-21 14:58:26 -0400 |
---|---|---|
committer | Paul Gortmaker <paul.gortmaker@windriver.com> | 2011-05-10 16:03:59 -0400 |
commit | 3a777ff8b14456e15991c9fcc225943453dc3a75 (patch) | |
tree | 50f2b2ca5c9a2a4a1df107da4db00611ae938f32 /net/tipc | |
parent | dc63d91eb1cf74233c68b0058dcd477f5d019d02 (diff) |
tipc: Enhance handling of discovery object creation failures
Modifies bearer creation and deletion code to improve handling of
scenarios when a neighbor discovery object cannot be created. The
creation routine now aborts the creation of a bearer if its discovery
object cannot be created, and deletes the newly created bearer, rather
than failing quietly and leaving an unusable bearer hanging around.
Since the exit via the goto label really isn't a definitive failure
in all cases, relabel it appropriately.
Signed-off-by: Allan Stephens <Allan.Stephens@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Diffstat (limited to 'net/tipc')
-rw-r--r-- | net/tipc/bearer.c | 30 | ||||
-rw-r--r-- | net/tipc/discover.c | 45 | ||||
-rw-r--r-- | net/tipc/discover.h | 8 |
3 files changed, 42 insertions, 41 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index f7c29af4ab81..5fcd1c1214fd 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -46,6 +46,8 @@ static u32 media_count; | |||
46 | 46 | ||
47 | struct tipc_bearer tipc_bearers[MAX_BEARERS]; | 47 | struct tipc_bearer tipc_bearers[MAX_BEARERS]; |
48 | 48 | ||
49 | static void bearer_disable(struct tipc_bearer *b_ptr); | ||
50 | |||
49 | /** | 51 | /** |
50 | * media_name_valid - validate media name | 52 | * media_name_valid - validate media name |
51 | * | 53 | * |
@@ -518,7 +520,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) | |||
518 | if (!m_ptr) { | 520 | if (!m_ptr) { |
519 | warn("Bearer <%s> rejected, media <%s> not registered\n", name, | 521 | warn("Bearer <%s> rejected, media <%s> not registered\n", name, |
520 | b_name.media_name); | 522 | b_name.media_name); |
521 | goto failed; | 523 | goto exit; |
522 | } | 524 | } |
523 | 525 | ||
524 | if (priority == TIPC_MEDIA_LINK_PRI) | 526 | if (priority == TIPC_MEDIA_LINK_PRI) |
@@ -534,14 +536,14 @@ restart: | |||
534 | } | 536 | } |
535 | if (!strcmp(name, tipc_bearers[i].name)) { | 537 | if (!strcmp(name, tipc_bearers[i].name)) { |
536 | warn("Bearer <%s> rejected, already enabled\n", name); | 538 | warn("Bearer <%s> rejected, already enabled\n", name); |
537 | goto failed; | 539 | goto exit; |
538 | } | 540 | } |
539 | if ((tipc_bearers[i].priority == priority) && | 541 | if ((tipc_bearers[i].priority == priority) && |
540 | (++with_this_prio > 2)) { | 542 | (++with_this_prio > 2)) { |
541 | if (priority-- == 0) { | 543 | if (priority-- == 0) { |
542 | warn("Bearer <%s> rejected, duplicate priority\n", | 544 | warn("Bearer <%s> rejected, duplicate priority\n", |
543 | name); | 545 | name); |
544 | goto failed; | 546 | goto exit; |
545 | } | 547 | } |
546 | warn("Bearer <%s> priority adjustment required %u->%u\n", | 548 | warn("Bearer <%s> priority adjustment required %u->%u\n", |
547 | name, priority + 1, priority); | 549 | name, priority + 1, priority); |
@@ -551,7 +553,7 @@ restart: | |||
551 | if (bearer_id >= MAX_BEARERS) { | 553 | if (bearer_id >= MAX_BEARERS) { |
552 | warn("Bearer <%s> rejected, bearer limit reached (%u)\n", | 554 | warn("Bearer <%s> rejected, bearer limit reached (%u)\n", |
553 | name, MAX_BEARERS); | 555 | name, MAX_BEARERS); |
554 | goto failed; | 556 | goto exit; |
555 | } | 557 | } |
556 | 558 | ||
557 | b_ptr = &tipc_bearers[bearer_id]; | 559 | b_ptr = &tipc_bearers[bearer_id]; |
@@ -559,7 +561,7 @@ restart: | |||
559 | res = m_ptr->enable_bearer(b_ptr); | 561 | res = m_ptr->enable_bearer(b_ptr); |
560 | if (res) { | 562 | if (res) { |
561 | warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res); | 563 | warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res); |
562 | goto failed; | 564 | goto exit; |
563 | } | 565 | } |
564 | 566 | ||
565 | b_ptr->identity = bearer_id; | 567 | b_ptr->identity = bearer_id; |
@@ -569,14 +571,18 @@ restart: | |||
569 | b_ptr->priority = priority; | 571 | b_ptr->priority = priority; |
570 | INIT_LIST_HEAD(&b_ptr->cong_links); | 572 | INIT_LIST_HEAD(&b_ptr->cong_links); |
571 | INIT_LIST_HEAD(&b_ptr->links); | 573 | INIT_LIST_HEAD(&b_ptr->links); |
572 | b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr, | ||
573 | disc_domain); | ||
574 | spin_lock_init(&b_ptr->lock); | 574 | spin_lock_init(&b_ptr->lock); |
575 | write_unlock_bh(&tipc_net_lock); | 575 | |
576 | res = tipc_disc_create(b_ptr, &m_ptr->bcast_addr, disc_domain); | ||
577 | if (res) { | ||
578 | bearer_disable(b_ptr); | ||
579 | warn("Bearer <%s> rejected, discovery object creation failed\n", | ||
580 | name); | ||
581 | goto exit; | ||
582 | } | ||
576 | info("Enabled bearer <%s>, discovery domain %s, priority %u\n", | 583 | info("Enabled bearer <%s>, discovery domain %s, priority %u\n", |
577 | name, tipc_addr_string_fill(addr_string, disc_domain), priority); | 584 | name, tipc_addr_string_fill(addr_string, disc_domain), priority); |
578 | return 0; | 585 | exit: |
579 | failed: | ||
580 | write_unlock_bh(&tipc_net_lock); | 586 | write_unlock_bh(&tipc_net_lock); |
581 | return res; | 587 | return res; |
582 | } | 588 | } |
@@ -627,14 +633,14 @@ static void bearer_disable(struct tipc_bearer *b_ptr) | |||
627 | struct link *temp_l_ptr; | 633 | struct link *temp_l_ptr; |
628 | 634 | ||
629 | info("Disabling bearer <%s>\n", b_ptr->name); | 635 | info("Disabling bearer <%s>\n", b_ptr->name); |
630 | tipc_disc_stop_link_req(b_ptr->link_req); | ||
631 | spin_lock_bh(&b_ptr->lock); | 636 | spin_lock_bh(&b_ptr->lock); |
632 | b_ptr->link_req = NULL; | ||
633 | b_ptr->blocked = 1; | 637 | b_ptr->blocked = 1; |
634 | b_ptr->media->disable_bearer(b_ptr); | 638 | b_ptr->media->disable_bearer(b_ptr); |
635 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 639 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { |
636 | tipc_link_delete(l_ptr); | 640 | tipc_link_delete(l_ptr); |
637 | } | 641 | } |
642 | if (b_ptr->link_req) | ||
643 | tipc_disc_delete(b_ptr->link_req); | ||
638 | spin_unlock_bh(&b_ptr->lock); | 644 | spin_unlock_bh(&b_ptr->lock); |
639 | memset(b_ptr, 0, sizeof(struct tipc_bearer)); | 645 | memset(b_ptr, 0, sizeof(struct tipc_bearer)); |
640 | } | 646 | } |
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index d2163bd99e59..6acf32a9eef8 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
@@ -216,22 +216,6 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
216 | } | 216 | } |
217 | 217 | ||
218 | /** | 218 | /** |
219 | * tipc_disc_stop_link_req - stop sending periodic link setup requests | ||
220 | * @req: ptr to link request structure | ||
221 | */ | ||
222 | |||
223 | void tipc_disc_stop_link_req(struct link_req *req) | ||
224 | { | ||
225 | if (!req) | ||
226 | return; | ||
227 | |||
228 | k_cancel_timer(&req->timer); | ||
229 | k_term_timer(&req->timer); | ||
230 | buf_discard(req->buf); | ||
231 | kfree(req); | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * tipc_disc_update_link_req - update frequency of periodic link setup requests | 219 | * tipc_disc_update_link_req - update frequency of periodic link setup requests |
236 | * @req: ptr to link request structure | 220 | * @req: ptr to link request structure |
237 | */ | 221 | */ |
@@ -286,28 +270,27 @@ static void disc_timeout(struct link_req *req) | |||
286 | } | 270 | } |
287 | 271 | ||
288 | /** | 272 | /** |
289 | * tipc_disc_init_link_req - start sending periodic link setup requests | 273 | * tipc_disc_create - create object to send periodic link setup requests |
290 | * @b_ptr: ptr to bearer issuing requests | 274 | * @b_ptr: ptr to bearer issuing requests |
291 | * @dest: destination address for request messages | 275 | * @dest: destination address for request messages |
292 | * @dest_domain: network domain to which links can be established | 276 | * @dest_domain: network domain to which links can be established |
293 | * | 277 | * |
294 | * Returns pointer to link request structure, or NULL if unable to create. | 278 | * Returns 0 if successful, otherwise -errno. |
295 | */ | 279 | */ |
296 | 280 | ||
297 | struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr, | 281 | int tipc_disc_create(struct tipc_bearer *b_ptr, |
298 | const struct tipc_media_addr *dest, | 282 | struct tipc_media_addr *dest, u32 dest_domain) |
299 | u32 dest_domain) | ||
300 | { | 283 | { |
301 | struct link_req *req; | 284 | struct link_req *req; |
302 | 285 | ||
303 | req = kmalloc(sizeof(*req), GFP_ATOMIC); | 286 | req = kmalloc(sizeof(*req), GFP_ATOMIC); |
304 | if (!req) | 287 | if (!req) |
305 | return NULL; | 288 | return -ENOMEM; |
306 | 289 | ||
307 | req->buf = tipc_disc_init_msg(DSC_REQ_MSG, dest_domain, b_ptr); | 290 | req->buf = tipc_disc_init_msg(DSC_REQ_MSG, dest_domain, b_ptr); |
308 | if (!req->buf) { | 291 | if (!req->buf) { |
309 | kfree(req); | 292 | kfree(req); |
310 | return NULL; | 293 | return -ENOMSG; |
311 | } | 294 | } |
312 | 295 | ||
313 | memcpy(&req->dest, dest, sizeof(*dest)); | 296 | memcpy(&req->dest, dest, sizeof(*dest)); |
@@ -316,6 +299,20 @@ struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr, | |||
316 | req->timer_intv = TIPC_LINK_REQ_INIT; | 299 | req->timer_intv = TIPC_LINK_REQ_INIT; |
317 | k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); | 300 | k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); |
318 | k_start_timer(&req->timer, req->timer_intv); | 301 | k_start_timer(&req->timer, req->timer_intv); |
319 | return req; | 302 | b_ptr->link_req = req; |
303 | return 0; | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * tipc_disc_delete - destroy object sending periodic link setup requests | ||
308 | * @req: ptr to link request structure | ||
309 | */ | ||
310 | |||
311 | void tipc_disc_delete(struct link_req *req) | ||
312 | { | ||
313 | k_cancel_timer(&req->timer); | ||
314 | k_term_timer(&req->timer); | ||
315 | buf_discard(req->buf); | ||
316 | kfree(req); | ||
320 | } | 317 | } |
321 | 318 | ||
diff --git a/net/tipc/discover.h b/net/tipc/discover.h index e48a167e47b2..d6e44e3dcdbc 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h | |||
@@ -39,12 +39,10 @@ | |||
39 | 39 | ||
40 | struct link_req; | 40 | struct link_req; |
41 | 41 | ||
42 | struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr, | 42 | int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest, |
43 | const struct tipc_media_addr *dest, | 43 | u32 dest_domain); |
44 | u32 dest_domain); | 44 | void tipc_disc_delete(struct link_req *req); |
45 | void tipc_disc_update_link_req(struct link_req *req); | 45 | void tipc_disc_update_link_req(struct link_req *req); |
46 | void tipc_disc_stop_link_req(struct link_req *req); | ||
47 | |||
48 | void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr); | 46 | void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr); |
49 | 47 | ||
50 | #endif | 48 | #endif |