diff options
Diffstat (limited to 'net/tipc/bearer.c')
| -rw-r--r-- | net/tipc/bearer.c | 110 |
1 files changed, 11 insertions, 99 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 4ec5c80e8a7c..aa62f93a9127 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
| @@ -279,116 +279,31 @@ void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest) | |||
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | /* | 281 | /* |
| 282 | * bearer_push(): Resolve bearer congestion. Force the waiting | 282 | * Interrupt enabling new requests after bearer blocking: |
| 283 | * links to push out their unsent packets, one packet per link | ||
| 284 | * per iteration, until all packets are gone or congestion reoccurs. | ||
| 285 | * 'tipc_net_lock' is read_locked when this function is called | ||
| 286 | * bearer.lock must be taken before calling | ||
| 287 | * Returns binary true(1) ore false(0) | ||
| 288 | */ | ||
| 289 | static int bearer_push(struct tipc_bearer *b_ptr) | ||
| 290 | { | ||
| 291 | u32 res = 0; | ||
| 292 | struct tipc_link *ln, *tln; | ||
| 293 | |||
| 294 | if (b_ptr->blocked) | ||
| 295 | return 0; | ||
| 296 | |||
| 297 | while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) { | ||
| 298 | list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) { | ||
| 299 | res = tipc_link_push_packet(ln); | ||
| 300 | if (res == PUSH_FAILED) | ||
| 301 | break; | ||
| 302 | if (res == PUSH_FINISHED) | ||
| 303 | list_move_tail(&ln->link_list, &b_ptr->links); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | return list_empty(&b_ptr->cong_links); | ||
| 307 | } | ||
| 308 | |||
| 309 | void tipc_bearer_lock_push(struct tipc_bearer *b_ptr) | ||
| 310 | { | ||
| 311 | spin_lock_bh(&b_ptr->lock); | ||
| 312 | bearer_push(b_ptr); | ||
| 313 | spin_unlock_bh(&b_ptr->lock); | ||
| 314 | } | ||
| 315 | |||
| 316 | |||
| 317 | /* | ||
| 318 | * Interrupt enabling new requests after bearer congestion or blocking: | ||
| 319 | * See bearer_send(). | 283 | * See bearer_send(). |
| 320 | */ | 284 | */ |
| 321 | void tipc_continue(struct tipc_bearer *b_ptr) | 285 | void tipc_continue(struct tipc_bearer *b) |
| 322 | { | 286 | { |
| 323 | spin_lock_bh(&b_ptr->lock); | 287 | spin_lock_bh(&b->lock); |
| 324 | if (!list_empty(&b_ptr->cong_links)) | 288 | b->blocked = 0; |
| 325 | tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr); | 289 | spin_unlock_bh(&b->lock); |
| 326 | b_ptr->blocked = 0; | ||
| 327 | spin_unlock_bh(&b_ptr->lock); | ||
| 328 | } | 290 | } |
| 329 | 291 | ||
| 330 | /* | 292 | /* |
| 331 | * Schedule link for sending of messages after the bearer | 293 | * tipc_bearer_blocked - determines if bearer is currently blocked |
| 332 | * has been deblocked by 'continue()'. This method is called | ||
| 333 | * when somebody tries to send a message via this link while | ||
| 334 | * the bearer is congested. 'tipc_net_lock' is in read_lock here | ||
| 335 | * bearer.lock is busy | ||
| 336 | */ | 294 | */ |
| 337 | static void tipc_bearer_schedule_unlocked(struct tipc_bearer *b_ptr, | 295 | int tipc_bearer_blocked(struct tipc_bearer *b) |
| 338 | struct tipc_link *l_ptr) | ||
| 339 | { | 296 | { |
| 340 | list_move_tail(&l_ptr->link_list, &b_ptr->cong_links); | 297 | int res; |
| 341 | } | ||
| 342 | |||
| 343 | /* | ||
| 344 | * Schedule link for sending of messages after the bearer | ||
| 345 | * has been deblocked by 'continue()'. This method is called | ||
| 346 | * when somebody tries to send a message via this link while | ||
| 347 | * the bearer is congested. 'tipc_net_lock' is in read_lock here, | ||
| 348 | * bearer.lock is free | ||
| 349 | */ | ||
| 350 | void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr) | ||
| 351 | { | ||
| 352 | spin_lock_bh(&b_ptr->lock); | ||
| 353 | tipc_bearer_schedule_unlocked(b_ptr, l_ptr); | ||
| 354 | spin_unlock_bh(&b_ptr->lock); | ||
| 355 | } | ||
| 356 | |||
| 357 | 298 | ||
| 358 | /* | 299 | spin_lock_bh(&b->lock); |
| 359 | * tipc_bearer_resolve_congestion(): Check if there is bearer congestion, | 300 | res = b->blocked; |
| 360 | * and if there is, try to resolve it before returning. | 301 | spin_unlock_bh(&b->lock); |
| 361 | * 'tipc_net_lock' is read_locked when this function is called | ||
| 362 | */ | ||
| 363 | int tipc_bearer_resolve_congestion(struct tipc_bearer *b_ptr, | ||
| 364 | struct tipc_link *l_ptr) | ||
| 365 | { | ||
| 366 | int res = 1; | ||
| 367 | 302 | ||
| 368 | if (list_empty(&b_ptr->cong_links)) | ||
| 369 | return 1; | ||
| 370 | spin_lock_bh(&b_ptr->lock); | ||
| 371 | if (!bearer_push(b_ptr)) { | ||
| 372 | tipc_bearer_schedule_unlocked(b_ptr, l_ptr); | ||
| 373 | res = 0; | ||
| 374 | } | ||
| 375 | spin_unlock_bh(&b_ptr->lock); | ||
| 376 | return res; | 303 | return res; |
| 377 | } | 304 | } |
| 378 | 305 | ||
| 379 | /** | 306 | /** |
| 380 | * tipc_bearer_congested - determines if bearer is currently congested | ||
| 381 | */ | ||
| 382 | int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr) | ||
| 383 | { | ||
| 384 | if (unlikely(b_ptr->blocked)) | ||
| 385 | return 1; | ||
| 386 | if (likely(list_empty(&b_ptr->cong_links))) | ||
| 387 | return 0; | ||
| 388 | return !tipc_bearer_resolve_congestion(b_ptr, l_ptr); | ||
| 389 | } | ||
| 390 | |||
| 391 | /** | ||
| 392 | * tipc_enable_bearer - enable bearer with the given name | 307 | * tipc_enable_bearer - enable bearer with the given name |
| 393 | */ | 308 | */ |
| 394 | int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) | 309 | int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) |
| @@ -489,7 +404,6 @@ restart: | |||
| 489 | b_ptr->net_plane = bearer_id + 'A'; | 404 | b_ptr->net_plane = bearer_id + 'A'; |
| 490 | b_ptr->active = 1; | 405 | b_ptr->active = 1; |
| 491 | b_ptr->priority = priority; | 406 | b_ptr->priority = priority; |
| 492 | INIT_LIST_HEAD(&b_ptr->cong_links); | ||
| 493 | INIT_LIST_HEAD(&b_ptr->links); | 407 | INIT_LIST_HEAD(&b_ptr->links); |
| 494 | spin_lock_init(&b_ptr->lock); | 408 | spin_lock_init(&b_ptr->lock); |
| 495 | 409 | ||
| @@ -528,7 +442,6 @@ int tipc_block_bearer(const char *name) | |||
| 528 | pr_info("Blocking bearer <%s>\n", name); | 442 | pr_info("Blocking bearer <%s>\n", name); |
| 529 | spin_lock_bh(&b_ptr->lock); | 443 | spin_lock_bh(&b_ptr->lock); |
| 530 | b_ptr->blocked = 1; | 444 | b_ptr->blocked = 1; |
| 531 | list_splice_init(&b_ptr->cong_links, &b_ptr->links); | ||
| 532 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 445 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { |
| 533 | struct tipc_node *n_ptr = l_ptr->owner; | 446 | struct tipc_node *n_ptr = l_ptr->owner; |
| 534 | 447 | ||
| @@ -555,7 +468,6 @@ static void bearer_disable(struct tipc_bearer *b_ptr) | |||
| 555 | spin_lock_bh(&b_ptr->lock); | 468 | spin_lock_bh(&b_ptr->lock); |
| 556 | b_ptr->blocked = 1; | 469 | b_ptr->blocked = 1; |
| 557 | b_ptr->media->disable_bearer(b_ptr); | 470 | b_ptr->media->disable_bearer(b_ptr); |
| 558 | list_splice_init(&b_ptr->cong_links, &b_ptr->links); | ||
| 559 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 471 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { |
| 560 | tipc_link_delete(l_ptr); | 472 | tipc_link_delete(l_ptr); |
| 561 | } | 473 | } |
