|
@@ -1870,15 +1870,39 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
|
|
|
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,
|
|
|
* 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
|
|
|
* 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,
|
|
|
- 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 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,
|
|
|
};
|
|
|
struct sk_buff *frag_iter;
|
|
|
- struct sock *sk = skb->sk;
|
|
|
int ret = 0;
|
|
|
|
|
|
/*
|
|
@@ -1914,20 +1937,8 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
|
|
|
}
|
|
|
|
|
|
done:
|
|
|
- if (spd.nr_pages) {
|
|
|
- /*
|
|
|
- * 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);
|
|
|
- }
|
|
|
+ if (spd.nr_pages)
|
|
|
+ ret = splice_cb(sk, pipe, &spd);
|
|
|
|
|
|
return ret;
|
|
|
}
|