summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2017-02-09 10:45:31 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2017-02-09 10:45:31 +1100
commit3f4f5b41d642af5e50ed36e80436d0a2cd51e272 (patch)
tree8a32dda99b4003d64966fb7168c19c2d3db452f6 /net
parentdf134f2d1211b675bd4fd23c5a2161efb15f5d3c (diff)
parent59479ae85e43a364d3380f82b1ddd8d04d13bd31 (diff)
Merge remote-tracking branch 'vfs/for-next'
Diffstat (limited to 'net')
-rw-r--r--net/ceph/messenger.c44
-rw-r--r--net/core/skbuff.c4
-rw-r--r--net/ipv4/tcp.c7
-rw-r--r--net/kcm/kcmsock.c5
-rw-r--r--net/rds/page.c29
-rw-r--r--net/rds/rds.h7
-rw-r--r--net/socket.c4
-rw-r--r--net/unix/af_unix.c113
8 files changed, 49 insertions, 164 deletions
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index 770c52701efa..6f3b5754cc7e 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -520,7 +520,8 @@ static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len)
struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL };
int r;
- r = kernel_recvmsg(sock, &msg, &iov, 1, len, msg.msg_flags);
+ iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, len);
+ r = sock_recvmsg(sock, &msg, msg.msg_flags);
if (r == -EAGAIN)
r = 0;
return r;
@@ -529,17 +530,20 @@ static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len)
static int ceph_tcp_recvpage(struct socket *sock, struct page *page,
int page_offset, size_t length)
{
- void *kaddr;
- int ret;
+ struct bio_vec bvec = {
+ .bv_page = page,
+ .bv_offset = page_offset,
+ .bv_len = length
+ };
+ struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL };
+ int r;
BUG_ON(page_offset + length > PAGE_SIZE);
-
- kaddr = kmap(page);
- BUG_ON(!kaddr);
- ret = ceph_tcp_recvmsg(sock, kaddr + page_offset, length);
- kunmap(page);
-
- return ret;
+ iov_iter_bvec(&msg.msg_iter, READ | ITER_BVEC, &bvec, 1, length);
+ r = sock_recvmsg(sock, &msg, msg.msg_flags);
+ if (r == -EAGAIN)
+ r = 0;
+ return r;
}
/*
@@ -579,18 +583,28 @@ static int __ceph_tcp_sendpage(struct socket *sock, struct page *page,
static int ceph_tcp_sendpage(struct socket *sock, struct page *page,
int offset, size_t size, bool more)
{
+ struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL };
+ struct bio_vec bvec;
int ret;
- struct kvec iov;
/* sendpage cannot properly handle pages with page_count == 0,
* we need to fallback to sendmsg if that's the case */
if (page_count(page) >= 1)
return __ceph_tcp_sendpage(sock, page, offset, size, more);
- iov.iov_base = kmap(page) + offset;
- iov.iov_len = size;
- ret = ceph_tcp_sendmsg(sock, &iov, 1, size, more);
- kunmap(page);
+ bvec.bv_page = page;
+ bvec.bv_offset = offset;
+ bvec.bv_len = size;
+
+ if (more)
+ msg.msg_flags |= MSG_MORE;
+ else
+ msg.msg_flags |= MSG_EOR; /* superfluous, but what the hell */
+
+ iov_iter_bvec(&msg.msg_iter, WRITE | ITER_BVEC, &bvec, 1, size);
+ ret = sock_sendmsg(sock, &msg);
+ if (ret == -EAGAIN)
+ ret = 0;
return ret;
}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 734c71468b01..08f51e97603d 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1967,8 +1967,7 @@ static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe,
* the fragments, and the frag list.
*/
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)
+ struct pipe_inode_info *pipe, unsigned int tlen)
{
struct partial_page partial[MAX_SKB_FRAGS];
struct page *pages[MAX_SKB_FRAGS];
@@ -1976,7 +1975,6 @@ int skb_splice_bits(struct sk_buff *skb, struct sock *sk, unsigned int offset,
.pages = pages,
.partial = partial,
.nr_pages_max = MAX_SKB_FRAGS,
- .flags = flags,
.ops = &nosteal_pipe_buf_ops,
.spd_release = sock_spd_release,
};
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 0efb4c7f6704..d1c1d26e1a51 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -311,7 +311,6 @@ EXPORT_SYMBOL(tcp_sockets_allocated);
struct tcp_splice_state {
struct pipe_inode_info *pipe;
size_t len;
- unsigned int flags;
};
/*
@@ -687,7 +686,7 @@ static int tcp_splice_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
int ret;
ret = skb_splice_bits(skb, skb->sk, offset, tss->pipe,
- min(rd_desc->count, len), tss->flags);
+ min(rd_desc->count, len));
if (ret > 0)
rd_desc->count -= ret;
return ret;
@@ -716,15 +715,15 @@ static int __tcp_splice_read(struct sock *sk, struct tcp_splice_state *tss)
* Will read pages from given socket and fill them into a pipe.
*
**/
-ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,
+ssize_t tcp_splice_read(struct file *file, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
unsigned int flags)
{
+ struct socket *sock = file->private_data;
struct sock *sk = sock->sk;
struct tcp_splice_state tss = {
.pipe = pipe,
.len = len,
- .flags = flags,
};
long timeo;
ssize_t spliced;
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
index 7e08a4d3d77d..7d955d04816b 100644
--- a/net/kcm/kcmsock.c
+++ b/net/kcm/kcmsock.c
@@ -1160,10 +1160,11 @@ out:
return copied ? : err;
}
-static ssize_t kcm_splice_read(struct socket *sock, loff_t *ppos,
+static ssize_t kcm_splice_read(struct file *file, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
unsigned int flags)
{
+ struct socket *sock = file->private_data;
struct sock *sk = sock->sk;
struct kcm_sock *kcm = kcm_sk(sk);
long timeo;
@@ -1189,7 +1190,7 @@ static ssize_t kcm_splice_read(struct socket *sock, loff_t *ppos,
if (len > rxm->full_len)
len = rxm->full_len;
- copied = skb_splice_bits(skb, sk, rxm->offset, pipe, len, flags);
+ copied = skb_splice_bits(skb, sk, rxm->offset, pipe, len);
if (copied < 0) {
err = copied;
goto err_out;
diff --git a/net/rds/page.c b/net/rds/page.c
index e2b5a5832d3d..7cc57e098ddb 100644
--- a/net/rds/page.c
+++ b/net/rds/page.c
@@ -45,35 +45,6 @@ struct rds_page_remainder {
static
DEFINE_PER_CPU_SHARED_ALIGNED(struct rds_page_remainder, rds_page_remainders);
-/*
- * returns 0 on success or -errno on failure.
- *
- * We don't have to worry about flush_dcache_page() as this only works
- * with private pages. If, say, we were to do directed receive to pinned
- * user pages we'd have to worry more about cache coherence. (Though
- * the flush_dcache_page() in get_user_pages() would probably be enough).
- */
-int rds_page_copy_user(struct page *page, unsigned long offset,
- void __user *ptr, unsigned long bytes,
- int to_user)
-{
- unsigned long ret;
- void *addr;
-
- addr = kmap(page);
- if (to_user) {
- rds_stats_add(s_copy_to_user, bytes);
- ret = copy_to_user(ptr, addr + offset, bytes);
- } else {
- rds_stats_add(s_copy_from_user, bytes);
- ret = copy_from_user(addr + offset, ptr, bytes);
- }
- kunmap(page);
-
- return ret ? -EFAULT : 0;
-}
-EXPORT_SYMBOL_GPL(rds_page_copy_user);
-
/**
* rds_page_remainder_alloc - build up regions of a message.
*
diff --git a/net/rds/rds.h b/net/rds/rds.h
index ebbf909b87ec..8635993066ae 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -781,13 +781,6 @@ static inline int rds_message_verify_checksum(const struct rds_header *hdr)
/* page.c */
int rds_page_remainder_alloc(struct scatterlist *scat, unsigned long bytes,
gfp_t gfp);
-int rds_page_copy_user(struct page *page, unsigned long offset,
- void __user *ptr, unsigned long bytes,
- int to_user);
-#define rds_page_copy_to_user(page, offset, ptr, bytes) \
- rds_page_copy_user(page, offset, ptr, bytes, 1)
-#define rds_page_copy_from_user(page, offset, ptr, bytes) \
- rds_page_copy_user(page, offset, ptr, bytes, 0)
void rds_page_exit(void);
/* recv.c */
diff --git a/net/socket.c b/net/socket.c
index 0758e13754e2..4f7c0c04fc8f 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -803,7 +803,7 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
if (unlikely(!sock->ops->splice_read))
return -EINVAL;
- return sock->ops->splice_read(sock, ppos, pipe, len, flags);
+ return sock->ops->splice_read(file, ppos, pipe, len, flags);
}
static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
@@ -814,7 +814,7 @@ static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
.msg_iocb = iocb};
ssize_t res;
- if (file->f_flags & O_NONBLOCK)
+ if ((file->f_flags & O_NONBLOCK) || (iocb->ki_flags & IOCB_NDELAY))
msg.msg_flags = MSG_DONTWAIT;
if (iocb->ki_pos != 0)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index cef79873b09d..38995d62d605 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -646,9 +646,6 @@ static int unix_stream_sendmsg(struct socket *, struct msghdr *, size_t);
static int unix_stream_recvmsg(struct socket *, struct msghdr *, size_t, int);
static ssize_t unix_stream_sendpage(struct socket *, struct page *, int offset,
size_t size, int flags);
-static ssize_t unix_stream_splice_read(struct socket *, loff_t *ppos,
- struct pipe_inode_info *, size_t size,
- unsigned int flags);
static int unix_dgram_sendmsg(struct socket *, struct msghdr *, size_t);
static int unix_dgram_recvmsg(struct socket *, struct msghdr *, size_t, int);
static int unix_dgram_connect(struct socket *, struct sockaddr *,
@@ -690,7 +687,7 @@ static const struct proto_ops unix_stream_ops = {
.recvmsg = unix_stream_recvmsg,
.mmap = sock_no_mmap,
.sendpage = unix_stream_sendpage,
- .splice_read = unix_stream_splice_read,
+ .splice_read = generic_file_splice_read,
.set_peek_off = unix_set_peek_off,
};
@@ -2248,34 +2245,21 @@ static unsigned int unix_skb_len(const struct sk_buff *skb)
return skb->len - UNIXCB(skb).consumed;
}
-struct unix_stream_read_state {
- int (*recv_actor)(struct sk_buff *, int, int,
- struct unix_stream_read_state *);
- struct socket *socket;
- struct msghdr *msg;
- struct pipe_inode_info *pipe;
- size_t size;
- int flags;
- unsigned int splice_flags;
-};
-
-static int unix_stream_read_generic(struct unix_stream_read_state *state,
- bool freezable)
+static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg,
+ size_t size, int flags)
{
struct scm_cookie scm;
- struct socket *sock = state->socket;
struct sock *sk = sock->sk;
struct unix_sock *u = unix_sk(sk);
int copied = 0;
- int flags = state->flags;
int noblock = flags & MSG_DONTWAIT;
bool check_creds = false;
int target;
int err = 0;
long timeo;
int skip;
- size_t size = state->size;
unsigned int last_len;
+ bool freezable = !(msg->msg_iter.type & ITER_PIPE);
if (unlikely(sk->sk_state != TCP_ESTABLISHED)) {
err = -EINVAL;
@@ -2304,7 +2288,6 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
do {
int chunk;
- bool drop_skb;
struct sk_buff *skb, *last;
redo:
@@ -2378,20 +2361,16 @@ unlock:
}
/* Copy address just once */
- if (state->msg && state->msg->msg_name) {
+ if (msg->msg_name) {
DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr,
- state->msg->msg_name);
- unix_copy_addr(state->msg, skb->sk);
+ msg->msg_name);
+ unix_copy_addr(msg, skb->sk);
sunaddr = NULL;
}
chunk = min_t(unsigned int, unix_skb_len(skb) - skip, size);
- skb_get(skb);
- chunk = state->recv_actor(skb, skip, chunk, state);
- drop_skb = !unix_skb_len(skb);
- /* skb is only safe to use if !drop_skb */
- consume_skb(skb);
- if (chunk < 0) {
+ if (skb_copy_datagram_msg(skb, UNIXCB(skb).consumed + skip,
+ msg, chunk)) {
if (copied == 0)
copied = -EFAULT;
break;
@@ -2399,18 +2378,6 @@ unlock:
copied += chunk;
size -= chunk;
- if (drop_skb) {
- /* the skb was touched by a concurrent reader;
- * we should not expect anything from this skb
- * anymore and assume it invalid - we can be
- * sure it was dropped from the socket queue
- *
- * let's report a short read
- */
- err = 0;
- break;
- }
-
/* Mark read part of skb as used */
if (!(flags & MSG_PEEK)) {
UNIXCB(skb).consumed += chunk;
@@ -2452,70 +2419,12 @@ unlock:
} while (size);
mutex_unlock(&u->iolock);
- if (state->msg)
- scm_recv(sock, state->msg, &scm, flags);
- else
- scm_destroy(&scm);
+ if (msg)
+ scm_recv(sock, msg, &scm, flags);
out:
return copied ? : err;
}
-static int unix_stream_read_actor(struct sk_buff *skb,
- int skip, int chunk,
- struct unix_stream_read_state *state)
-{
- int ret;
-
- ret = skb_copy_datagram_msg(skb, UNIXCB(skb).consumed + skip,
- state->msg, chunk);
- return ret ?: chunk;
-}
-
-static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg,
- size_t size, int flags)
-{
- struct unix_stream_read_state state = {
- .recv_actor = unix_stream_read_actor,
- .socket = sock,
- .msg = msg,
- .size = size,
- .flags = flags
- };
-
- return unix_stream_read_generic(&state, true);
-}
-
-static int unix_stream_splice_actor(struct sk_buff *skb,
- int skip, int chunk,
- struct unix_stream_read_state *state)
-{
- return skb_splice_bits(skb, state->socket->sk,
- UNIXCB(skb).consumed + skip,
- state->pipe, chunk, state->splice_flags);
-}
-
-static ssize_t unix_stream_splice_read(struct socket *sock, loff_t *ppos,
- struct pipe_inode_info *pipe,
- size_t size, unsigned int flags)
-{
- struct unix_stream_read_state state = {
- .recv_actor = unix_stream_splice_actor,
- .socket = sock,
- .pipe = pipe,
- .size = size,
- .splice_flags = flags,
- };
-
- if (unlikely(*ppos))
- return -ESPIPE;
-
- if (sock->file->f_flags & O_NONBLOCK ||
- flags & SPLICE_F_NONBLOCK)
- state.flags = MSG_DONTWAIT;
-
- return unix_stream_read_generic(&state, false);
-}
-
static int unix_shutdown(struct socket *sock, int mode)
{
struct sock *sk = sock->sk;