diff options
Diffstat (limited to 'net/tipc/bearer.c')
| -rw-r--r-- | net/tipc/bearer.c | 153 |
1 files changed, 70 insertions, 83 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 3fef7eb776dc..264474394f9f 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
| @@ -49,7 +49,7 @@ static struct tipc_media * const media_info_array[] = { | |||
| 49 | NULL | 49 | NULL |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | struct tipc_bearer *bearer_list[MAX_BEARERS + 1]; | 52 | struct tipc_bearer __rcu *bearer_list[MAX_BEARERS + 1]; |
| 53 | 53 | ||
| 54 | static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down); | 54 | static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down); |
| 55 | 55 | ||
| @@ -178,7 +178,7 @@ struct tipc_bearer *tipc_bearer_find(const char *name) | |||
| 178 | u32 i; | 178 | u32 i; |
| 179 | 179 | ||
| 180 | for (i = 0; i < MAX_BEARERS; i++) { | 180 | for (i = 0; i < MAX_BEARERS; i++) { |
| 181 | b_ptr = bearer_list[i]; | 181 | b_ptr = rtnl_dereference(bearer_list[i]); |
| 182 | if (b_ptr && (!strcmp(b_ptr->name, name))) | 182 | if (b_ptr && (!strcmp(b_ptr->name, name))) |
| 183 | return b_ptr; | 183 | return b_ptr; |
| 184 | } | 184 | } |
| @@ -198,10 +198,9 @@ struct sk_buff *tipc_bearer_get_names(void) | |||
| 198 | if (!buf) | 198 | if (!buf) |
| 199 | return NULL; | 199 | return NULL; |
| 200 | 200 | ||
| 201 | read_lock_bh(&tipc_net_lock); | ||
| 202 | for (i = 0; media_info_array[i] != NULL; i++) { | 201 | for (i = 0; media_info_array[i] != NULL; i++) { |
| 203 | for (j = 0; j < MAX_BEARERS; j++) { | 202 | for (j = 0; j < MAX_BEARERS; j++) { |
| 204 | b = bearer_list[j]; | 203 | b = rtnl_dereference(bearer_list[j]); |
| 205 | if (!b) | 204 | if (!b) |
| 206 | continue; | 205 | continue; |
| 207 | if (b->media == media_info_array[i]) { | 206 | if (b->media == media_info_array[i]) { |
| @@ -211,22 +210,33 @@ struct sk_buff *tipc_bearer_get_names(void) | |||
| 211 | } | 210 | } |
| 212 | } | 211 | } |
| 213 | } | 212 | } |
| 214 | read_unlock_bh(&tipc_net_lock); | ||
| 215 | return buf; | 213 | return buf; |
| 216 | } | 214 | } |
| 217 | 215 | ||
| 218 | void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest) | 216 | void tipc_bearer_add_dest(u32 bearer_id, u32 dest) |
| 219 | { | 217 | { |
| 220 | tipc_nmap_add(&b_ptr->nodes, dest); | 218 | struct tipc_bearer *b_ptr; |
| 221 | tipc_bcbearer_sort(); | 219 | |
| 222 | tipc_disc_add_dest(b_ptr->link_req); | 220 | rcu_read_lock(); |
| 221 | b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]); | ||
| 222 | if (b_ptr) { | ||
| 223 | tipc_bcbearer_sort(&b_ptr->nodes, dest, true); | ||
| 224 | tipc_disc_add_dest(b_ptr->link_req); | ||
| 225 | } | ||
| 226 | rcu_read_unlock(); | ||
| 223 | } | 227 | } |
| 224 | 228 | ||
| 225 | void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest) | 229 | void tipc_bearer_remove_dest(u32 bearer_id, u32 dest) |
| 226 | { | 230 | { |
| 227 | tipc_nmap_remove(&b_ptr->nodes, dest); | 231 | struct tipc_bearer *b_ptr; |
| 228 | tipc_bcbearer_sort(); | 232 | |
| 229 | tipc_disc_remove_dest(b_ptr->link_req); | 233 | rcu_read_lock(); |
| 234 | b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]); | ||
| 235 | if (b_ptr) { | ||
| 236 | tipc_bcbearer_sort(&b_ptr->nodes, dest, false); | ||
| 237 | tipc_disc_remove_dest(b_ptr->link_req); | ||
| 238 | } | ||
| 239 | rcu_read_unlock(); | ||
| 230 | } | 240 | } |
| 231 | 241 | ||
| 232 | /** | 242 | /** |
| @@ -271,13 +281,11 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) | |||
| 271 | return -EINVAL; | 281 | return -EINVAL; |
| 272 | } | 282 | } |
| 273 | 283 | ||
| 274 | write_lock_bh(&tipc_net_lock); | ||
| 275 | |||
| 276 | m_ptr = tipc_media_find(b_names.media_name); | 284 | m_ptr = tipc_media_find(b_names.media_name); |
| 277 | if (!m_ptr) { | 285 | if (!m_ptr) { |
| 278 | pr_warn("Bearer <%s> rejected, media <%s> not registered\n", | 286 | pr_warn("Bearer <%s> rejected, media <%s> not registered\n", |
| 279 | name, b_names.media_name); | 287 | name, b_names.media_name); |
| 280 | goto exit; | 288 | return -EINVAL; |
| 281 | } | 289 | } |
| 282 | 290 | ||
| 283 | if (priority == TIPC_MEDIA_LINK_PRI) | 291 | if (priority == TIPC_MEDIA_LINK_PRI) |
| @@ -287,7 +295,7 @@ restart: | |||
| 287 | bearer_id = MAX_BEARERS; | 295 | bearer_id = MAX_BEARERS; |
| 288 | with_this_prio = 1; | 296 | with_this_prio = 1; |
| 289 | for (i = MAX_BEARERS; i-- != 0; ) { | 297 | for (i = MAX_BEARERS; i-- != 0; ) { |
| 290 | b_ptr = bearer_list[i]; | 298 | b_ptr = rtnl_dereference(bearer_list[i]); |
| 291 | if (!b_ptr) { | 299 | if (!b_ptr) { |
| 292 | bearer_id = i; | 300 | bearer_id = i; |
| 293 | continue; | 301 | continue; |
| @@ -295,14 +303,14 @@ restart: | |||
| 295 | if (!strcmp(name, b_ptr->name)) { | 303 | if (!strcmp(name, b_ptr->name)) { |
| 296 | pr_warn("Bearer <%s> rejected, already enabled\n", | 304 | pr_warn("Bearer <%s> rejected, already enabled\n", |
| 297 | name); | 305 | name); |
| 298 | goto exit; | 306 | return -EINVAL; |
| 299 | } | 307 | } |
| 300 | if ((b_ptr->priority == priority) && | 308 | if ((b_ptr->priority == priority) && |
| 301 | (++with_this_prio > 2)) { | 309 | (++with_this_prio > 2)) { |
| 302 | if (priority-- == 0) { | 310 | if (priority-- == 0) { |
| 303 | pr_warn("Bearer <%s> rejected, duplicate priority\n", | 311 | pr_warn("Bearer <%s> rejected, duplicate priority\n", |
| 304 | name); | 312 | name); |
| 305 | goto exit; | 313 | return -EINVAL; |
| 306 | } | 314 | } |
| 307 | pr_warn("Bearer <%s> priority adjustment required %u->%u\n", | 315 | pr_warn("Bearer <%s> priority adjustment required %u->%u\n", |
| 308 | name, priority + 1, priority); | 316 | name, priority + 1, priority); |
| @@ -312,21 +320,20 @@ restart: | |||
| 312 | if (bearer_id >= MAX_BEARERS) { | 320 | if (bearer_id >= MAX_BEARERS) { |
| 313 | pr_warn("Bearer <%s> rejected, bearer limit reached (%u)\n", | 321 | pr_warn("Bearer <%s> rejected, bearer limit reached (%u)\n", |
| 314 | name, MAX_BEARERS); | 322 | name, MAX_BEARERS); |
| 315 | goto exit; | 323 | return -EINVAL; |
| 316 | } | 324 | } |
| 317 | 325 | ||
| 318 | b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC); | 326 | b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC); |
| 319 | if (!b_ptr) { | 327 | if (!b_ptr) |
| 320 | res = -ENOMEM; | 328 | return -ENOMEM; |
| 321 | goto exit; | 329 | |
| 322 | } | ||
| 323 | strcpy(b_ptr->name, name); | 330 | strcpy(b_ptr->name, name); |
| 324 | b_ptr->media = m_ptr; | 331 | b_ptr->media = m_ptr; |
| 325 | res = m_ptr->enable_media(b_ptr); | 332 | res = m_ptr->enable_media(b_ptr); |
| 326 | if (res) { | 333 | if (res) { |
| 327 | pr_warn("Bearer <%s> rejected, enable failure (%d)\n", | 334 | pr_warn("Bearer <%s> rejected, enable failure (%d)\n", |
| 328 | name, -res); | 335 | name, -res); |
| 329 | goto exit; | 336 | return -EINVAL; |
| 330 | } | 337 | } |
| 331 | 338 | ||
| 332 | b_ptr->identity = bearer_id; | 339 | b_ptr->identity = bearer_id; |
| @@ -341,16 +348,14 @@ restart: | |||
| 341 | bearer_disable(b_ptr, false); | 348 | bearer_disable(b_ptr, false); |
| 342 | pr_warn("Bearer <%s> rejected, discovery object creation failed\n", | 349 | pr_warn("Bearer <%s> rejected, discovery object creation failed\n", |
| 343 | name); | 350 | name); |
| 344 | goto exit; | 351 | return -EINVAL; |
| 345 | } | 352 | } |
| 346 | 353 | ||
| 347 | bearer_list[bearer_id] = b_ptr; | 354 | rcu_assign_pointer(bearer_list[bearer_id], b_ptr); |
| 348 | 355 | ||
| 349 | pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", | 356 | pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", |
| 350 | name, | 357 | name, |
| 351 | tipc_addr_string_fill(addr_string, disc_domain), priority); | 358 | tipc_addr_string_fill(addr_string, disc_domain), priority); |
| 352 | exit: | ||
| 353 | write_unlock_bh(&tipc_net_lock); | ||
| 354 | return res; | 359 | return res; |
| 355 | } | 360 | } |
| 356 | 361 | ||
| @@ -359,19 +364,16 @@ exit: | |||
| 359 | */ | 364 | */ |
| 360 | static int tipc_reset_bearer(struct tipc_bearer *b_ptr) | 365 | static int tipc_reset_bearer(struct tipc_bearer *b_ptr) |
| 361 | { | 366 | { |
| 362 | read_lock_bh(&tipc_net_lock); | ||
| 363 | pr_info("Resetting bearer <%s>\n", b_ptr->name); | 367 | pr_info("Resetting bearer <%s>\n", b_ptr->name); |
| 364 | tipc_disc_delete(b_ptr->link_req); | ||
| 365 | tipc_link_reset_list(b_ptr->identity); | 368 | tipc_link_reset_list(b_ptr->identity); |
| 366 | tipc_disc_create(b_ptr, &b_ptr->bcast_addr); | 369 | tipc_disc_reset(b_ptr); |
| 367 | read_unlock_bh(&tipc_net_lock); | ||
| 368 | return 0; | 370 | return 0; |
| 369 | } | 371 | } |
| 370 | 372 | ||
| 371 | /** | 373 | /** |
| 372 | * bearer_disable | 374 | * bearer_disable |
| 373 | * | 375 | * |
| 374 | * Note: This routine assumes caller holds tipc_net_lock. | 376 | * Note: This routine assumes caller holds RTNL lock. |
| 375 | */ | 377 | */ |
| 376 | static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down) | 378 | static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down) |
| 377 | { | 379 | { |
| @@ -385,12 +387,12 @@ static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down) | |||
| 385 | tipc_disc_delete(b_ptr->link_req); | 387 | tipc_disc_delete(b_ptr->link_req); |
| 386 | 388 | ||
| 387 | for (i = 0; i < MAX_BEARERS; i++) { | 389 | for (i = 0; i < MAX_BEARERS; i++) { |
| 388 | if (b_ptr == bearer_list[i]) { | 390 | if (b_ptr == rtnl_dereference(bearer_list[i])) { |
| 389 | bearer_list[i] = NULL; | 391 | RCU_INIT_POINTER(bearer_list[i], NULL); |
| 390 | break; | 392 | break; |
| 391 | } | 393 | } |
| 392 | } | 394 | } |
| 393 | kfree(b_ptr); | 395 | kfree_rcu(b_ptr, rcu); |
| 394 | } | 396 | } |
| 395 | 397 | ||
| 396 | int tipc_disable_bearer(const char *name) | 398 | int tipc_disable_bearer(const char *name) |
| @@ -398,7 +400,6 @@ int tipc_disable_bearer(const char *name) | |||
| 398 | struct tipc_bearer *b_ptr; | 400 | struct tipc_bearer *b_ptr; |
| 399 | int res; | 401 | int res; |
| 400 | 402 | ||
| 401 | write_lock_bh(&tipc_net_lock); | ||
| 402 | b_ptr = tipc_bearer_find(name); | 403 | b_ptr = tipc_bearer_find(name); |
| 403 | if (b_ptr == NULL) { | 404 | if (b_ptr == NULL) { |
| 404 | pr_warn("Attempt to disable unknown bearer <%s>\n", name); | 405 | pr_warn("Attempt to disable unknown bearer <%s>\n", name); |
| @@ -407,32 +408,9 @@ int tipc_disable_bearer(const char *name) | |||
| 407 | bearer_disable(b_ptr, false); | 408 | bearer_disable(b_ptr, false); |
| 408 | res = 0; | 409 | res = 0; |
| 409 | } | 410 | } |
| 410 | write_unlock_bh(&tipc_net_lock); | ||
| 411 | return res; | 411 | return res; |
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | |||
| 415 | /* tipc_l2_media_addr_set - initialize Ethernet media address structure | ||
| 416 | * | ||
| 417 | * Media-dependent "value" field stores MAC address in first 6 bytes | ||
| 418 | * and zeroes out the remaining bytes. | ||
| 419 | */ | ||
| 420 | void tipc_l2_media_addr_set(const struct tipc_bearer *b, | ||
| 421 | struct tipc_media_addr *a, char *mac) | ||
| 422 | { | ||
| 423 | int len = b->media->hwaddr_len; | ||
| 424 | |||
| 425 | if (unlikely(sizeof(a->value) < len)) { | ||
| 426 | WARN_ONCE(1, "Media length invalid\n"); | ||
| 427 | return; | ||
| 428 | } | ||
| 429 | |||
| 430 | memcpy(a->value, mac, len); | ||
| 431 | memset(a->value + len, 0, sizeof(a->value) - len); | ||
| 432 | a->media_id = b->media->type_id; | ||
| 433 | a->broadcast = !memcmp(mac, b->bcast_addr.value, len); | ||
| 434 | } | ||
| 435 | |||
| 436 | int tipc_enable_l2_media(struct tipc_bearer *b) | 414 | int tipc_enable_l2_media(struct tipc_bearer *b) |
| 437 | { | 415 | { |
| 438 | struct net_device *dev; | 416 | struct net_device *dev; |
| @@ -443,33 +421,37 @@ int tipc_enable_l2_media(struct tipc_bearer *b) | |||
| 443 | if (!dev) | 421 | if (!dev) |
| 444 | return -ENODEV; | 422 | return -ENODEV; |
| 445 | 423 | ||
| 446 | /* Associate TIPC bearer with Ethernet bearer */ | 424 | /* Associate TIPC bearer with L2 bearer */ |
| 447 | b->media_ptr = dev; | 425 | rcu_assign_pointer(b->media_ptr, dev); |
| 448 | memset(b->bcast_addr.value, 0, sizeof(b->bcast_addr.value)); | 426 | memset(&b->bcast_addr, 0, sizeof(b->bcast_addr)); |
| 449 | memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len); | 427 | memcpy(b->bcast_addr.value, dev->broadcast, b->media->hwaddr_len); |
| 450 | b->bcast_addr.media_id = b->media->type_id; | 428 | b->bcast_addr.media_id = b->media->type_id; |
| 451 | b->bcast_addr.broadcast = 1; | 429 | b->bcast_addr.broadcast = 1; |
| 452 | b->mtu = dev->mtu; | 430 | b->mtu = dev->mtu; |
| 453 | tipc_l2_media_addr_set(b, &b->addr, (char *)dev->dev_addr); | 431 | b->media->raw2addr(b, &b->addr, (char *)dev->dev_addr); |
| 454 | rcu_assign_pointer(dev->tipc_ptr, b); | 432 | rcu_assign_pointer(dev->tipc_ptr, b); |
| 455 | return 0; | 433 | return 0; |
| 456 | } | 434 | } |
| 457 | 435 | ||
| 458 | /* tipc_disable_l2_media - detach TIPC bearer from an Ethernet interface | 436 | /* tipc_disable_l2_media - detach TIPC bearer from an L2 interface |
| 459 | * | 437 | * |
| 460 | * Mark Ethernet bearer as inactive so that incoming buffers are thrown away, | 438 | * Mark L2 bearer as inactive so that incoming buffers are thrown away, |
| 461 | * then get worker thread to complete bearer cleanup. (Can't do cleanup | 439 | * then get worker thread to complete bearer cleanup. (Can't do cleanup |
| 462 | * here because cleanup code needs to sleep and caller holds spinlocks.) | 440 | * here because cleanup code needs to sleep and caller holds spinlocks.) |
| 463 | */ | 441 | */ |
| 464 | void tipc_disable_l2_media(struct tipc_bearer *b) | 442 | void tipc_disable_l2_media(struct tipc_bearer *b) |
| 465 | { | 443 | { |
| 466 | struct net_device *dev = (struct net_device *)b->media_ptr; | 444 | struct net_device *dev; |
| 445 | |||
| 446 | dev = (struct net_device *)rtnl_dereference(b->media_ptr); | ||
| 447 | RCU_INIT_POINTER(b->media_ptr, NULL); | ||
| 467 | RCU_INIT_POINTER(dev->tipc_ptr, NULL); | 448 | RCU_INIT_POINTER(dev->tipc_ptr, NULL); |
| 449 | synchronize_net(); | ||
| 468 | dev_put(dev); | 450 | dev_put(dev); |
| 469 | } | 451 | } |
| 470 | 452 | ||
| 471 | /** | 453 | /** |
| 472 | * tipc_l2_send_msg - send a TIPC packet out over an Ethernet interface | 454 | * tipc_l2_send_msg - send a TIPC packet out over an L2 interface |
| 473 | * @buf: the packet to be sent | 455 | * @buf: the packet to be sent |
| 474 | * @b_ptr: the bearer through which the packet is to be sent | 456 | * @b_ptr: the bearer through which the packet is to be sent |
| 475 | * @dest: peer destination address | 457 | * @dest: peer destination address |
| @@ -478,8 +460,12 @@ int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b, | |||
| 478 | struct tipc_media_addr *dest) | 460 | struct tipc_media_addr *dest) |
| 479 | { | 461 | { |
| 480 | struct sk_buff *clone; | 462 | struct sk_buff *clone; |
| 463 | struct net_device *dev; | ||
| 481 | int delta; | 464 | int delta; |
| 482 | struct net_device *dev = (struct net_device *)b->media_ptr; | 465 | |
| 466 | dev = (struct net_device *)rcu_dereference_rtnl(b->media_ptr); | ||
| 467 | if (!dev) | ||
| 468 | return 0; | ||
| 483 | 469 | ||
| 484 | clone = skb_clone(buf, GFP_ATOMIC); | 470 | clone = skb_clone(buf, GFP_ATOMIC); |
| 485 | if (!clone) | 471 | if (!clone) |
| @@ -507,10 +493,16 @@ int tipc_l2_send_msg(struct sk_buff *buf, struct tipc_bearer *b, | |||
| 507 | * The media send routine must not alter the buffer being passed in | 493 | * The media send routine must not alter the buffer being passed in |
| 508 | * as it may be needed for later retransmission! | 494 | * as it may be needed for later retransmission! |
| 509 | */ | 495 | */ |
| 510 | void tipc_bearer_send(struct tipc_bearer *b, struct sk_buff *buf, | 496 | void tipc_bearer_send(u32 bearer_id, struct sk_buff *buf, |
| 511 | struct tipc_media_addr *dest) | 497 | struct tipc_media_addr *dest) |
| 512 | { | 498 | { |
| 513 | b->media->send_msg(buf, b, dest); | 499 | struct tipc_bearer *b_ptr; |
| 500 | |||
| 501 | rcu_read_lock(); | ||
| 502 | b_ptr = rcu_dereference_rtnl(bearer_list[bearer_id]); | ||
| 503 | if (likely(b_ptr)) | ||
| 504 | b_ptr->media->send_msg(buf, b_ptr, dest); | ||
| 505 | rcu_read_unlock(); | ||
| 514 | } | 506 | } |
| 515 | 507 | ||
| 516 | /** | 508 | /** |
| @@ -535,7 +527,7 @@ static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev, | |||
| 535 | } | 527 | } |
| 536 | 528 | ||
| 537 | rcu_read_lock(); | 529 | rcu_read_lock(); |
| 538 | b_ptr = rcu_dereference(dev->tipc_ptr); | 530 | b_ptr = rcu_dereference_rtnl(dev->tipc_ptr); |
| 539 | if (likely(b_ptr)) { | 531 | if (likely(b_ptr)) { |
| 540 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { | 532 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { |
| 541 | buf->next = NULL; | 533 | buf->next = NULL; |
| @@ -568,12 +560,9 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, | |||
| 568 | if (!net_eq(dev_net(dev), &init_net)) | 560 | if (!net_eq(dev_net(dev), &init_net)) |
| 569 | return NOTIFY_DONE; | 561 | return NOTIFY_DONE; |
| 570 | 562 | ||
| 571 | rcu_read_lock(); | 563 | b_ptr = rtnl_dereference(dev->tipc_ptr); |
| 572 | b_ptr = rcu_dereference(dev->tipc_ptr); | 564 | if (!b_ptr) |
| 573 | if (!b_ptr) { | ||
| 574 | rcu_read_unlock(); | ||
| 575 | return NOTIFY_DONE; | 565 | return NOTIFY_DONE; |
| 576 | } | ||
| 577 | 566 | ||
| 578 | b_ptr->mtu = dev->mtu; | 567 | b_ptr->mtu = dev->mtu; |
| 579 | 568 | ||
| @@ -586,17 +575,15 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, | |||
| 586 | tipc_reset_bearer(b_ptr); | 575 | tipc_reset_bearer(b_ptr); |
| 587 | break; | 576 | break; |
| 588 | case NETDEV_CHANGEADDR: | 577 | case NETDEV_CHANGEADDR: |
| 589 | tipc_l2_media_addr_set(b_ptr, &b_ptr->addr, | 578 | b_ptr->media->raw2addr(b_ptr, &b_ptr->addr, |
| 590 | (char *)dev->dev_addr); | 579 | (char *)dev->dev_addr); |
| 591 | tipc_reset_bearer(b_ptr); | 580 | tipc_reset_bearer(b_ptr); |
| 592 | break; | 581 | break; |
| 593 | case NETDEV_UNREGISTER: | 582 | case NETDEV_UNREGISTER: |
| 594 | case NETDEV_CHANGENAME: | 583 | case NETDEV_CHANGENAME: |
| 595 | tipc_disable_bearer(b_ptr->name); | 584 | bearer_disable(b_ptr, false); |
| 596 | break; | 585 | break; |
| 597 | } | 586 | } |
| 598 | rcu_read_unlock(); | ||
| 599 | |||
| 600 | return NOTIFY_OK; | 587 | return NOTIFY_OK; |
| 601 | } | 588 | } |
| 602 | 589 | ||
| @@ -633,7 +620,7 @@ void tipc_bearer_stop(void) | |||
| 633 | u32 i; | 620 | u32 i; |
| 634 | 621 | ||
| 635 | for (i = 0; i < MAX_BEARERS; i++) { | 622 | for (i = 0; i < MAX_BEARERS; i++) { |
| 636 | b_ptr = bearer_list[i]; | 623 | b_ptr = rtnl_dereference(bearer_list[i]); |
| 637 | if (b_ptr) { | 624 | if (b_ptr) { |
| 638 | bearer_disable(b_ptr, true); | 625 | bearer_disable(b_ptr, true); |
| 639 | bearer_list[i] = NULL; | 626 | bearer_list[i] = NULL; |
