summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-09-29 13:47:08 -0700
committerDavid S. Miller <davem@davemloft.net>2015-09-29 13:47:08 -0700
commit3504bb639ec793c181de6e33a205fc8ca6cf32bf (patch)
treeba19241592c69f4336f1429cd9d2a1933722f015
parent2103d6b818fcdae15ffa04cf385f770e6c3892c3 (diff)
parent9f389e35674f5b086edd70ed524ca0f287259725 (diff)
downloadlinux-dynticks-3504bb639ec793c181de6e33a205fc8ca6cf32bf.tar.gz
Merge branch 'af_unix_MSG_PEEK'
Aaron Conole says: ==================== af_unix: return data from multiple SKBs on recv() with MSG_PEEK flag This patch set implements a bugfix for kernel.org bugzilla #12323, allowing MSG_PEEK to return all queued data on the unix domain socket, not just the data contained in a single SKB. This is the v3 version of this patch, which includes a suggested modification by Eric Dumazet to convert the unix_sk() conversion macro to a static inline function. These patches are independent and can be applied separately. This set was tested over a 24-hour period, utilizing a loop continually executing the bugzilla issue attached python code. It was instrumented with a pr_err_once() ([ 13.798683] unix: went there at least one time). v2->v3: - Added Eric Dumazet's suggestion for #define to static inline - Fixed an issue calling unix_state_lock() with an invalid argument v3->v4: - Eliminated an XXX comment - Changed from goto unlock to explicit unix_state_unlock() and break ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/af_unix.h6
-rw-r--r--net/unix/af_unix.c15
2 files changed, 19 insertions, 2 deletions
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 4a167b30a12ff0..cb1b9bbda33211 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -63,7 +63,11 @@ struct unix_sock {
#define UNIX_GC_MAYBE_CYCLE 1
struct socket_wq peer_wq;
};
-#define unix_sk(__sk) ((struct unix_sock *)__sk)
+
+static inline struct unix_sock *unix_sk(struct sock *sk)
+{
+ return (struct unix_sock *)sk;
+}
#define peer_wait peer_wq.wait
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 03ee4d359f6a49..ef31b40ad55000 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2179,8 +2179,21 @@ unlock:
if (UNIXCB(skb).fp)
scm.fp = scm_fp_dup(UNIXCB(skb).fp);
- sk_peek_offset_fwd(sk, chunk);
+ if (skip) {
+ sk_peek_offset_fwd(sk, chunk);
+ skip -= chunk;
+ }
+ if (UNIXCB(skb).fp)
+ break;
+
+ last = skb;
+ last_len = skb->len;
+ unix_state_lock(sk);
+ skb = skb_peek_next(skb, &sk->sk_receive_queue);
+ if (skb)
+ goto again;
+ unix_state_unlock(sk);
break;
}
} while (size);