diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2017-02-09 10:45:31 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2017-02-09 10:45:31 +1100 |
commit | 3f4f5b41d642af5e50ed36e80436d0a2cd51e272 (patch) | |
tree | 8a32dda99b4003d64966fb7168c19c2d3db452f6 /net | |
parent | df134f2d1211b675bd4fd23c5a2161efb15f5d3c (diff) | |
parent | 59479ae85e43a364d3380f82b1ddd8d04d13bd31 (diff) |
Merge remote-tracking branch 'vfs/for-next'
Diffstat (limited to 'net')
-rw-r--r-- | net/ceph/messenger.c | 44 | ||||
-rw-r--r-- | net/core/skbuff.c | 4 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 7 | ||||
-rw-r--r-- | net/kcm/kcmsock.c | 5 | ||||
-rw-r--r-- | net/rds/page.c | 29 | ||||
-rw-r--r-- | net/rds/rds.h | 7 | ||||
-rw-r--r-- | net/socket.c | 4 | ||||
-rw-r--r-- | net/unix/af_unix.c | 113 |
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; |