aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Frederic Sowa <hannes@stressinduktion.org>2015-05-21 11:00:00 -0400
committerDavid S. Miller <davem@davemloft.net>2015-05-25 00:06:59 -0400
commita60e3cc7c92973a31fad0fd04dc5cf4355d3d1ef (patch)
treefccece19424d49db1c03ef8f204f3c7ca3478a4a
parent869e7c62486ec0e170a9771acaa251d1a33b5871 (diff)
net: make skb_splice_bits more configureable
Prepare skb_splice_bits to be able to deal with AF_UNIX sockets. AF_UNIX sockets don't use lock_sock/release_sock and thus we have to use a callback to make the locking and unlocking configureable. Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/skbuff.h11
-rw-r--r--net/core/skbuff.c45
-rw-r--r--net/ipv4/tcp.c5
3 files changed, 40 insertions, 21 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index f708936cdd23..6b41c15efa27 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -35,6 +35,7 @@
35#include <linux/netdev_features.h> 35#include <linux/netdev_features.h>
36#include <linux/sched.h> 36#include <linux/sched.h>
37#include <net/flow_dissector.h> 37#include <net/flow_dissector.h>
38#include <linux/splice.h>
38 39
39/* A. Checksumming of received packets by device. 40/* A. Checksumming of received packets by device.
40 * 41 *
@@ -2699,9 +2700,15 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len);
2699int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len); 2700int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len);
2700__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to, 2701__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to,
2701 int len, __wsum csum); 2702 int len, __wsum csum);
2702int skb_splice_bits(struct sk_buff *skb, unsigned int offset, 2703ssize_t skb_socket_splice(struct sock *sk,
2704 struct pipe_inode_info *pipe,
2705 struct splice_pipe_desc *spd);
2706int skb_splice_bits(struct sk_buff *skb, struct sock *sk, unsigned int offset,
2703 struct pipe_inode_info *pipe, unsigned int len, 2707 struct pipe_inode_info *pipe, unsigned int len,
2704 unsigned int flags); 2708 unsigned int flags,
2709 ssize_t (*splice_cb)(struct sock *,
2710 struct pipe_inode_info *,
2711 struct splice_pipe_desc *));
2705void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to); 2712void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
2706unsigned int skb_zerocopy_headlen(const struct sk_buff *from); 2713unsigned int skb_zerocopy_headlen(const struct sk_buff *from);
2707int skb_zerocopy(struct sk_buff *to, struct sk_buff *from, 2714int skb_zerocopy(struct sk_buff *to, struct sk_buff *from,
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 4f2babeaf18d..02769fa4f5c8 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1870,15 +1870,39 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
1870 return false; 1870 return false;
1871} 1871}
1872 1872
1873ssize_t skb_socket_splice(struct sock *sk,
1874 struct pipe_inode_info *pipe,
1875 struct splice_pipe_desc *spd)
1876{
1877 int ret;
1878
1879 /* Drop the socket lock, otherwise we have reverse
1880 * locking dependencies between sk_lock and i_mutex
1881 * here as compared to sendfile(). We enter here
1882 * with the socket lock held, and splice_to_pipe() will
1883 * grab the pipe inode lock. For sendfile() emulation,
1884 * we call into ->sendpage() with the i_mutex lock held
1885 * and networking will grab the socket lock.
1886 */
1887 release_sock(sk);
1888 ret = splice_to_pipe(pipe, spd);
1889 lock_sock(sk);
1890
1891 return ret;
1892}
1893
1873/* 1894/*
1874 * Map data from the skb to a pipe. Should handle both the linear part, 1895 * Map data from the skb to a pipe. Should handle both the linear part,
1875 * the fragments, and the frag list. It does NOT handle frag lists within 1896 * the fragments, and the frag list. It does NOT handle frag lists within
1876 * the frag list, if such a thing exists. We'd probably need to recurse to 1897 * the frag list, if such a thing exists. We'd probably need to recurse to
1877 * handle that cleanly. 1898 * handle that cleanly.
1878 */ 1899 */
1879int skb_splice_bits(struct sk_buff *skb, unsigned int offset, 1900int skb_splice_bits(struct sk_buff *skb, struct sock *sk, unsigned int offset,
1880 struct pipe_inode_info *pipe, unsigned int tlen, 1901 struct pipe_inode_info *pipe, unsigned int tlen,
1881 unsigned int flags) 1902 unsigned int flags,
1903 ssize_t (*splice_cb)(struct sock *,
1904 struct pipe_inode_info *,
1905 struct splice_pipe_desc *))
1882{ 1906{
1883 struct partial_page partial[MAX_SKB_FRAGS]; 1907 struct partial_page partial[MAX_SKB_FRAGS];
1884 struct page *pages[MAX_SKB_FRAGS]; 1908 struct page *pages[MAX_SKB_FRAGS];
@@ -1891,7 +1915,6 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
1891 .spd_release = sock_spd_release, 1915 .spd_release = sock_spd_release,
1892 }; 1916 };
1893 struct sk_buff *frag_iter; 1917 struct sk_buff *frag_iter;
1894 struct sock *sk = skb->sk;
1895 int ret = 0; 1918 int ret = 0;
1896 1919
1897 /* 1920 /*
@@ -1914,20 +1937,8 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
1914 } 1937 }
1915 1938
1916done: 1939done:
1917 if (spd.nr_pages) { 1940 if (spd.nr_pages)
1918 /* 1941 ret = splice_cb(sk, pipe, &spd);
1919 * Drop the socket lock, otherwise we have reverse
1920 * locking dependencies between sk_lock and i_mutex
1921 * here as compared to sendfile(). We enter here
1922 * with the socket lock held, and splice_to_pipe() will
1923 * grab the pipe inode lock. For sendfile() emulation,
1924 * we call into ->sendpage() with the i_mutex lock held
1925 * and networking will grab the socket lock.
1926 */
1927 release_sock(sk);
1928 ret = splice_to_pipe(pipe, &spd);
1929 lock_sock(sk);
1930 }
1931 1942
1932 return ret; 1943 return ret;
1933} 1944}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 90afcec3f427..65f791f74845 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -695,8 +695,9 @@ static int tcp_splice_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
695 struct tcp_splice_state *tss = rd_desc->arg.data; 695 struct tcp_splice_state *tss = rd_desc->arg.data;
696 int ret; 696 int ret;
697 697
698 ret = skb_splice_bits(skb, offset, tss->pipe, min(rd_desc->count, len), 698 ret = skb_splice_bits(skb, skb->sk, offset, tss->pipe,
699 tss->flags); 699 min(rd_desc->count, len), tss->flags,
700 skb_socket_splice);
700 if (ret > 0) 701 if (ret > 0)
701 rd_desc->count -= ret; 702 rd_desc->count -= ret;
702 return ret; 703 return ret;