* this is not a good place to change state. Let the workqueue
                 * do it.
                 */
-               if (mptcp_pending_data_fin(sk, NULL) &&
-                   schedule_work(&msk->work))
-                       sock_hold(sk);
+               if (mptcp_pending_data_fin(sk, NULL))
+                       mptcp_schedule_work(sk);
        }
 
        spin_unlock_bh(&sk->sk_lock.slock);
        sk_reset_timer(sk, &icsk->icsk_retransmit_timer, jiffies + tout);
 }
 
+bool mptcp_schedule_work(struct sock *sk)
+{
+       if (inet_sk_state_load(sk) != TCP_CLOSE &&
+           schedule_work(&mptcp_sk(sk)->work)) {
+               /* each subflow already holds a reference to the sk, and the
+                * workqueue is invoked by a subflow, so sk can't go away here.
+                */
+               sock_hold(sk);
+               return true;
+       }
+       return false;
+}
+
 void mptcp_data_acked(struct sock *sk)
 {
        mptcp_reset_timer(sk);
 
        if ((!test_bit(MPTCP_SEND_SPACE, &mptcp_sk(sk)->flags) ||
-            (inet_sk_state_load(sk) != TCP_ESTABLISHED)) &&
-           schedule_work(&mptcp_sk(sk)->work))
-               sock_hold(sk);
+            (inet_sk_state_load(sk) != TCP_ESTABLISHED)))
+               mptcp_schedule_work(sk);
 }
 
 void mptcp_subflow_eof(struct sock *sk)
 {
-       struct mptcp_sock *msk = mptcp_sk(sk);
-
-       if (!test_and_set_bit(MPTCP_WORK_EOF, &msk->flags) &&
-           schedule_work(&msk->work))
-               sock_hold(sk);
+       if (!test_and_set_bit(MPTCP_WORK_EOF, &mptcp_sk(sk)->flags))
+               mptcp_schedule_work(sk);
 }
 
 static void mptcp_check_for_eof(struct mptcp_sock *msk)
                mptcp_stop_timer(sk);
        } else {
                set_bit(MPTCP_WORK_RTX, &msk->flags);
-               if (schedule_work(&msk->work))
-                       sock_hold(sk);
+               mptcp_schedule_work(sk);
        }
 }
 
                struct sock *ssk;
 
                ssk = mptcp_subflow_recv_lookup(msk);
-               if (!ssk || !schedule_work(&msk->work))
+               if (!ssk || sk->sk_state == TCP_CLOSE ||
+                   !schedule_work(&msk->work))
                        __sock_put(sk);
        }
 
 
 void mptcp_rcv_space_init(struct mptcp_sock *msk, const struct sock *ssk);
 void mptcp_data_ready(struct sock *sk, struct sock *ssk);
 bool mptcp_finish_join(struct sock *sk);
+bool mptcp_schedule_work(struct sock *sk);
 void mptcp_data_acked(struct sock *sk);
 void mptcp_subflow_eof(struct sock *sk);
 bool mptcp_update_rcv_data_fin(struct mptcp_sock *msk, u64 data_fin_seq, bool use_64bit);