diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/unix/af_unix.c | 25 |
1 files changed, 12 insertions, 13 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 2db702d82e7d..1a02af0e3049 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -1859,10 +1859,10 @@ out: | |||
1859 | } | 1859 | } |
1860 | 1860 | ||
1861 | /* | 1861 | /* |
1862 | * Sleep until data has arrive. But check for races.. | 1862 | * Sleep until more data has arrived. But check for races.. |
1863 | */ | 1863 | */ |
1864 | 1864 | static long unix_stream_data_wait(struct sock *sk, long timeo, | |
1865 | static long unix_stream_data_wait(struct sock *sk, long timeo) | 1865 | struct sk_buff *last) |
1866 | { | 1866 | { |
1867 | DEFINE_WAIT(wait); | 1867 | DEFINE_WAIT(wait); |
1868 | 1868 | ||
@@ -1871,7 +1871,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo) | |||
1871 | for (;;) { | 1871 | for (;;) { |
1872 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 1872 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1873 | 1873 | ||
1874 | if (!skb_queue_empty(&sk->sk_receive_queue) || | 1874 | if (skb_peek_tail(&sk->sk_receive_queue) != last || |
1875 | sk->sk_err || | 1875 | sk->sk_err || |
1876 | (sk->sk_shutdown & RCV_SHUTDOWN) || | 1876 | (sk->sk_shutdown & RCV_SHUTDOWN) || |
1877 | signal_pending(current) || | 1877 | signal_pending(current) || |
@@ -1890,8 +1890,6 @@ static long unix_stream_data_wait(struct sock *sk, long timeo) | |||
1890 | return timeo; | 1890 | return timeo; |
1891 | } | 1891 | } |
1892 | 1892 | ||
1893 | |||
1894 | |||
1895 | static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | 1893 | static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, |
1896 | struct msghdr *msg, size_t size, | 1894 | struct msghdr *msg, size_t size, |
1897 | int flags) | 1895 | int flags) |
@@ -1936,14 +1934,12 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1936 | goto out; | 1934 | goto out; |
1937 | } | 1935 | } |
1938 | 1936 | ||
1939 | skip = sk_peek_offset(sk, flags); | ||
1940 | |||
1941 | do { | 1937 | do { |
1942 | int chunk; | 1938 | int chunk; |
1943 | struct sk_buff *skb; | 1939 | struct sk_buff *skb, *last; |
1944 | 1940 | ||
1945 | unix_state_lock(sk); | 1941 | unix_state_lock(sk); |
1946 | skb = skb_peek(&sk->sk_receive_queue); | 1942 | last = skb = skb_peek(&sk->sk_receive_queue); |
1947 | again: | 1943 | again: |
1948 | if (skb == NULL) { | 1944 | if (skb == NULL) { |
1949 | unix_sk(sk)->recursion_level = 0; | 1945 | unix_sk(sk)->recursion_level = 0; |
@@ -1966,7 +1962,7 @@ again: | |||
1966 | break; | 1962 | break; |
1967 | mutex_unlock(&u->readlock); | 1963 | mutex_unlock(&u->readlock); |
1968 | 1964 | ||
1969 | timeo = unix_stream_data_wait(sk, timeo); | 1965 | timeo = unix_stream_data_wait(sk, timeo, last); |
1970 | 1966 | ||
1971 | if (signal_pending(current) | 1967 | if (signal_pending(current) |
1972 | || mutex_lock_interruptible(&u->readlock)) { | 1968 | || mutex_lock_interruptible(&u->readlock)) { |
@@ -1980,10 +1976,13 @@ again: | |||
1980 | break; | 1976 | break; |
1981 | } | 1977 | } |
1982 | 1978 | ||
1983 | if (skip >= skb->len) { | 1979 | skip = sk_peek_offset(sk, flags); |
1980 | while (skip >= skb->len) { | ||
1984 | skip -= skb->len; | 1981 | skip -= skb->len; |
1982 | last = skb; | ||
1985 | skb = skb_peek_next(skb, &sk->sk_receive_queue); | 1983 | skb = skb_peek_next(skb, &sk->sk_receive_queue); |
1986 | goto again; | 1984 | if (!skb) |
1985 | goto again; | ||
1987 | } | 1986 | } |
1988 | 1987 | ||
1989 | unix_state_unlock(sk); | 1988 | unix_state_unlock(sk); |