From: Amir Vadai Date: Thu, 26 Nov 2009 15:10:57 +0000 (+0200) Subject: sdp: flush rx_comp_work before destroying socket + make dreq_wait_timeout_work flushi... X-Git-Tag: v4.1.12-92~264^2~5^2~237 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=177c871ab4bf0b50a165af317fdce402456dae43;p=users%2Fjedix%2Flinux-maple.git sdp: flush rx_comp_work before destroying socket + make dreq_wait_timeout_work flushing synced Signed-off-by: Amir Vadai --- diff --git a/drivers/infiniband/ulp/sdp/sdp.h b/drivers/infiniband/ulp/sdp/sdp.h index d6ba236ec1c88..d67a973d1b55e 100644 --- a/drivers/infiniband/ulp/sdp/sdp.h +++ b/drivers/infiniband/ulp/sdp/sdp.h @@ -726,9 +726,7 @@ void sdp_start_keepalive_timer(struct sock *sk); void sdp_remove_sock(struct sdp_sock *ssk); void sdp_add_sock(struct sdp_sock *ssk); void sdp_urg(struct sdp_sock *ssk, struct sk_buff *skb); -void sdp_dreq_wait_timeout_work(struct work_struct *work); void sdp_cancel_dreq_wait_timeout(struct sdp_sock *ssk); -void sdp_destroy_work(struct work_struct *work); void sdp_reset_sk(struct sock *sk, int rc); void sdp_reset(struct sock *sk); int sdp_tx_wait_memory(struct sdp_sock *ssk, long *timeo_p, int *credits_needed); diff --git a/drivers/infiniband/ulp/sdp/sdp_main.c b/drivers/infiniband/ulp/sdp/sdp_main.c index bb8a15be71085..61ad1c8898a05 100644 --- a/drivers/infiniband/ulp/sdp/sdp_main.c +++ b/drivers/infiniband/ulp/sdp/sdp_main.c @@ -958,7 +958,7 @@ void sdp_cancel_dreq_wait_timeout(struct sdp_sock *ssk) sdp_dbg(&ssk->isk.sk, "cancelling dreq wait timeout\n"); ssk->dreq_wait_timeout = 0; - if (cancel_delayed_work(&ssk->dreq_wait_work)) { + if (cancel_delayed_work_sync(&ssk->dreq_wait_work)) { /* The timeout hasn't reached - need to clean ref count */ sock_put(&ssk->isk.sk, SOCK_REF_DREQ_TO); } @@ -966,7 +966,7 @@ void sdp_cancel_dreq_wait_timeout(struct sdp_sock *ssk) percpu_counter_dec(ssk->isk.sk.sk_prot->orphan_count); } -void sdp_destroy_work(struct work_struct *work) +static void sdp_destroy_work(struct work_struct *work) { struct sdp_sock *ssk = container_of(work, struct sdp_sock, destroy_work); @@ -975,6 +975,13 @@ void sdp_destroy_work(struct work_struct *work) sdp_destroy_qp(ssk); + /* Can be sure that rx_comp_work won't be queued from here cause + * ssk->rx_ring.cq is NULL from here + */ + if (cancel_work_sync(&ssk->rx_comp_work)) { + sdp_dbg(sk, "RX completion work was queued during destroy\n"); + } + memset((void *)&ssk->id, 0, sizeof(*ssk) - offsetof(typeof(*ssk), id)); sdp_cancel_dreq_wait_timeout(ssk); @@ -991,15 +998,18 @@ void sdp_destroy_work(struct work_struct *work) sock_put(sk, SOCK_REF_RESET); } -void sdp_dreq_wait_timeout_work(struct work_struct *work) +static void sdp_dreq_wait_timeout_work(struct work_struct *work) { struct sdp_sock *ssk = container_of(work, struct sdp_sock, dreq_wait_work.work); struct sock *sk = &ssk->isk.sk; + + if (!ssk->dreq_wait_timeout) + goto out; lock_sock(sk); - if (!sdp_sk(sk)->dreq_wait_timeout || + if (!ssk->dreq_wait_timeout || !((1 << sk->sk_state) & (TCPF_FIN_WAIT1 | TCPF_LAST_ACK))) { release_sock(sk); goto out; @@ -1036,6 +1046,9 @@ static struct lock_class_key ib_sdp_sk_receive_queue_lock_key; static struct lock_class_key ib_sdp_sk_callback_lock_key; +static void sdp_destroy_work(struct work_struct *work); +static void sdp_dreq_wait_timeout_work(struct work_struct *work); + int sdp_init_sock(struct sock *sk) { struct sdp_sock *ssk = sdp_sk(sk);