aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@linbit.com>2012-08-10 11:00:30 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-09 08:05:50 -0500
commit715306f69d85f7ea21eaef4efe75b8364cfea1d5 (patch)
treef6abd1f0a94aab0d2e097b72743f7dbe9ef9deaa
parenteb12010e9af119c84e6b2214064a98681027e0e3 (diff)
drbd: Don't unregister socket state_change callback from within the callback
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
-rw-r--r--drivers/block/drbd/drbd_receiver.c31
1 files changed, 18 insertions, 13 deletions
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index 99121076bf12..14df37ccd524 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -679,21 +679,15 @@ struct accept_wait_data {
679 679
680}; 680};
681 681
682static void incomming_connection(struct sock *sk) 682static void drbd_incoming_connection(struct sock *sk)
683{ 683{
684 struct accept_wait_data *ad = sk->sk_user_data; 684 struct accept_wait_data *ad = sk->sk_user_data;
685 struct drbd_tconn *tconn = ad->tconn; 685 void (*state_change)(struct sock *sk);
686 686
687 if (sk->sk_state != TCP_ESTABLISHED) 687 state_change = ad->original_sk_state_change;
688 conn_warn(tconn, "unexpected tcp state change. sk_state = %d\n", sk->sk_state); 688 if (sk->sk_state == TCP_ESTABLISHED)
689 689 complete(&ad->door_bell);
690 write_lock_bh(&sk->sk_callback_lock); 690 state_change(sk);
691 sk->sk_state_change = ad->original_sk_state_change;
692 sk->sk_user_data = NULL;
693 write_unlock_bh(&sk->sk_callback_lock);
694
695 sk->sk_state_change(sk);
696 complete(&ad->door_bell);
697} 691}
698 692
699static int prepare_listen_socket(struct drbd_tconn *tconn, struct accept_wait_data *ad) 693static int prepare_listen_socket(struct drbd_tconn *tconn, struct accept_wait_data *ad)
@@ -736,7 +730,7 @@ static int prepare_listen_socket(struct drbd_tconn *tconn, struct accept_wait_da
736 ad->s_listen = s_listen; 730 ad->s_listen = s_listen;
737 write_lock_bh(&s_listen->sk->sk_callback_lock); 731 write_lock_bh(&s_listen->sk->sk_callback_lock);
738 ad->original_sk_state_change = s_listen->sk->sk_state_change; 732 ad->original_sk_state_change = s_listen->sk->sk_state_change;
739 s_listen->sk->sk_state_change = incomming_connection; 733 s_listen->sk->sk_state_change = drbd_incoming_connection;
740 s_listen->sk->sk_user_data = ad; 734 s_listen->sk->sk_user_data = ad;
741 write_unlock_bh(&s_listen->sk->sk_callback_lock); 735 write_unlock_bh(&s_listen->sk->sk_callback_lock);
742 736
@@ -759,6 +753,14 @@ out:
759 return -EIO; 753 return -EIO;
760} 754}
761 755
756static void unregister_state_change(struct sock *sk, struct accept_wait_data *ad)
757{
758 write_lock_bh(&sk->sk_callback_lock);
759 sk->sk_state_change = ad->original_sk_state_change;
760 sk->sk_user_data = NULL;
761 write_unlock_bh(&sk->sk_callback_lock);
762}
763
762static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn, struct accept_wait_data *ad) 764static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn, struct accept_wait_data *ad)
763{ 765{
764 int timeo, connect_int, err = 0; 766 int timeo, connect_int, err = 0;
@@ -789,6 +791,9 @@ static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn, struct acc
789 } 791 }
790 } 792 }
791 793
794 if (s_estab)
795 unregister_state_change(s_estab->sk, ad);
796
792 return s_estab; 797 return s_estab;
793} 798}
794 799