diff options
Diffstat (limited to 'net/tipc/bearer.c')
| -rw-r--r-- | net/tipc/bearer.c | 96 |
1 files changed, 51 insertions, 45 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 574b86193b15..3fef7eb776dc 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
| @@ -49,9 +49,9 @@ static struct tipc_media * const media_info_array[] = { | |||
| 49 | NULL | 49 | NULL |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | struct tipc_bearer tipc_bearers[MAX_BEARERS]; | 52 | struct tipc_bearer *bearer_list[MAX_BEARERS + 1]; |
| 53 | 53 | ||
| 54 | static void bearer_disable(struct tipc_bearer *b_ptr); | 54 | static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down); |
| 55 | 55 | ||
| 56 | /** | 56 | /** |
| 57 | * tipc_media_find - locates specified media object by name | 57 | * tipc_media_find - locates specified media object by name |
| @@ -177,8 +177,9 @@ struct tipc_bearer *tipc_bearer_find(const char *name) | |||
| 177 | struct tipc_bearer *b_ptr; | 177 | struct tipc_bearer *b_ptr; |
| 178 | u32 i; | 178 | u32 i; |
| 179 | 179 | ||
| 180 | for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) { | 180 | for (i = 0; i < MAX_BEARERS; i++) { |
| 181 | if (b_ptr->active && (!strcmp(b_ptr->name, name))) | 181 | b_ptr = bearer_list[i]; |
| 182 | if (b_ptr && (!strcmp(b_ptr->name, name))) | ||
| 182 | return b_ptr; | 183 | return b_ptr; |
| 183 | } | 184 | } |
| 184 | return NULL; | 185 | return NULL; |
| @@ -200,8 +201,10 @@ struct sk_buff *tipc_bearer_get_names(void) | |||
| 200 | read_lock_bh(&tipc_net_lock); | 201 | read_lock_bh(&tipc_net_lock); |
| 201 | for (i = 0; media_info_array[i] != NULL; i++) { | 202 | for (i = 0; media_info_array[i] != NULL; i++) { |
| 202 | for (j = 0; j < MAX_BEARERS; j++) { | 203 | for (j = 0; j < MAX_BEARERS; j++) { |
| 203 | b = &tipc_bearers[j]; | 204 | b = bearer_list[j]; |
| 204 | if (b->active && (b->media == media_info_array[i])) { | 205 | if (!b) |
| 206 | continue; | ||
| 207 | if (b->media == media_info_array[i]) { | ||
| 205 | tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, | 208 | tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, |
| 206 | b->name, | 209 | b->name, |
| 207 | strlen(b->name) + 1); | 210 | strlen(b->name) + 1); |
| @@ -284,16 +287,17 @@ restart: | |||
| 284 | bearer_id = MAX_BEARERS; | 287 | bearer_id = MAX_BEARERS; |
| 285 | with_this_prio = 1; | 288 | with_this_prio = 1; |
| 286 | for (i = MAX_BEARERS; i-- != 0; ) { | 289 | for (i = MAX_BEARERS; i-- != 0; ) { |
| 287 | if (!tipc_bearers[i].active) { | 290 | b_ptr = bearer_list[i]; |
| 291 | if (!b_ptr) { | ||
| 288 | bearer_id = i; | 292 | bearer_id = i; |
| 289 | continue; | 293 | continue; |
| 290 | } | 294 | } |
| 291 | if (!strcmp(name, tipc_bearers[i].name)) { | 295 | if (!strcmp(name, b_ptr->name)) { |
| 292 | pr_warn("Bearer <%s> rejected, already enabled\n", | 296 | pr_warn("Bearer <%s> rejected, already enabled\n", |
| 293 | name); | 297 | name); |
| 294 | goto exit; | 298 | goto exit; |
| 295 | } | 299 | } |
| 296 | if ((tipc_bearers[i].priority == priority) && | 300 | if ((b_ptr->priority == priority) && |
| 297 | (++with_this_prio > 2)) { | 301 | (++with_this_prio > 2)) { |
| 298 | if (priority-- == 0) { | 302 | if (priority-- == 0) { |
| 299 | pr_warn("Bearer <%s> rejected, duplicate priority\n", | 303 | pr_warn("Bearer <%s> rejected, duplicate priority\n", |
| @@ -311,7 +315,11 @@ restart: | |||
| 311 | goto exit; | 315 | goto exit; |
| 312 | } | 316 | } |
| 313 | 317 | ||
| 314 | b_ptr = &tipc_bearers[bearer_id]; | 318 | b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC); |
| 319 | if (!b_ptr) { | ||
| 320 | res = -ENOMEM; | ||
| 321 | goto exit; | ||
| 322 | } | ||
| 315 | strcpy(b_ptr->name, name); | 323 | strcpy(b_ptr->name, name); |
| 316 | b_ptr->media = m_ptr; | 324 | b_ptr->media = m_ptr; |
| 317 | res = m_ptr->enable_media(b_ptr); | 325 | res = m_ptr->enable_media(b_ptr); |
| @@ -324,19 +332,20 @@ restart: | |||
| 324 | b_ptr->identity = bearer_id; | 332 | b_ptr->identity = bearer_id; |
| 325 | b_ptr->tolerance = m_ptr->tolerance; | 333 | b_ptr->tolerance = m_ptr->tolerance; |
| 326 | b_ptr->window = m_ptr->window; | 334 | b_ptr->window = m_ptr->window; |
| 335 | b_ptr->domain = disc_domain; | ||
| 327 | b_ptr->net_plane = bearer_id + 'A'; | 336 | b_ptr->net_plane = bearer_id + 'A'; |
| 328 | b_ptr->active = 1; | ||
| 329 | b_ptr->priority = priority; | 337 | b_ptr->priority = priority; |
| 330 | INIT_LIST_HEAD(&b_ptr->links); | ||
| 331 | spin_lock_init(&b_ptr->lock); | ||
| 332 | 338 | ||
| 333 | res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr, disc_domain); | 339 | res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr); |
| 334 | if (res) { | 340 | if (res) { |
| 335 | bearer_disable(b_ptr); | 341 | bearer_disable(b_ptr, false); |
| 336 | pr_warn("Bearer <%s> rejected, discovery object creation failed\n", | 342 | pr_warn("Bearer <%s> rejected, discovery object creation failed\n", |
| 337 | name); | 343 | name); |
| 338 | goto exit; | 344 | goto exit; |
| 339 | } | 345 | } |
| 346 | |||
| 347 | bearer_list[bearer_id] = b_ptr; | ||
| 348 | |||
| 340 | pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", | 349 | pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", |
| 341 | name, | 350 | name, |
| 342 | tipc_addr_string_fill(addr_string, disc_domain), priority); | 351 | tipc_addr_string_fill(addr_string, disc_domain), priority); |
| @@ -350,20 +359,11 @@ exit: | |||
| 350 | */ | 359 | */ |
| 351 | static int tipc_reset_bearer(struct tipc_bearer *b_ptr) | 360 | static int tipc_reset_bearer(struct tipc_bearer *b_ptr) |
| 352 | { | 361 | { |
| 353 | struct tipc_link *l_ptr; | ||
| 354 | struct tipc_link *temp_l_ptr; | ||
| 355 | |||
| 356 | read_lock_bh(&tipc_net_lock); | 362 | read_lock_bh(&tipc_net_lock); |
| 357 | pr_info("Resetting bearer <%s>\n", b_ptr->name); | 363 | pr_info("Resetting bearer <%s>\n", b_ptr->name); |
| 358 | spin_lock_bh(&b_ptr->lock); | 364 | tipc_disc_delete(b_ptr->link_req); |
| 359 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 365 | tipc_link_reset_list(b_ptr->identity); |
| 360 | struct tipc_node *n_ptr = l_ptr->owner; | 366 | tipc_disc_create(b_ptr, &b_ptr->bcast_addr); |
| 361 | |||
| 362 | spin_lock_bh(&n_ptr->lock); | ||
| 363 | tipc_link_reset(l_ptr); | ||
| 364 | spin_unlock_bh(&n_ptr->lock); | ||
| 365 | } | ||
| 366 | spin_unlock_bh(&b_ptr->lock); | ||
| 367 | read_unlock_bh(&tipc_net_lock); | 367 | read_unlock_bh(&tipc_net_lock); |
| 368 | return 0; | 368 | return 0; |
| 369 | } | 369 | } |
| @@ -373,26 +373,24 @@ static int tipc_reset_bearer(struct tipc_bearer *b_ptr) | |||
| 373 | * | 373 | * |
| 374 | * Note: This routine assumes caller holds tipc_net_lock. | 374 | * Note: This routine assumes caller holds tipc_net_lock. |
| 375 | */ | 375 | */ |
| 376 | static void bearer_disable(struct tipc_bearer *b_ptr) | 376 | static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down) |
| 377 | { | 377 | { |
| 378 | struct tipc_link *l_ptr; | 378 | u32 i; |
| 379 | struct tipc_link *temp_l_ptr; | ||
| 380 | struct tipc_link_req *temp_req; | ||
| 381 | 379 | ||
| 382 | pr_info("Disabling bearer <%s>\n", b_ptr->name); | 380 | pr_info("Disabling bearer <%s>\n", b_ptr->name); |
| 383 | spin_lock_bh(&b_ptr->lock); | ||
| 384 | b_ptr->media->disable_media(b_ptr); | 381 | b_ptr->media->disable_media(b_ptr); |
| 385 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | ||
| 386 | tipc_link_delete(l_ptr); | ||
| 387 | } | ||
| 388 | temp_req = b_ptr->link_req; | ||
| 389 | b_ptr->link_req = NULL; | ||
| 390 | spin_unlock_bh(&b_ptr->lock); | ||
| 391 | 382 | ||
| 392 | if (temp_req) | 383 | tipc_link_delete_list(b_ptr->identity, shutting_down); |
| 393 | tipc_disc_delete(temp_req); | 384 | if (b_ptr->link_req) |
| 385 | tipc_disc_delete(b_ptr->link_req); | ||
| 394 | 386 | ||
| 395 | memset(b_ptr, 0, sizeof(struct tipc_bearer)); | 387 | for (i = 0; i < MAX_BEARERS; i++) { |
| 388 | if (b_ptr == bearer_list[i]) { | ||
| 389 | bearer_list[i] = NULL; | ||
| 390 | break; | ||
| 391 | } | ||
| 392 | } | ||
| 393 | kfree(b_ptr); | ||
| 396 | } | 394 | } |
| 397 | 395 | ||
| 398 | int tipc_disable_bearer(const char *name) | 396 | int tipc_disable_bearer(const char *name) |
| @@ -406,7 +404,7 @@ int tipc_disable_bearer(const char *name) | |||
| 406 | pr_warn("Attempt to disable unknown bearer <%s>\n", name); | 404 | pr_warn("Attempt to disable unknown bearer <%s>\n", name); |
| 407 | res = -EINVAL; | 405 | res = -EINVAL; |
| 408 | } else { | 406 | } else { |
| 409 | bearer_disable(b_ptr); | 407 | bearer_disable(b_ptr, false); |
| 410 | res = 0; | 408 | res = 0; |
| 411 | } | 409 | } |
| 412 | write_unlock_bh(&tipc_net_lock); | 410 | write_unlock_bh(&tipc_net_lock); |
| @@ -585,7 +583,11 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, | |||
| 585 | break; | 583 | break; |
| 586 | case NETDEV_DOWN: | 584 | case NETDEV_DOWN: |
| 587 | case NETDEV_CHANGEMTU: | 585 | case NETDEV_CHANGEMTU: |
| 586 | tipc_reset_bearer(b_ptr); | ||
| 587 | break; | ||
| 588 | case NETDEV_CHANGEADDR: | 588 | case NETDEV_CHANGEADDR: |
| 589 | tipc_l2_media_addr_set(b_ptr, &b_ptr->addr, | ||
| 590 | (char *)dev->dev_addr); | ||
| 589 | tipc_reset_bearer(b_ptr); | 591 | tipc_reset_bearer(b_ptr); |
| 590 | break; | 592 | break; |
| 591 | case NETDEV_UNREGISTER: | 593 | case NETDEV_UNREGISTER: |
| @@ -599,7 +601,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, | |||
| 599 | } | 601 | } |
| 600 | 602 | ||
| 601 | static struct packet_type tipc_packet_type __read_mostly = { | 603 | static struct packet_type tipc_packet_type __read_mostly = { |
| 602 | .type = __constant_htons(ETH_P_TIPC), | 604 | .type = htons(ETH_P_TIPC), |
| 603 | .func = tipc_l2_rcv_msg, | 605 | .func = tipc_l2_rcv_msg, |
| 604 | }; | 606 | }; |
| 605 | 607 | ||
| @@ -627,10 +629,14 @@ void tipc_bearer_cleanup(void) | |||
| 627 | 629 | ||
| 628 | void tipc_bearer_stop(void) | 630 | void tipc_bearer_stop(void) |
| 629 | { | 631 | { |
| 632 | struct tipc_bearer *b_ptr; | ||
| 630 | u32 i; | 633 | u32 i; |
| 631 | 634 | ||
| 632 | for (i = 0; i < MAX_BEARERS; i++) { | 635 | for (i = 0; i < MAX_BEARERS; i++) { |
| 633 | if (tipc_bearers[i].active) | 636 | b_ptr = bearer_list[i]; |
| 634 | bearer_disable(&tipc_bearers[i]); | 637 | if (b_ptr) { |
| 638 | bearer_disable(b_ptr, true); | ||
| 639 | bearer_list[i] = NULL; | ||
| 640 | } | ||
| 635 | } | 641 | } |
| 636 | } | 642 | } |
