mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
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>
This commit is contained in:
parent
869e7c6248
commit
a60e3cc7c9
3 changed files with 40 additions and 21 deletions
|
@ -35,6 +35,7 @@
|
||||||
#include <linux/netdev_features.h>
|
#include <linux/netdev_features.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <net/flow_dissector.h>
|
#include <net/flow_dissector.h>
|
||||||
|
#include <linux/splice.h>
|
||||||
|
|
||||||
/* A. Checksumming of received packets by device.
|
/* A. Checksumming of received packets by device.
|
||||||
*
|
*
|
||||||
|
@ -2699,9 +2700,15 @@ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len);
|
||||||
int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len);
|
int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len);
|
||||||
__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to,
|
__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to,
|
||||||
int len, __wsum csum);
|
int len, __wsum csum);
|
||||||
int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
|
ssize_t skb_socket_splice(struct sock *sk,
|
||||||
|
struct pipe_inode_info *pipe,
|
||||||
|
struct splice_pipe_desc *spd);
|
||||||
|
int skb_splice_bits(struct sk_buff *skb, struct sock *sk, unsigned int offset,
|
||||||
struct pipe_inode_info *pipe, unsigned int len,
|
struct pipe_inode_info *pipe, unsigned int len,
|
||||||
unsigned int flags);
|
unsigned int flags,
|
||||||
|
ssize_t (*splice_cb)(struct sock *,
|
||||||
|
struct pipe_inode_info *,
|
||||||
|
struct splice_pipe_desc *));
|
||||||
void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
|
void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
|
||||||
unsigned int skb_zerocopy_headlen(const struct sk_buff *from);
|
unsigned int skb_zerocopy_headlen(const struct sk_buff *from);
|
||||||
int skb_zerocopy(struct sk_buff *to, struct sk_buff *from,
|
int skb_zerocopy(struct sk_buff *to, struct sk_buff *from,
|
||||||
|
|
|
@ -1870,15 +1870,39 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssize_t skb_socket_splice(struct sock *sk,
|
||||||
|
struct pipe_inode_info *pipe,
|
||||||
|
struct splice_pipe_desc *spd)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Drop the socket lock, otherwise we have reverse
|
||||||
|
* locking dependencies between sk_lock and i_mutex
|
||||||
|
* here as compared to sendfile(). We enter here
|
||||||
|
* with the socket lock held, and splice_to_pipe() will
|
||||||
|
* grab the pipe inode lock. For sendfile() emulation,
|
||||||
|
* we call into ->sendpage() with the i_mutex lock held
|
||||||
|
* and networking will grab the socket lock.
|
||||||
|
*/
|
||||||
|
release_sock(sk);
|
||||||
|
ret = splice_to_pipe(pipe, spd);
|
||||||
|
lock_sock(sk);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Map data from the skb to a pipe. Should handle both the linear part,
|
* Map data from the skb to a pipe. Should handle both the linear part,
|
||||||
* the fragments, and the frag list. It does NOT handle frag lists within
|
* the fragments, and the frag list. It does NOT handle frag lists within
|
||||||
* the frag list, if such a thing exists. We'd probably need to recurse to
|
* the frag list, if such a thing exists. We'd probably need to recurse to
|
||||||
* handle that cleanly.
|
* handle that cleanly.
|
||||||
*/
|
*/
|
||||||
int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
|
int skb_splice_bits(struct sk_buff *skb, struct sock *sk, unsigned int offset,
|
||||||
struct pipe_inode_info *pipe, unsigned int tlen,
|
struct pipe_inode_info *pipe, unsigned int tlen,
|
||||||
unsigned int flags)
|
unsigned int flags,
|
||||||
|
ssize_t (*splice_cb)(struct sock *,
|
||||||
|
struct pipe_inode_info *,
|
||||||
|
struct splice_pipe_desc *))
|
||||||
{
|
{
|
||||||
struct partial_page partial[MAX_SKB_FRAGS];
|
struct partial_page partial[MAX_SKB_FRAGS];
|
||||||
struct page *pages[MAX_SKB_FRAGS];
|
struct page *pages[MAX_SKB_FRAGS];
|
||||||
|
@ -1891,7 +1915,6 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
|
||||||
.spd_release = sock_spd_release,
|
.spd_release = sock_spd_release,
|
||||||
};
|
};
|
||||||
struct sk_buff *frag_iter;
|
struct sk_buff *frag_iter;
|
||||||
struct sock *sk = skb->sk;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1914,20 +1937,8 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (spd.nr_pages) {
|
if (spd.nr_pages)
|
||||||
/*
|
ret = splice_cb(sk, pipe, &spd);
|
||||||
* Drop the socket lock, otherwise we have reverse
|
|
||||||
* locking dependencies between sk_lock and i_mutex
|
|
||||||
* here as compared to sendfile(). We enter here
|
|
||||||
* with the socket lock held, and splice_to_pipe() will
|
|
||||||
* grab the pipe inode lock. For sendfile() emulation,
|
|
||||||
* we call into ->sendpage() with the i_mutex lock held
|
|
||||||
* and networking will grab the socket lock.
|
|
||||||
*/
|
|
||||||
release_sock(sk);
|
|
||||||
ret = splice_to_pipe(pipe, &spd);
|
|
||||||
lock_sock(sk);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -695,8 +695,9 @@ static int tcp_splice_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
|
||||||
struct tcp_splice_state *tss = rd_desc->arg.data;
|
struct tcp_splice_state *tss = rd_desc->arg.data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = skb_splice_bits(skb, offset, tss->pipe, min(rd_desc->count, len),
|
ret = skb_splice_bits(skb, skb->sk, offset, tss->pipe,
|
||||||
tss->flags);
|
min(rd_desc->count, len), tss->flags,
|
||||||
|
skb_socket_splice);
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
rd_desc->count -= ret;
|
rd_desc->count -= ret;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue