aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/llc/af_llc.c147
1 files changed, 67 insertions, 80 deletions
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index aed61e6376ed..436c8db67f55 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -426,12 +426,30 @@ static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
426 sk->sk_state = TCP_CLOSE; 426 sk->sk_state = TCP_CLOSE;
427 goto out; 427 goto out;
428 } 428 }
429 rc = llc_ui_wait_for_conn(sk, sk->sk_rcvtimeo); 429
430 if (rc) 430 if (sk->sk_state == TCP_SYN_SENT) {
431 dprintk("%s: llc_ui_wait_for_conn failed=%d\n", __FUNCTION__, rc); 431 const int timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
432
433 if (!timeo || !llc_ui_wait_for_conn(sk, timeo))
434 goto out;
435
436 rc = sock_intr_errno(timeo);
437 if (signal_pending(current))
438 goto out;
439 }
440
441 if (sk->sk_state == TCP_CLOSE)
442 goto sock_error;
443
444 sock->state = SS_CONNECTED;
445 rc = 0;
432out: 446out:
433 release_sock(sk); 447 release_sock(sk);
434 return rc; 448 return rc;
449sock_error:
450 rc = sock_error(sk) ? : -ECONNABORTED;
451 sock->state = SS_UNCONNECTED;
452 goto out;
435} 453}
436 454
437/** 455/**
@@ -472,117 +490,88 @@ out:
472 490
473static int llc_ui_wait_for_disc(struct sock *sk, int timeout) 491static int llc_ui_wait_for_disc(struct sock *sk, int timeout)
474{ 492{
475 DECLARE_WAITQUEUE(wait, current); 493 DEFINE_WAIT(wait);
476 int rc; 494 int rc = 0;
477 495
478 add_wait_queue_exclusive(sk->sk_sleep, &wait); 496 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
479 for (;;) { 497 while (sk->sk_state != TCP_CLOSE) {
480 __set_current_state(TASK_INTERRUPTIBLE); 498 release_sock(sk);
481 rc = 0; 499 timeout = schedule_timeout(timeout);
482 if (sk->sk_state != TCP_CLOSE) { 500 lock_sock(sk);
483 release_sock(sk);
484 timeout = schedule_timeout(timeout);
485 lock_sock(sk);
486 } else
487 break;
488 rc = -ERESTARTSYS; 501 rc = -ERESTARTSYS;
489 if (signal_pending(current)) 502 if (signal_pending(current))
490 break; 503 break;
491 rc = -EAGAIN; 504 rc = -EAGAIN;
492 if (!timeout) 505 if (!timeout)
493 break; 506 break;
507 rc = 0;
508 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
494 } 509 }
495 __set_current_state(TASK_RUNNING); 510 finish_wait(sk->sk_sleep, &wait);
496 remove_wait_queue(sk->sk_sleep, &wait);
497 return rc; 511 return rc;
498} 512}
499 513
500static int llc_ui_wait_for_conn(struct sock *sk, int timeout) 514static int llc_ui_wait_for_conn(struct sock *sk, int timeout)
501{ 515{
502 DECLARE_WAITQUEUE(wait, current); 516 DEFINE_WAIT(wait);
503 int rc;
504 517
505 add_wait_queue_exclusive(sk->sk_sleep, &wait); 518 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
506 for (;;) { 519
507 __set_current_state(TASK_INTERRUPTIBLE); 520 while (sk->sk_state == TCP_SYN_SENT) {
508 rc = -EAGAIN; 521 release_sock(sk);
509 if (sk->sk_state == TCP_CLOSE) 522 timeout = schedule_timeout(timeout);
510 break; 523 lock_sock(sk);
511 rc = 0; 524 if (signal_pending(current) || !timeout)
512 if (sk->sk_state != TCP_ESTABLISHED) {
513 release_sock(sk);
514 timeout = schedule_timeout(timeout);
515 lock_sock(sk);
516 } else
517 break;
518 rc = -ERESTARTSYS;
519 if (signal_pending(current))
520 break;
521 rc = -EAGAIN;
522 if (!timeout)
523 break; 525 break;
526 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
524 } 527 }
525 __set_current_state(TASK_RUNNING); 528 finish_wait(sk->sk_sleep, &wait);
526 remove_wait_queue(sk->sk_sleep, &wait); 529 return timeout;
527 return rc;
528} 530}
529 531
530static int llc_ui_wait_for_data(struct sock *sk, int timeout) 532static int llc_ui_wait_for_data(struct sock *sk, int timeout)
531{ 533{
532 DECLARE_WAITQUEUE(wait, current); 534 DEFINE_WAIT(wait);
533 int rc = 0; 535 int rc = 0;
534 536
535 add_wait_queue_exclusive(sk->sk_sleep, &wait);
536 for (;;) { 537 for (;;) {
537 __set_current_state(TASK_INTERRUPTIBLE); 538 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
538 if (sk->sk_shutdown & RCV_SHUTDOWN) 539 if (sk->sk_shutdown & RCV_SHUTDOWN)
539 break; 540 break;
540 /* 541 if (!skb_queue_empty(&sk->sk_receive_queue))
541 * Well, if we have backlog, try to process it now.
542 */
543 if (sk->sk_backlog.tail) {
544 release_sock(sk);
545 lock_sock(sk);
546 }
547 rc = 0;
548 if (skb_queue_empty(&sk->sk_receive_queue)) {
549 release_sock(sk);
550 timeout = schedule_timeout(timeout);
551 lock_sock(sk);
552 } else
553 break; 542 break;
543 release_sock(sk);
544 timeout = schedule_timeout(timeout);
545 lock_sock(sk);
554 rc = -ERESTARTSYS; 546 rc = -ERESTARTSYS;
555 if (signal_pending(current)) 547 if (signal_pending(current))
556 break; 548 break;
557 rc = -EAGAIN; 549 rc = -EAGAIN;
558 if (!timeout) 550 if (!timeout)
559 break; 551 break;
552 rc = 0;
560 } 553 }
561 __set_current_state(TASK_RUNNING); 554 finish_wait(sk->sk_sleep, &wait);
562 remove_wait_queue(sk->sk_sleep, &wait);
563 return rc; 555 return rc;
564} 556}
565 557
566static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout) 558static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout)
567{ 559{
568 DECLARE_WAITQUEUE(wait, current); 560 DEFINE_WAIT(wait);
569 struct llc_sock *llc = llc_sk(sk); 561 struct llc_sock *llc = llc_sk(sk);
570 int rc; 562 int rc;
571 563
572 add_wait_queue_exclusive(sk->sk_sleep, &wait);
573 for (;;) { 564 for (;;) {
574 dprintk("%s: looping...\n", __FUNCTION__); 565 prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
575 __set_current_state(TASK_INTERRUPTIBLE);
576 rc = -ENOTCONN; 566 rc = -ENOTCONN;
577 if (sk->sk_shutdown & RCV_SHUTDOWN) 567 if (sk->sk_shutdown & RCV_SHUTDOWN)
578 break; 568 break;
579 rc = 0; 569 rc = 0;
580 if (llc_data_accept_state(llc->state) || llc->p_flag) { 570 if (!llc_data_accept_state(llc->state) && !llc->p_flag)
581 release_sock(sk);
582 timeout = schedule_timeout(timeout);
583 lock_sock(sk);
584 } else
585 break; 571 break;
572 release_sock(sk);
573 timeout = schedule_timeout(timeout);
574 lock_sock(sk);
586 rc = -ERESTARTSYS; 575 rc = -ERESTARTSYS;
587 if (signal_pending(current)) 576 if (signal_pending(current))
588 break; 577 break;
@@ -590,8 +579,7 @@ static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout)
590 if (!timeout) 579 if (!timeout)
591 break; 580 break;
592 } 581 }
593 __set_current_state(TASK_RUNNING); 582 finish_wait(sk->sk_sleep, &wait);
594 remove_wait_queue(sk->sk_sleep, &wait);
595 return rc; 583 return rc;
596} 584}
597 585
@@ -621,9 +609,11 @@ static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
621 sk->sk_state != TCP_LISTEN)) 609 sk->sk_state != TCP_LISTEN))
622 goto out; 610 goto out;
623 /* wait for a connection to arrive. */ 611 /* wait for a connection to arrive. */
624 rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo); 612 if (skb_queue_empty(&sk->sk_receive_queue)) {
625 if (rc) 613 rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo);
626 goto out; 614 if (rc)
615 goto out;
616 }
627 dprintk("%s: got a new connection on %02X\n", __FUNCTION__, 617 dprintk("%s: got a new connection on %02X\n", __FUNCTION__,
628 llc_sk(sk)->laddr.lsap); 618 llc_sk(sk)->laddr.lsap);
629 skb = skb_dequeue(&sk->sk_receive_queue); 619 skb = skb_dequeue(&sk->sk_receive_queue);
@@ -672,19 +662,16 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
672 struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name; 662 struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name;
673 struct sk_buff *skb; 663 struct sk_buff *skb;
674 size_t copied = 0; 664 size_t copied = 0;
675 int rc = -ENOMEM, timeout; 665 int rc = -ENOMEM;
676 int noblock = flags & MSG_DONTWAIT; 666 int noblock = flags & MSG_DONTWAIT;
677 667
678 dprintk("%s: receiving in %02X from %02X\n", __FUNCTION__, 668 dprintk("%s: receiving in %02X from %02X\n", __FUNCTION__,
679 llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap); 669 llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);
680 lock_sock(sk); 670 lock_sock(sk);
681 timeout = sock_rcvtimeo(sk, noblock); 671 if (skb_queue_empty(&sk->sk_receive_queue)) {
682 rc = llc_ui_wait_for_data(sk, timeout); 672 rc = llc_ui_wait_for_data(sk, sock_rcvtimeo(sk, noblock));
683 if (rc) { 673 if (rc)
684 dprintk("%s: llc_ui_wait_for_data failed recv " 674 goto out;
685 "in %02X from %02X\n", __FUNCTION__,
686 llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);
687 goto out;
688 } 675 }
689 skb = skb_dequeue(&sk->sk_receive_queue); 676 skb = skb_dequeue(&sk->sk_receive_queue);
690 if (!skb) /* shutdown */ 677 if (!skb) /* shutdown */