Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: decnet: Fix sleeping inside in af_decnet

The release_sock() is blocking function, it would change the state
after sleeping. use wait_woken() instead.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Yajun Deng <yajun.deng@linux.dev>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Yajun Deng and committed by
David S. Miller
5f119ba1 11d8d98c

+12 -15
+12 -15
net/decnet/af_decnet.c
··· 816 816 static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation) 817 817 { 818 818 struct dn_scp *scp = DN_SK(sk); 819 - DEFINE_WAIT(wait); 819 + DEFINE_WAIT_FUNC(wait, woken_wake_function); 820 820 int err; 821 821 822 822 if (scp->state != DN_CR) ··· 826 826 scp->segsize_loc = dst_metric_advmss(__sk_dst_get(sk)); 827 827 dn_send_conn_conf(sk, allocation); 828 828 829 - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 829 + add_wait_queue(sk_sleep(sk), &wait); 830 830 for(;;) { 831 831 release_sock(sk); 832 832 if (scp->state == DN_CC) 833 - *timeo = schedule_timeout(*timeo); 833 + *timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, *timeo); 834 834 lock_sock(sk); 835 835 err = 0; 836 836 if (scp->state == DN_RUN) ··· 844 844 err = -EAGAIN; 845 845 if (!*timeo) 846 846 break; 847 - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 848 847 } 849 - finish_wait(sk_sleep(sk), &wait); 848 + remove_wait_queue(sk_sleep(sk), &wait); 850 849 if (err == 0) { 851 850 sk->sk_socket->state = SS_CONNECTED; 852 851 } else if (scp->state != DN_CC) { ··· 857 858 static int dn_wait_run(struct sock *sk, long *timeo) 858 859 { 859 860 struct dn_scp *scp = DN_SK(sk); 860 - DEFINE_WAIT(wait); 861 + DEFINE_WAIT_FUNC(wait, woken_wake_function); 861 862 int err = 0; 862 863 863 864 if (scp->state == DN_RUN) ··· 866 867 if (!*timeo) 867 868 return -EALREADY; 868 869 869 - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 870 + add_wait_queue(sk_sleep(sk), &wait); 870 871 for(;;) { 871 872 release_sock(sk); 872 873 if (scp->state == DN_CI || scp->state == DN_CC) 873 - *timeo = schedule_timeout(*timeo); 874 + *timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, *timeo); 874 875 lock_sock(sk); 875 876 err = 0; 876 877 if (scp->state == DN_RUN) ··· 884 885 err = -ETIMEDOUT; 885 886 if (!*timeo) 886 887 break; 887 - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 888 888 } 889 - finish_wait(sk_sleep(sk), &wait); 889 + remove_wait_queue(sk_sleep(sk), &wait); 890 890 out: 891 891 if (err == 0) { 892 892 sk->sk_socket->state = SS_CONNECTED; ··· 1030 1032 1031 1033 static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo) 1032 1034 { 1033 - DEFINE_WAIT(wait); 1035 + DEFINE_WAIT_FUNC(wait, woken_wake_function); 1034 1036 struct sk_buff *skb = NULL; 1035 1037 int err = 0; 1036 1038 1037 - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 1039 + add_wait_queue(sk_sleep(sk), &wait); 1038 1040 for(;;) { 1039 1041 release_sock(sk); 1040 1042 skb = skb_dequeue(&sk->sk_receive_queue); 1041 1043 if (skb == NULL) { 1042 - *timeo = schedule_timeout(*timeo); 1044 + *timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, *timeo); 1043 1045 skb = skb_dequeue(&sk->sk_receive_queue); 1044 1046 } 1045 1047 lock_sock(sk); ··· 1054 1056 err = -EAGAIN; 1055 1057 if (!*timeo) 1056 1058 break; 1057 - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 1058 1059 } 1059 - finish_wait(sk_sleep(sk), &wait); 1060 + remove_wait_queue(sk_sleep(sk), &wait); 1060 1061 1061 1062 return skb == NULL ? ERR_PTR(err) : skb; 1062 1063 }