forked from Minki/linux
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>
This commit is contained in:
parent
eb12010e9a
commit
715306f69d
@ -679,21 +679,15 @@ struct accept_wait_data {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void incomming_connection(struct sock *sk)
|
static void drbd_incoming_connection(struct sock *sk)
|
||||||
{
|
{
|
||||||
struct accept_wait_data *ad = sk->sk_user_data;
|
struct accept_wait_data *ad = sk->sk_user_data;
|
||||||
struct drbd_tconn *tconn = ad->tconn;
|
void (*state_change)(struct sock *sk);
|
||||||
|
|
||||||
if (sk->sk_state != TCP_ESTABLISHED)
|
state_change = ad->original_sk_state_change;
|
||||||
conn_warn(tconn, "unexpected tcp state change. sk_state = %d\n", sk->sk_state);
|
if (sk->sk_state == TCP_ESTABLISHED)
|
||||||
|
complete(&ad->door_bell);
|
||||||
write_lock_bh(&sk->sk_callback_lock);
|
state_change(sk);
|
||||||
sk->sk_state_change = ad->original_sk_state_change;
|
|
||||||
sk->sk_user_data = NULL;
|
|
||||||
write_unlock_bh(&sk->sk_callback_lock);
|
|
||||||
|
|
||||||
sk->sk_state_change(sk);
|
|
||||||
complete(&ad->door_bell);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int prepare_listen_socket(struct drbd_tconn *tconn, struct accept_wait_data *ad)
|
static 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
|
|||||||
ad->s_listen = s_listen;
|
ad->s_listen = s_listen;
|
||||||
write_lock_bh(&s_listen->sk->sk_callback_lock);
|
write_lock_bh(&s_listen->sk->sk_callback_lock);
|
||||||
ad->original_sk_state_change = s_listen->sk->sk_state_change;
|
ad->original_sk_state_change = s_listen->sk->sk_state_change;
|
||||||
s_listen->sk->sk_state_change = incomming_connection;
|
s_listen->sk->sk_state_change = drbd_incoming_connection;
|
||||||
s_listen->sk->sk_user_data = ad;
|
s_listen->sk->sk_user_data = ad;
|
||||||
write_unlock_bh(&s_listen->sk->sk_callback_lock);
|
write_unlock_bh(&s_listen->sk->sk_callback_lock);
|
||||||
|
|
||||||
@ -759,6 +753,14 @@ out:
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void unregister_state_change(struct sock *sk, struct accept_wait_data *ad)
|
||||||
|
{
|
||||||
|
write_lock_bh(&sk->sk_callback_lock);
|
||||||
|
sk->sk_state_change = ad->original_sk_state_change;
|
||||||
|
sk->sk_user_data = NULL;
|
||||||
|
write_unlock_bh(&sk->sk_callback_lock);
|
||||||
|
}
|
||||||
|
|
||||||
static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn, struct accept_wait_data *ad)
|
static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn, struct accept_wait_data *ad)
|
||||||
{
|
{
|
||||||
int timeo, connect_int, err = 0;
|
int timeo, connect_int, err = 0;
|
||||||
@ -789,6 +791,9 @@ static struct socket *drbd_wait_for_connect(struct drbd_tconn *tconn, struct acc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s_estab)
|
||||||
|
unregister_state_change(s_estab->sk, ad);
|
||||||
|
|
||||||
return s_estab;
|
return s_estab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user