diff options
Diffstat (limited to 'net/rds/send.c')
-rw-r--r-- | net/rds/send.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/net/rds/send.c b/net/rds/send.c index f04b929ded92..9c1c6bcaa6c9 100644 --- a/net/rds/send.c +++ b/net/rds/send.c | |||
@@ -508,12 +508,13 @@ EXPORT_SYMBOL_GPL(rds_send_get_message); | |||
508 | */ | 508 | */ |
509 | void rds_send_remove_from_sock(struct list_head *messages, int status) | 509 | void rds_send_remove_from_sock(struct list_head *messages, int status) |
510 | { | 510 | { |
511 | unsigned long flags = 0; /* silence gcc :P */ | 511 | unsigned long flags; |
512 | struct rds_sock *rs = NULL; | 512 | struct rds_sock *rs = NULL; |
513 | struct rds_message *rm; | 513 | struct rds_message *rm; |
514 | 514 | ||
515 | local_irq_save(flags); | ||
516 | while (!list_empty(messages)) { | 515 | while (!list_empty(messages)) { |
516 | int was_on_sock = 0; | ||
517 | |||
517 | rm = list_entry(messages->next, struct rds_message, | 518 | rm = list_entry(messages->next, struct rds_message, |
518 | m_conn_item); | 519 | m_conn_item); |
519 | list_del_init(&rm->m_conn_item); | 520 | list_del_init(&rm->m_conn_item); |
@@ -528,20 +529,19 @@ void rds_send_remove_from_sock(struct list_head *messages, int status) | |||
528 | * while we're messing with it. It does not prevent the | 529 | * while we're messing with it. It does not prevent the |
529 | * message from being removed from the socket, though. | 530 | * message from being removed from the socket, though. |
530 | */ | 531 | */ |
531 | spin_lock(&rm->m_rs_lock); | 532 | spin_lock_irqsave(&rm->m_rs_lock, flags); |
532 | if (!test_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) | 533 | if (!test_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) |
533 | goto unlock_and_drop; | 534 | goto unlock_and_drop; |
534 | 535 | ||
535 | if (rs != rm->m_rs) { | 536 | if (rs != rm->m_rs) { |
536 | if (rs) { | 537 | if (rs) { |
537 | spin_unlock(&rs->rs_lock); | ||
538 | rds_wake_sk_sleep(rs); | 538 | rds_wake_sk_sleep(rs); |
539 | sock_put(rds_rs_to_sk(rs)); | 539 | sock_put(rds_rs_to_sk(rs)); |
540 | } | 540 | } |
541 | rs = rm->m_rs; | 541 | rs = rm->m_rs; |
542 | spin_lock(&rs->rs_lock); | ||
543 | sock_hold(rds_rs_to_sk(rs)); | 542 | sock_hold(rds_rs_to_sk(rs)); |
544 | } | 543 | } |
544 | spin_lock(&rs->rs_lock); | ||
545 | 545 | ||
546 | if (test_and_clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) { | 546 | if (test_and_clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) { |
547 | struct rds_rdma_op *ro = rm->m_rdma_op; | 547 | struct rds_rdma_op *ro = rm->m_rdma_op; |
@@ -558,21 +558,22 @@ void rds_send_remove_from_sock(struct list_head *messages, int status) | |||
558 | notifier->n_status = status; | 558 | notifier->n_status = status; |
559 | rm->m_rdma_op->r_notifier = NULL; | 559 | rm->m_rdma_op->r_notifier = NULL; |
560 | } | 560 | } |
561 | rds_message_put(rm); | 561 | was_on_sock = 1; |
562 | rm->m_rs = NULL; | 562 | rm->m_rs = NULL; |
563 | } | 563 | } |
564 | spin_unlock(&rs->rs_lock); | ||
564 | 565 | ||
565 | unlock_and_drop: | 566 | unlock_and_drop: |
566 | spin_unlock(&rm->m_rs_lock); | 567 | spin_unlock_irqrestore(&rm->m_rs_lock, flags); |
567 | rds_message_put(rm); | 568 | rds_message_put(rm); |
569 | if (was_on_sock) | ||
570 | rds_message_put(rm); | ||
568 | } | 571 | } |
569 | 572 | ||
570 | if (rs) { | 573 | if (rs) { |
571 | spin_unlock(&rs->rs_lock); | ||
572 | rds_wake_sk_sleep(rs); | 574 | rds_wake_sk_sleep(rs); |
573 | sock_put(rds_rs_to_sk(rs)); | 575 | sock_put(rds_rs_to_sk(rs)); |
574 | } | 576 | } |
575 | local_irq_restore(flags); | ||
576 | } | 577 | } |
577 | 578 | ||
578 | /* | 579 | /* |
@@ -634,9 +635,6 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
634 | list_move(&rm->m_sock_item, &list); | 635 | list_move(&rm->m_sock_item, &list); |
635 | rds_send_sndbuf_remove(rs, rm); | 636 | rds_send_sndbuf_remove(rs, rm); |
636 | clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags); | 637 | clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags); |
637 | |||
638 | /* If this is a RDMA operation, notify the app. */ | ||
639 | __rds_rdma_send_complete(rs, rm, RDS_RDMA_CANCELED); | ||
640 | } | 638 | } |
641 | 639 | ||
642 | /* order flag updates with the rs lock */ | 640 | /* order flag updates with the rs lock */ |
@@ -645,9 +643,6 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
645 | 643 | ||
646 | spin_unlock_irqrestore(&rs->rs_lock, flags); | 644 | spin_unlock_irqrestore(&rs->rs_lock, flags); |
647 | 645 | ||
648 | if (wake) | ||
649 | rds_wake_sk_sleep(rs); | ||
650 | |||
651 | conn = NULL; | 646 | conn = NULL; |
652 | 647 | ||
653 | /* now remove the messages from the conn list as needed */ | 648 | /* now remove the messages from the conn list as needed */ |
@@ -655,6 +650,10 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
655 | /* We do this here rather than in the loop above, so that | 650 | /* We do this here rather than in the loop above, so that |
656 | * we don't have to nest m_rs_lock under rs->rs_lock */ | 651 | * we don't have to nest m_rs_lock under rs->rs_lock */ |
657 | spin_lock_irqsave(&rm->m_rs_lock, flags2); | 652 | spin_lock_irqsave(&rm->m_rs_lock, flags2); |
653 | /* If this is a RDMA operation, notify the app. */ | ||
654 | spin_lock(&rs->rs_lock); | ||
655 | __rds_rdma_send_complete(rs, rm, RDS_RDMA_CANCELED); | ||
656 | spin_unlock(&rs->rs_lock); | ||
658 | rm->m_rs = NULL; | 657 | rm->m_rs = NULL; |
659 | spin_unlock_irqrestore(&rm->m_rs_lock, flags2); | 658 | spin_unlock_irqrestore(&rm->m_rs_lock, flags2); |
660 | 659 | ||
@@ -683,6 +682,9 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
683 | if (conn) | 682 | if (conn) |
684 | spin_unlock_irqrestore(&conn->c_lock, flags); | 683 | spin_unlock_irqrestore(&conn->c_lock, flags); |
685 | 684 | ||
685 | if (wake) | ||
686 | rds_wake_sk_sleep(rs); | ||
687 | |||
686 | while (!list_empty(&list)) { | 688 | while (!list_empty(&list)) { |
687 | rm = list_entry(list.next, struct rds_message, m_sock_item); | 689 | rm = list_entry(list.next, struct rds_message, m_sock_item); |
688 | list_del_init(&rm->m_sock_item); | 690 | list_del_init(&rm->m_sock_item); |
@@ -816,7 +818,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
816 | int ret = 0; | 818 | int ret = 0; |
817 | int queued = 0, allocated_mr = 0; | 819 | int queued = 0, allocated_mr = 0; |
818 | int nonblock = msg->msg_flags & MSG_DONTWAIT; | 820 | int nonblock = msg->msg_flags & MSG_DONTWAIT; |
819 | long timeo = sock_rcvtimeo(sk, nonblock); | 821 | long timeo = sock_sndtimeo(sk, nonblock); |
820 | 822 | ||
821 | /* Mirror Linux UDP mirror of BSD error message compatibility */ | 823 | /* Mirror Linux UDP mirror of BSD error message compatibility */ |
822 | /* XXX: Perhaps MSG_MORE someday */ | 824 | /* XXX: Perhaps MSG_MORE someday */ |
@@ -895,8 +897,10 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
895 | queue_delayed_work(rds_wq, &conn->c_conn_w, 0); | 897 | queue_delayed_work(rds_wq, &conn->c_conn_w, 0); |
896 | 898 | ||
897 | ret = rds_cong_wait(conn->c_fcong, dport, nonblock, rs); | 899 | ret = rds_cong_wait(conn->c_fcong, dport, nonblock, rs); |
898 | if (ret) | 900 | if (ret) { |
901 | rs->rs_seen_congestion = 1; | ||
899 | goto out; | 902 | goto out; |
903 | } | ||
900 | 904 | ||
901 | while (!rds_send_queue_rm(rs, conn, rm, rs->rs_bound_port, | 905 | while (!rds_send_queue_rm(rs, conn, rm, rs->rs_bound_port, |
902 | dport, &queued)) { | 906 | dport, &queued)) { |
@@ -911,7 +915,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
911 | goto out; | 915 | goto out; |
912 | } | 916 | } |
913 | 917 | ||
914 | timeo = wait_event_interruptible_timeout(*sk->sk_sleep, | 918 | timeo = wait_event_interruptible_timeout(*sk_sleep(sk), |
915 | rds_send_queue_rm(rs, conn, rm, | 919 | rds_send_queue_rm(rs, conn, rm, |
916 | rs->rs_bound_port, | 920 | rs->rs_bound_port, |
917 | dport, | 921 | dport, |