forked from Minki/linux
Merge branch 'for-davem-2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
More iov_iter work for the networking from Al Viro. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
6e5f59aacb
@ -42,7 +42,7 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
struct hash_ctx *ctx = ask->private;
|
||||
unsigned long iovlen;
|
||||
struct iovec *iov;
|
||||
const struct iovec *iov;
|
||||
long copied = 0;
|
||||
int err;
|
||||
|
||||
@ -58,7 +58,7 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
|
||||
|
||||
ctx->more = 0;
|
||||
|
||||
for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
|
||||
for (iov = msg->msg_iter.iov, iovlen = msg->msg_iter.nr_segs; iovlen > 0;
|
||||
iovlen--, iov++) {
|
||||
unsigned long seglen = iov->iov_len;
|
||||
char __user *from = iov->iov_base;
|
||||
|
@ -429,13 +429,13 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock,
|
||||
struct skcipher_sg_list *sgl;
|
||||
struct scatterlist *sg;
|
||||
unsigned long iovlen;
|
||||
struct iovec *iov;
|
||||
const struct iovec *iov;
|
||||
int err = -EAGAIN;
|
||||
int used;
|
||||
long copied = 0;
|
||||
|
||||
lock_sock(sk);
|
||||
for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
|
||||
for (iov = msg->msg_iter.iov, iovlen = msg->msg_iter.nr_segs; iovlen > 0;
|
||||
iovlen--, iov++) {
|
||||
unsigned long seglen = iov->iov_len;
|
||||
char __user *from = iov->iov_base;
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <linux/uio.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#include "vmci_handle_array.h"
|
||||
#include "vmci_queue_pair.h"
|
||||
@ -429,11 +430,11 @@ static int __qp_memcpy_from_queue(void *dest,
|
||||
to_copy = size - bytes_copied;
|
||||
|
||||
if (is_iovec) {
|
||||
struct iovec *iov = (struct iovec *)dest;
|
||||
struct msghdr *msg = dest;
|
||||
int err;
|
||||
|
||||
/* The iovec will track bytes_copied internally. */
|
||||
err = memcpy_toiovec(iov, (u8 *)va + page_offset,
|
||||
err = memcpy_to_msg(msg, (u8 *)va + page_offset,
|
||||
to_copy);
|
||||
if (err != 0) {
|
||||
if (kernel_if->host)
|
||||
@ -3264,13 +3265,13 @@ EXPORT_SYMBOL_GPL(vmci_qpair_enquev);
|
||||
* of bytes dequeued or < 0 on error.
|
||||
*/
|
||||
ssize_t vmci_qpair_dequev(struct vmci_qp *qpair,
|
||||
void *iov,
|
||||
struct msghdr *msg,
|
||||
size_t iov_size,
|
||||
int buf_type)
|
||||
{
|
||||
ssize_t result;
|
||||
|
||||
if (!qpair || !iov)
|
||||
if (!qpair)
|
||||
return VMCI_ERROR_INVALID_ARGS;
|
||||
|
||||
qp_lock(qpair);
|
||||
@ -3279,7 +3280,7 @@ ssize_t vmci_qpair_dequev(struct vmci_qp *qpair,
|
||||
result = qp_dequeue_locked(qpair->produce_q,
|
||||
qpair->consume_q,
|
||||
qpair->consume_q_size,
|
||||
iov, iov_size,
|
||||
msg, iov_size,
|
||||
qp_memcpy_from_queue_iov,
|
||||
true);
|
||||
|
||||
@ -3308,13 +3309,13 @@ EXPORT_SYMBOL_GPL(vmci_qpair_dequev);
|
||||
* of bytes peeked or < 0 on error.
|
||||
*/
|
||||
ssize_t vmci_qpair_peekv(struct vmci_qp *qpair,
|
||||
void *iov,
|
||||
struct msghdr *msg,
|
||||
size_t iov_size,
|
||||
int buf_type)
|
||||
{
|
||||
ssize_t result;
|
||||
|
||||
if (!qpair || !iov)
|
||||
if (!qpair)
|
||||
return VMCI_ERROR_INVALID_ARGS;
|
||||
|
||||
qp_lock(qpair);
|
||||
@ -3323,7 +3324,7 @@ ssize_t vmci_qpair_peekv(struct vmci_qp *qpair,
|
||||
result = qp_dequeue_locked(qpair->produce_q,
|
||||
qpair->consume_q,
|
||||
qpair->consume_q_size,
|
||||
iov, iov_size,
|
||||
msg, iov_size,
|
||||
qp_memcpy_from_queue_iov,
|
||||
false);
|
||||
|
||||
|
@ -1095,9 +1095,7 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||
struct msghdr *m, size_t total_len)
|
||||
{
|
||||
struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
|
||||
struct iov_iter from;
|
||||
iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len);
|
||||
return macvtap_get_user(q, m, &from, m->msg_flags & MSG_DONTWAIT);
|
||||
return macvtap_get_user(q, m, &m->msg_iter, m->msg_flags & MSG_DONTWAIT);
|
||||
}
|
||||
|
||||
static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
@ -1105,12 +1103,10 @@ static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
int flags)
|
||||
{
|
||||
struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
|
||||
struct iov_iter to;
|
||||
int ret;
|
||||
if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
|
||||
return -EINVAL;
|
||||
iov_iter_init(&to, READ, m->msg_iov, m->msg_iovlen, total_len);
|
||||
ret = macvtap_do_read(q, &to, flags & MSG_DONTWAIT);
|
||||
ret = macvtap_do_read(q, &m->msg_iter, flags & MSG_DONTWAIT);
|
||||
if (ret > total_len) {
|
||||
m->msg_flags |= MSG_TRUNC;
|
||||
ret = flags & MSG_TRUNC ? ret : total_len;
|
||||
|
@ -417,6 +417,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
|
||||
ssize_t ret;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct iovec iov;
|
||||
struct iov_iter to;
|
||||
|
||||
ret = count;
|
||||
|
||||
@ -462,7 +463,8 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
|
||||
ret = -EFAULT;
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = count;
|
||||
if (skb_copy_datagram_iovec(skb, 0, &iov, skb->len))
|
||||
iov_iter_init(&to, READ, &iov, 1, count);
|
||||
if (skb_copy_datagram_iter(skb, 0, &to, skb->len))
|
||||
goto outf;
|
||||
ret = skb->len;
|
||||
|
||||
|
@ -1449,13 +1449,11 @@ static int tun_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||
int ret;
|
||||
struct tun_file *tfile = container_of(sock, struct tun_file, socket);
|
||||
struct tun_struct *tun = __tun_get(tfile);
|
||||
struct iov_iter from;
|
||||
|
||||
if (!tun)
|
||||
return -EBADFD;
|
||||
|
||||
iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len);
|
||||
ret = tun_get_user(tun, tfile, m->msg_control, &from,
|
||||
ret = tun_get_user(tun, tfile, m->msg_control, &m->msg_iter,
|
||||
m->msg_flags & MSG_DONTWAIT);
|
||||
tun_put(tun);
|
||||
return ret;
|
||||
@ -1467,7 +1465,6 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
{
|
||||
struct tun_file *tfile = container_of(sock, struct tun_file, socket);
|
||||
struct tun_struct *tun = __tun_get(tfile);
|
||||
struct iov_iter to;
|
||||
int ret;
|
||||
|
||||
if (!tun)
|
||||
@ -1482,8 +1479,7 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
SOL_PACKET, TUN_TX_TIMESTAMP);
|
||||
goto out;
|
||||
}
|
||||
iov_iter_init(&to, READ, m->msg_iov, m->msg_iovlen, total_len);
|
||||
ret = tun_do_read(tun, tfile, &to, flags & MSG_DONTWAIT);
|
||||
ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT);
|
||||
if (ret > total_len) {
|
||||
m->msg_flags |= MSG_TRUNC;
|
||||
ret = flags & MSG_TRUNC ? ret : total_len;
|
||||
|
@ -1326,21 +1326,19 @@ static int iscsit_do_rx_data(
|
||||
struct iscsi_conn *conn,
|
||||
struct iscsi_data_count *count)
|
||||
{
|
||||
int data = count->data_length, rx_loop = 0, total_rx = 0, iov_len;
|
||||
struct kvec *iov_p;
|
||||
int data = count->data_length, rx_loop = 0, total_rx = 0;
|
||||
struct msghdr msg;
|
||||
|
||||
if (!conn || !conn->sock || !conn->conn_ops)
|
||||
return -1;
|
||||
|
||||
memset(&msg, 0, sizeof(struct msghdr));
|
||||
|
||||
iov_p = count->iov;
|
||||
iov_len = count->iov_count;
|
||||
iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC,
|
||||
count->iov, count->iov_count, data);
|
||||
|
||||
while (total_rx < data) {
|
||||
rx_loop = kernel_recvmsg(conn->sock, &msg, iov_p, iov_len,
|
||||
(data - total_rx), MSG_WAITALL);
|
||||
rx_loop = sock_recvmsg(conn->sock, &msg,
|
||||
(data - total_rx), MSG_WAITALL);
|
||||
if (rx_loop <= 0) {
|
||||
pr_debug("rx_loop: %d total_rx: %d\n",
|
||||
rx_loop, total_rx);
|
||||
|
@ -342,7 +342,6 @@ static void handle_tx(struct vhost_net *net)
|
||||
.msg_namelen = 0,
|
||||
.msg_control = NULL,
|
||||
.msg_controllen = 0,
|
||||
.msg_iov = vq->iov,
|
||||
.msg_flags = MSG_DONTWAIT,
|
||||
};
|
||||
size_t len, total_len = 0;
|
||||
@ -396,8 +395,8 @@ static void handle_tx(struct vhost_net *net)
|
||||
}
|
||||
/* Skip header. TODO: support TSO. */
|
||||
s = move_iovec_hdr(vq->iov, nvq->hdr, hdr_size, out);
|
||||
msg.msg_iovlen = out;
|
||||
len = iov_length(vq->iov, out);
|
||||
iov_iter_init(&msg.msg_iter, WRITE, vq->iov, out, len);
|
||||
/* Sanity check */
|
||||
if (!len) {
|
||||
vq_err(vq, "Unexpected header len for TX: "
|
||||
@ -562,7 +561,6 @@ static void handle_rx(struct vhost_net *net)
|
||||
.msg_namelen = 0,
|
||||
.msg_control = NULL, /* FIXME: get and handle RX aux data. */
|
||||
.msg_controllen = 0,
|
||||
.msg_iov = vq->iov,
|
||||
.msg_flags = MSG_DONTWAIT,
|
||||
};
|
||||
struct virtio_net_hdr_mrg_rxbuf hdr = {
|
||||
@ -600,7 +598,7 @@ static void handle_rx(struct vhost_net *net)
|
||||
break;
|
||||
/* On overrun, truncate and discard */
|
||||
if (unlikely(headcount > UIO_MAXIOV)) {
|
||||
msg.msg_iovlen = 1;
|
||||
iov_iter_init(&msg.msg_iter, READ, vq->iov, 1, 1);
|
||||
err = sock->ops->recvmsg(NULL, sock, &msg,
|
||||
1, MSG_DONTWAIT | MSG_TRUNC);
|
||||
pr_debug("Discarded rx packet: len %zd\n", sock_len);
|
||||
@ -626,7 +624,7 @@ static void handle_rx(struct vhost_net *net)
|
||||
/* Copy the header for use in VIRTIO_NET_F_MRG_RXBUF:
|
||||
* needed because recvmsg can modify msg_iov. */
|
||||
copy_iovec_hdr(vq->iov, nvq->hdr, sock_hlen, in);
|
||||
msg.msg_iovlen = in;
|
||||
iov_iter_init(&msg.msg_iter, READ, vq->iov, in, sock_len);
|
||||
err = sock->ops->recvmsg(NULL, sock, &msg,
|
||||
sock_len, MSG_DONTWAIT | MSG_TRUNC);
|
||||
/* Userspace might have consumed the packet meanwhile:
|
||||
|
@ -306,8 +306,8 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg,
|
||||
|
||||
_debug("- range %u-%u%s",
|
||||
offset, to, msg->msg_flags ? " [more]" : "");
|
||||
msg->msg_iov = (struct iovec *) iov;
|
||||
msg->msg_iovlen = 1;
|
||||
iov_iter_init(&msg->msg_iter, WRITE,
|
||||
(struct iovec *) iov, 1, to - offset);
|
||||
|
||||
/* have to change the state *before* sending the last
|
||||
* packet as RxRPC might give us the reply before it
|
||||
@ -384,8 +384,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
|
||||
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = (struct iovec *) iov;
|
||||
msg.msg_iovlen = 1;
|
||||
iov_iter_init(&msg.msg_iter, WRITE, (struct iovec *)iov, 1,
|
||||
call->request_size);
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = (call->send_pages ? MSG_MORE : 0);
|
||||
@ -778,8 +778,7 @@ void afs_send_empty_reply(struct afs_call *call)
|
||||
iov[0].iov_len = 0;
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 0;
|
||||
iov_iter_init(&msg.msg_iter, WRITE, iov, 0, 0); /* WTF? */
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = 0;
|
||||
@ -815,8 +814,7 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
|
||||
iov[0].iov_len = len;
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
iov_iter_init(&msg.msg_iter, WRITE, iov, 1, len);
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = 0;
|
||||
|
@ -2644,24 +2644,17 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock,
|
||||
int *err);
|
||||
unsigned int datagram_poll(struct file *file, struct socket *sock,
|
||||
struct poll_table_struct *wait);
|
||||
int skb_copy_datagram_iovec(const struct sk_buff *from, int offset,
|
||||
struct iovec *to, int size);
|
||||
int skb_copy_datagram_iter(const struct sk_buff *from, int offset,
|
||||
struct iov_iter *to, int size);
|
||||
static inline int skb_copy_datagram_msg(const struct sk_buff *from, int offset,
|
||||
struct msghdr *msg, int size)
|
||||
{
|
||||
return skb_copy_datagram_iovec(from, offset, msg->msg_iov, size);
|
||||
}
|
||||
int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen,
|
||||
struct iovec *iov);
|
||||
static inline int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen,
|
||||
struct msghdr *msg)
|
||||
{
|
||||
return skb_copy_and_csum_datagram_iovec(skb, hlen, msg->msg_iov);
|
||||
return skb_copy_datagram_iter(from, offset, &msg->msg_iter, size);
|
||||
}
|
||||
int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen,
|
||||
struct msghdr *msg);
|
||||
int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset,
|
||||
struct iov_iter *from, int len);
|
||||
int skb_copy_datagram_iter(const struct sk_buff *from, int offset,
|
||||
struct iov_iter *to, int size);
|
||||
int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *frm);
|
||||
void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
|
||||
void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb);
|
||||
@ -2689,12 +2682,13 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
|
||||
|
||||
static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len)
|
||||
{
|
||||
return memcpy_fromiovec(data, msg->msg_iov, len);
|
||||
/* XXX: stripping const */
|
||||
return memcpy_fromiovec(data, (struct iovec *)msg->msg_iter.iov, len);
|
||||
}
|
||||
|
||||
static inline int memcpy_to_msg(struct msghdr *msg, void *data, int len)
|
||||
{
|
||||
return memcpy_toiovec(msg->msg_iov, data, len);
|
||||
return copy_to_iter(data, len, &msg->msg_iter) == len ? 0 : -EFAULT;
|
||||
}
|
||||
|
||||
struct skb_checksum_ops {
|
||||
|
@ -47,8 +47,7 @@ struct linger {
|
||||
struct msghdr {
|
||||
void *msg_name; /* ptr to socket address structure */
|
||||
int msg_namelen; /* size of socket address structure */
|
||||
struct iovec *msg_iov; /* scatter/gather array */
|
||||
__kernel_size_t msg_iovlen; /* # elements in msg_iov */
|
||||
struct iov_iter msg_iter; /* data */
|
||||
void *msg_control; /* ancillary data */
|
||||
__kernel_size_t msg_controllen; /* ancillary data buffer length */
|
||||
unsigned int msg_flags; /* flags on received message */
|
||||
|
@ -162,7 +162,7 @@ struct tcp_sock {
|
||||
struct {
|
||||
struct sk_buff_head prequeue;
|
||||
struct task_struct *task;
|
||||
struct iovec *iov;
|
||||
struct msghdr *msg;
|
||||
int memory;
|
||||
int len;
|
||||
} ucopy;
|
||||
|
@ -31,6 +31,7 @@ struct iov_iter {
|
||||
size_t count;
|
||||
union {
|
||||
const struct iovec *iov;
|
||||
const struct kvec *kvec;
|
||||
const struct bio_vec *bvec;
|
||||
};
|
||||
unsigned long nr_segs;
|
||||
@ -82,10 +83,13 @@ size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes,
|
||||
struct iov_iter *i);
|
||||
size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i);
|
||||
size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i);
|
||||
size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i);
|
||||
size_t iov_iter_zero(size_t bytes, struct iov_iter *);
|
||||
unsigned long iov_iter_alignment(const struct iov_iter *i);
|
||||
void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov,
|
||||
unsigned long nr_segs, size_t count);
|
||||
void iov_iter_kvec(struct iov_iter *i, int direction, const struct kvec *iov,
|
||||
unsigned long nr_segs, size_t count);
|
||||
ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages,
|
||||
size_t maxsize, unsigned maxpages, size_t *start);
|
||||
ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages,
|
||||
@ -123,9 +127,10 @@ static inline void iov_iter_reexpand(struct iov_iter *i, size_t count)
|
||||
{
|
||||
i->count = count;
|
||||
}
|
||||
size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
|
||||
size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
|
||||
|
||||
int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
|
||||
int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len);
|
||||
int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
|
||||
int offset, int len);
|
||||
int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define VMCI_KERNEL_API_VERSION_2 2
|
||||
#define VMCI_KERNEL_API_VERSION VMCI_KERNEL_API_VERSION_2
|
||||
|
||||
struct msghdr;
|
||||
typedef void (vmci_device_shutdown_fn) (void *device_registration,
|
||||
void *user_data);
|
||||
|
||||
@ -75,8 +76,8 @@ ssize_t vmci_qpair_peek(struct vmci_qp *qpair, void *buf, size_t buf_size,
|
||||
ssize_t vmci_qpair_enquev(struct vmci_qp *qpair,
|
||||
void *iov, size_t iov_size, int mode);
|
||||
ssize_t vmci_qpair_dequev(struct vmci_qp *qpair,
|
||||
void *iov, size_t iov_size, int mode);
|
||||
ssize_t vmci_qpair_peekv(struct vmci_qp *qpair, void *iov, size_t iov_size,
|
||||
struct msghdr *msg, size_t iov_size, int mode);
|
||||
ssize_t vmci_qpair_peekv(struct vmci_qp *qpair, struct msghdr *msg, size_t iov_size,
|
||||
int mode);
|
||||
|
||||
#endif /* !__VMW_VMCI_API_H__ */
|
||||
|
@ -608,10 +608,6 @@ struct l2cap_ops {
|
||||
struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan,
|
||||
unsigned long hdr_len,
|
||||
unsigned long len, int nb);
|
||||
int (*memcpy_fromiovec) (struct l2cap_chan *chan,
|
||||
unsigned char *kdata,
|
||||
struct iovec *iov,
|
||||
int len);
|
||||
};
|
||||
|
||||
struct l2cap_conn {
|
||||
@ -905,31 +901,6 @@ static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int l2cap_chan_no_memcpy_fromiovec(struct l2cap_chan *chan,
|
||||
unsigned char *kdata,
|
||||
struct iovec *iov,
|
||||
int len)
|
||||
{
|
||||
/* Following is safe since for compiler definitions of kvec and
|
||||
* iovec are identical, yielding the same in-core layout and alignment
|
||||
*/
|
||||
struct kvec *vec = (struct kvec *)iov;
|
||||
|
||||
while (len > 0) {
|
||||
if (vec->iov_len) {
|
||||
int copy = min_t(unsigned int, len, vec->iov_len);
|
||||
memcpy(kdata, vec->iov_base, copy);
|
||||
len -= copy;
|
||||
kdata += copy;
|
||||
vec->iov_base += copy;
|
||||
vec->iov_len -= copy;
|
||||
}
|
||||
vec++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern bool disable_ertm;
|
||||
|
||||
int l2cap_init_sockets(void);
|
||||
|
@ -19,7 +19,9 @@ extern struct udp_table udplite_table;
|
||||
static __inline__ int udplite_getfrag(void *from, char *to, int offset,
|
||||
int len, int odd, struct sk_buff *skb)
|
||||
{
|
||||
return memcpy_fromiovecend(to, (struct iovec *) from, offset, len);
|
||||
struct msghdr *msg = from;
|
||||
/* XXX: stripping const */
|
||||
return memcpy_fromiovecend(to, (struct iovec *)msg->msg_iter.iov, offset, len);
|
||||
}
|
||||
|
||||
/* Designate sk as UDP-Lite socket */
|
||||
|
25
lib/iovec.c
25
lib/iovec.c
@ -27,31 +27,6 @@ int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
|
||||
}
|
||||
EXPORT_SYMBOL(memcpy_fromiovec);
|
||||
|
||||
/*
|
||||
* Copy kernel to iovec. Returns -EFAULT on error.
|
||||
*
|
||||
* Note: this modifies the original iovec.
|
||||
*/
|
||||
|
||||
int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
|
||||
{
|
||||
while (len > 0) {
|
||||
if (iov->iov_len) {
|
||||
int copy = min_t(unsigned int, iov->iov_len, len);
|
||||
if (copy_to_user(iov->iov_base, kdata, copy))
|
||||
return -EFAULT;
|
||||
kdata += copy;
|
||||
len -= copy;
|
||||
iov->iov_len -= copy;
|
||||
iov->iov_base += copy;
|
||||
}
|
||||
iov++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(memcpy_toiovec);
|
||||
|
||||
/*
|
||||
* Copy kernel to iovec. Returns -EFAULT on error.
|
||||
*/
|
||||
|
1068
mm/iov_iter.c
1068
mm/iov_iter.c
File diff suppressed because it is too large
Load Diff
@ -577,9 +577,6 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
|
||||
struct atm_vcc *vcc;
|
||||
struct sk_buff *skb;
|
||||
int eff, error;
|
||||
struct iov_iter from;
|
||||
|
||||
iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, size);
|
||||
|
||||
lock_sock(sk);
|
||||
if (sock->state != SS_CONNECTED) {
|
||||
@ -634,7 +631,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
|
||||
goto out;
|
||||
skb->dev = NULL; /* for paths shared with net_device interfaces */
|
||||
ATM_SKB(skb)->atm_options = vcc->atm_options;
|
||||
if (copy_from_iter(skb_put(skb, size), size, &from) != size) {
|
||||
if (copy_from_iter(skb_put(skb, size), size, &m->msg_iter) != size) {
|
||||
kfree_skb(skb);
|
||||
error = -EFAULT;
|
||||
goto out;
|
||||
|
@ -537,12 +537,12 @@ static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb,
|
||||
*/
|
||||
chan->data = skb;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msg_iov = (struct iovec *) &iv;
|
||||
msg.msg_iovlen = 1;
|
||||
iv.iov_base = skb->data;
|
||||
iv.iov_len = skb->len;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, skb->len);
|
||||
|
||||
err = l2cap_chan_send(chan, &msg, skb->len);
|
||||
if (err > 0) {
|
||||
netdev->stats.tx_bytes += err;
|
||||
@ -1050,7 +1050,6 @@ static const struct l2cap_ops bt_6lowpan_chan_ops = {
|
||||
.suspend = chan_suspend_cb,
|
||||
.get_sndtimeo = chan_get_sndtimeo_cb,
|
||||
.alloc_skb = chan_alloc_skb_cb,
|
||||
.memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
|
||||
|
||||
.teardown = l2cap_chan_no_teardown,
|
||||
.defer = l2cap_chan_no_defer,
|
||||
|
@ -60,8 +60,7 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
msg.msg_iov = (struct iovec *) &iv;
|
||||
msg.msg_iovlen = 1;
|
||||
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, total_len);
|
||||
|
||||
l2cap_chan_send(chan, &msg, total_len);
|
||||
|
||||
@ -720,7 +719,6 @@ static const struct l2cap_ops a2mp_chan_ops = {
|
||||
.resume = l2cap_chan_no_resume,
|
||||
.set_shutdown = l2cap_chan_no_set_shutdown,
|
||||
.get_sndtimeo = l2cap_chan_no_get_sndtimeo,
|
||||
.memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
|
||||
};
|
||||
|
||||
static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
|
||||
|
@ -2103,8 +2103,7 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
|
||||
struct sk_buff **frag;
|
||||
int sent = 0;
|
||||
|
||||
if (chan->ops->memcpy_fromiovec(chan, skb_put(skb, count),
|
||||
msg->msg_iov, count))
|
||||
if (copy_from_iter(skb_put(skb, count), count, &msg->msg_iter) != count)
|
||||
return -EFAULT;
|
||||
|
||||
sent += count;
|
||||
@ -2124,8 +2123,8 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan,
|
||||
|
||||
*frag = tmp;
|
||||
|
||||
if (chan->ops->memcpy_fromiovec(chan, skb_put(*frag, count),
|
||||
msg->msg_iov, count))
|
||||
if (copy_from_iter(skb_put(*frag, count), count,
|
||||
&msg->msg_iter) != count)
|
||||
return -EFAULT;
|
||||
|
||||
sent += count;
|
||||
|
@ -1336,13 +1336,6 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int l2cap_sock_memcpy_fromiovec_cb(struct l2cap_chan *chan,
|
||||
unsigned char *kdata,
|
||||
struct iovec *iov, int len)
|
||||
{
|
||||
return memcpy_fromiovec(kdata, iov, len);
|
||||
}
|
||||
|
||||
static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
|
||||
{
|
||||
struct sock *sk = chan->data;
|
||||
@ -1427,7 +1420,6 @@ static const struct l2cap_ops l2cap_chan_ops = {
|
||||
.set_shutdown = l2cap_sock_set_shutdown_cb,
|
||||
.get_sndtimeo = l2cap_sock_get_sndtimeo_cb,
|
||||
.alloc_skb = l2cap_sock_alloc_skb_cb,
|
||||
.memcpy_fromiovec = l2cap_sock_memcpy_fromiovec_cb,
|
||||
};
|
||||
|
||||
static void l2cap_sock_destruct(struct sock *sk)
|
||||
|
@ -539,8 +539,7 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
msg.msg_iov = (struct iovec *) &iv;
|
||||
msg.msg_iovlen = 2;
|
||||
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, iv, 2, 1 + len);
|
||||
|
||||
l2cap_chan_send(chan, &msg, 1 + len);
|
||||
|
||||
@ -2865,7 +2864,6 @@ static const struct l2cap_ops smp_chan_ops = {
|
||||
.suspend = l2cap_chan_no_suspend,
|
||||
.set_shutdown = l2cap_chan_no_set_shutdown,
|
||||
.get_sndtimeo = l2cap_chan_no_get_sndtimeo,
|
||||
.memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
|
||||
};
|
||||
|
||||
static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
|
||||
@ -2914,7 +2912,6 @@ static const struct l2cap_ops smp_root_chan_ops = {
|
||||
.resume = l2cap_chan_no_resume,
|
||||
.set_shutdown = l2cap_chan_no_set_shutdown,
|
||||
.get_sndtimeo = l2cap_chan_no_get_sndtimeo,
|
||||
.memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
|
||||
};
|
||||
|
||||
static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
|
||||
|
@ -535,7 +535,7 @@ static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||||
goto err;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (unlikely(msg->msg_iov->iov_base == NULL))
|
||||
if (unlikely(msg->msg_iter.iov->iov_base == NULL))
|
||||
goto err;
|
||||
noblock = msg->msg_flags & MSG_DONTWAIT;
|
||||
|
||||
|
10
net/compat.c
10
net/compat.c
@ -37,13 +37,14 @@ ssize_t get_compat_msghdr(struct msghdr *kmsg,
|
||||
struct iovec **iov)
|
||||
{
|
||||
compat_uptr_t uaddr, uiov, tmp3;
|
||||
compat_size_t nr_segs;
|
||||
ssize_t err;
|
||||
|
||||
if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
|
||||
__get_user(uaddr, &umsg->msg_name) ||
|
||||
__get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
|
||||
__get_user(uiov, &umsg->msg_iov) ||
|
||||
__get_user(kmsg->msg_iovlen, &umsg->msg_iovlen) ||
|
||||
__get_user(nr_segs, &umsg->msg_iovlen) ||
|
||||
__get_user(tmp3, &umsg->msg_control) ||
|
||||
__get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
|
||||
__get_user(kmsg->msg_flags, &umsg->msg_flags))
|
||||
@ -68,14 +69,15 @@ ssize_t get_compat_msghdr(struct msghdr *kmsg,
|
||||
kmsg->msg_namelen = 0;
|
||||
}
|
||||
|
||||
if (kmsg->msg_iovlen > UIO_MAXIOV)
|
||||
if (nr_segs > UIO_MAXIOV)
|
||||
return -EMSGSIZE;
|
||||
|
||||
err = compat_rw_copy_check_uvector(save_addr ? READ : WRITE,
|
||||
compat_ptr(uiov), kmsg->msg_iovlen,
|
||||
compat_ptr(uiov), nr_segs,
|
||||
UIO_FASTIOV, *iov, iov);
|
||||
if (err >= 0)
|
||||
kmsg->msg_iov = *iov;
|
||||
iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE,
|
||||
*iov, nr_segs, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -309,90 +309,6 @@ int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags)
|
||||
}
|
||||
EXPORT_SYMBOL(skb_kill_datagram);
|
||||
|
||||
/**
|
||||
* skb_copy_datagram_iovec - Copy a datagram to an iovec.
|
||||
* @skb: buffer to copy
|
||||
* @offset: offset in the buffer to start copying from
|
||||
* @to: io vector to copy to
|
||||
* @len: amount of data to copy from buffer to iovec
|
||||
*
|
||||
* Note: the iovec is modified during the copy.
|
||||
*/
|
||||
int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
|
||||
struct iovec *to, int len)
|
||||
{
|
||||
int start = skb_headlen(skb);
|
||||
int i, copy = start - offset;
|
||||
struct sk_buff *frag_iter;
|
||||
|
||||
trace_skb_copy_datagram_iovec(skb, len);
|
||||
|
||||
/* Copy header. */
|
||||
if (copy > 0) {
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
if (memcpy_toiovec(to, skb->data + offset, copy))
|
||||
goto fault;
|
||||
if ((len -= copy) == 0)
|
||||
return 0;
|
||||
offset += copy;
|
||||
}
|
||||
|
||||
/* Copy paged appendix. Hmm... why does this look so complicated? */
|
||||
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
||||
int end;
|
||||
const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
||||
|
||||
WARN_ON(start > offset + len);
|
||||
|
||||
end = start + skb_frag_size(frag);
|
||||
if ((copy = end - offset) > 0) {
|
||||
int err;
|
||||
u8 *vaddr;
|
||||
struct page *page = skb_frag_page(frag);
|
||||
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
vaddr = kmap(page);
|
||||
err = memcpy_toiovec(to, vaddr + frag->page_offset +
|
||||
offset - start, copy);
|
||||
kunmap(page);
|
||||
if (err)
|
||||
goto fault;
|
||||
if (!(len -= copy))
|
||||
return 0;
|
||||
offset += copy;
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
|
||||
skb_walk_frags(skb, frag_iter) {
|
||||
int end;
|
||||
|
||||
WARN_ON(start > offset + len);
|
||||
|
||||
end = start + frag_iter->len;
|
||||
if ((copy = end - offset) > 0) {
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
if (skb_copy_datagram_iovec(frag_iter,
|
||||
offset - start,
|
||||
to, copy))
|
||||
goto fault;
|
||||
if ((len -= copy) == 0)
|
||||
return 0;
|
||||
offset += copy;
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
fault:
|
||||
return -EFAULT;
|
||||
}
|
||||
EXPORT_SYMBOL(skb_copy_datagram_iovec);
|
||||
|
||||
/**
|
||||
* skb_copy_datagram_iter - Copy a datagram to an iovec iterator.
|
||||
* @skb: buffer to copy
|
||||
@ -615,27 +531,25 @@ int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *from)
|
||||
EXPORT_SYMBOL(zerocopy_sg_from_iter);
|
||||
|
||||
static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
|
||||
u8 __user *to, int len,
|
||||
struct iov_iter *to, int len,
|
||||
__wsum *csump)
|
||||
{
|
||||
int start = skb_headlen(skb);
|
||||
int i, copy = start - offset;
|
||||
struct sk_buff *frag_iter;
|
||||
int pos = 0;
|
||||
int n;
|
||||
|
||||
/* Copy header. */
|
||||
if (copy > 0) {
|
||||
int err = 0;
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
*csump = csum_and_copy_to_user(skb->data + offset, to, copy,
|
||||
*csump, &err);
|
||||
if (err)
|
||||
n = csum_and_copy_to_iter(skb->data + offset, copy, csump, to);
|
||||
if (n != copy)
|
||||
goto fault;
|
||||
if ((len -= copy) == 0)
|
||||
return 0;
|
||||
offset += copy;
|
||||
to += copy;
|
||||
pos = copy;
|
||||
}
|
||||
|
||||
@ -647,26 +561,22 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
|
||||
|
||||
end = start + skb_frag_size(frag);
|
||||
if ((copy = end - offset) > 0) {
|
||||
__wsum csum2;
|
||||
int err = 0;
|
||||
u8 *vaddr;
|
||||
__wsum csum2 = 0;
|
||||
struct page *page = skb_frag_page(frag);
|
||||
u8 *vaddr = kmap(page);
|
||||
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
vaddr = kmap(page);
|
||||
csum2 = csum_and_copy_to_user(vaddr +
|
||||
frag->page_offset +
|
||||
offset - start,
|
||||
to, copy, 0, &err);
|
||||
n = csum_and_copy_to_iter(vaddr + frag->page_offset +
|
||||
offset - start, copy,
|
||||
&csum2, to);
|
||||
kunmap(page);
|
||||
if (err)
|
||||
if (n != copy)
|
||||
goto fault;
|
||||
*csump = csum_block_add(*csump, csum2, pos);
|
||||
if (!(len -= copy))
|
||||
return 0;
|
||||
offset += copy;
|
||||
to += copy;
|
||||
pos += copy;
|
||||
}
|
||||
start = end;
|
||||
@ -691,7 +601,6 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset,
|
||||
if ((len -= copy) == 0)
|
||||
return 0;
|
||||
offset += copy;
|
||||
to += copy;
|
||||
pos += copy;
|
||||
}
|
||||
start = end;
|
||||
@ -744,20 +653,19 @@ __sum16 __skb_checksum_complete(struct sk_buff *skb)
|
||||
EXPORT_SYMBOL(__skb_checksum_complete);
|
||||
|
||||
/**
|
||||
* skb_copy_and_csum_datagram_iovec - Copy and checksum skb to user iovec.
|
||||
* skb_copy_and_csum_datagram_msg - Copy and checksum skb to user iovec.
|
||||
* @skb: skbuff
|
||||
* @hlen: hardware length
|
||||
* @iov: io vector
|
||||
* @msg: destination
|
||||
*
|
||||
* Caller _must_ check that skb will fit to this iovec.
|
||||
*
|
||||
* Returns: 0 - success.
|
||||
* -EINVAL - checksum failure.
|
||||
* -EFAULT - fault during copy. Beware, in this case iovec
|
||||
* can be modified!
|
||||
* -EFAULT - fault during copy.
|
||||
*/
|
||||
int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
|
||||
int hlen, struct iovec *iov)
|
||||
int skb_copy_and_csum_datagram_msg(struct sk_buff *skb,
|
||||
int hlen, struct msghdr *msg)
|
||||
{
|
||||
__wsum csum;
|
||||
int chunk = skb->len - hlen;
|
||||
@ -765,28 +673,20 @@ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
|
||||
if (!chunk)
|
||||
return 0;
|
||||
|
||||
/* Skip filled elements.
|
||||
* Pretty silly, look at memcpy_toiovec, though 8)
|
||||
*/
|
||||
while (!iov->iov_len)
|
||||
iov++;
|
||||
|
||||
if (iov->iov_len < chunk) {
|
||||
if (iov_iter_count(&msg->msg_iter) < chunk) {
|
||||
if (__skb_checksum_complete(skb))
|
||||
goto csum_error;
|
||||
if (skb_copy_datagram_iovec(skb, hlen, iov, chunk))
|
||||
if (skb_copy_datagram_msg(skb, hlen, msg, chunk))
|
||||
goto fault;
|
||||
} else {
|
||||
csum = csum_partial(skb->data, hlen, skb->csum);
|
||||
if (skb_copy_and_csum_datagram(skb, hlen, iov->iov_base,
|
||||
if (skb_copy_and_csum_datagram(skb, hlen, &msg->msg_iter,
|
||||
chunk, &csum))
|
||||
goto fault;
|
||||
if (csum_fold(csum))
|
||||
goto csum_error;
|
||||
if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
|
||||
netdev_rx_csum_fault(skb->dev);
|
||||
iov->iov_len -= chunk;
|
||||
iov->iov_base += chunk;
|
||||
}
|
||||
return 0;
|
||||
csum_error:
|
||||
@ -794,7 +694,7 @@ csum_error:
|
||||
fault:
|
||||
return -EFAULT;
|
||||
}
|
||||
EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec);
|
||||
EXPORT_SYMBOL(skb_copy_and_csum_datagram_msg);
|
||||
|
||||
/**
|
||||
* datagram_poll - generic datagram poll
|
||||
|
@ -752,14 +752,16 @@ EXPORT_SYMBOL(ip_fragment);
|
||||
int
|
||||
ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
|
||||
{
|
||||
struct iovec *iov = from;
|
||||
struct msghdr *msg = from;
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
if (memcpy_fromiovecend(to, iov, offset, len) < 0)
|
||||
/* XXX: stripping const */
|
||||
if (memcpy_fromiovecend(to, (struct iovec *)msg->msg_iter.iov, offset, len) < 0)
|
||||
return -EFAULT;
|
||||
} else {
|
||||
__wsum csum = 0;
|
||||
if (csum_partial_copy_fromiovecend(to, iov, offset, len, &csum) < 0)
|
||||
/* XXX: stripping const */
|
||||
if (csum_partial_copy_fromiovecend(to, (struct iovec *)msg->msg_iter.iov, offset, len, &csum) < 0)
|
||||
return -EFAULT;
|
||||
skb->csum = csum_block_add(skb->csum, csum, odd);
|
||||
}
|
||||
|
@ -811,7 +811,8 @@ back_from_confirm:
|
||||
pfh.icmph.checksum = 0;
|
||||
pfh.icmph.un.echo.id = inet->inet_sport;
|
||||
pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence;
|
||||
pfh.iov = msg->msg_iov;
|
||||
/* XXX: stripping const */
|
||||
pfh.iov = (struct iovec *)msg->msg_iter.iov;
|
||||
pfh.wcheck = 0;
|
||||
pfh.family = AF_INET;
|
||||
|
||||
|
@ -82,7 +82,7 @@
|
||||
#include <linux/uio.h>
|
||||
|
||||
struct raw_frag_vec {
|
||||
struct iovec *iov;
|
||||
struct msghdr *msg;
|
||||
union {
|
||||
struct icmphdr icmph;
|
||||
char c[1];
|
||||
@ -440,7 +440,7 @@ static int raw_probe_proto_opt(struct raw_frag_vec *rfv, struct flowi4 *fl4)
|
||||
/* We only need the first two bytes. */
|
||||
rfv->hlen = 2;
|
||||
|
||||
err = memcpy_fromiovec(rfv->hdr.c, rfv->iov, rfv->hlen);
|
||||
err = memcpy_from_msg(rfv->hdr.c, rfv->msg, rfv->hlen);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -478,7 +478,7 @@ static int raw_getfrag(void *from, char *to, int offset, int len, int odd,
|
||||
|
||||
offset -= rfv->hlen;
|
||||
|
||||
return ip_generic_getfrag(rfv->iov, to, offset, len, odd, skb);
|
||||
return ip_generic_getfrag(rfv->msg, to, offset, len, odd, skb);
|
||||
}
|
||||
|
||||
static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
||||
@ -600,7 +600,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
||||
daddr, saddr, 0, 0);
|
||||
|
||||
if (!inet->hdrincl) {
|
||||
rfv.iov = msg->msg_iov;
|
||||
rfv.msg = msg;
|
||||
rfv.hlen = 0;
|
||||
|
||||
err = raw_probe_proto_opt(&rfv, &fl4);
|
||||
@ -625,7 +625,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
||||
back_from_confirm:
|
||||
|
||||
if (inet->hdrincl)
|
||||
err = raw_send_hdrinc(sk, &fl4, msg->msg_iov, len,
|
||||
/* XXX: stripping const */
|
||||
err = raw_send_hdrinc(sk, &fl4, (struct iovec *)msg->msg_iter.iov, len,
|
||||
&rt, msg->msg_flags);
|
||||
|
||||
else {
|
||||
|
@ -1067,7 +1067,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
|
||||
int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
||||
size_t size)
|
||||
{
|
||||
struct iovec *iov;
|
||||
const struct iovec *iov;
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
struct sk_buff *skb;
|
||||
int iovlen, flags, err, copied = 0;
|
||||
@ -1118,8 +1118,8 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
||||
mss_now = tcp_send_mss(sk, &size_goal, flags);
|
||||
|
||||
/* Ok commence sending. */
|
||||
iovlen = msg->msg_iovlen;
|
||||
iov = msg->msg_iov;
|
||||
iovlen = msg->msg_iter.nr_segs;
|
||||
iov = msg->msg_iter.iov;
|
||||
copied = 0;
|
||||
|
||||
err = -EPIPE;
|
||||
@ -1711,7 +1711,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
||||
if (!user_recv && !(flags & (MSG_TRUNC | MSG_PEEK))) {
|
||||
user_recv = current;
|
||||
tp->ucopy.task = user_recv;
|
||||
tp->ucopy.iov = msg->msg_iov;
|
||||
tp->ucopy.msg = msg;
|
||||
}
|
||||
|
||||
tp->ucopy.len = len;
|
||||
|
@ -4421,7 +4421,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
local_bh_enable();
|
||||
if (!skb_copy_datagram_iovec(skb, 0, tp->ucopy.iov, chunk)) {
|
||||
if (!skb_copy_datagram_msg(skb, 0, tp->ucopy.msg, chunk)) {
|
||||
tp->ucopy.len -= chunk;
|
||||
tp->copied_seq += chunk;
|
||||
eaten = (chunk == skb->len);
|
||||
@ -4941,10 +4941,9 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
|
||||
|
||||
local_bh_enable();
|
||||
if (skb_csum_unnecessary(skb))
|
||||
err = skb_copy_datagram_iovec(skb, hlen, tp->ucopy.iov, chunk);
|
||||
err = skb_copy_datagram_msg(skb, hlen, tp->ucopy.msg, chunk);
|
||||
else
|
||||
err = skb_copy_and_csum_datagram_iovec(skb, hlen,
|
||||
tp->ucopy.iov);
|
||||
err = skb_copy_and_csum_datagram_msg(skb, hlen, tp->ucopy.msg);
|
||||
|
||||
if (!err) {
|
||||
tp->ucopy.len -= chunk;
|
||||
|
@ -3073,7 +3073,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
|
||||
syn_data->ip_summed = CHECKSUM_PARTIAL;
|
||||
memcpy(syn_data->cb, syn->cb, sizeof(syn->cb));
|
||||
if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space),
|
||||
fo->data->msg_iov, 0, space))) {
|
||||
fo->data->msg_iter.iov, 0, space))) {
|
||||
kfree_skb(syn_data);
|
||||
goto fallback;
|
||||
}
|
||||
|
@ -1049,7 +1049,7 @@ back_from_confirm:
|
||||
|
||||
/* Lockless fast path for the non-corking case. */
|
||||
if (!corkreq) {
|
||||
skb = ip_make_skb(sk, fl4, getfrag, msg->msg_iov, ulen,
|
||||
skb = ip_make_skb(sk, fl4, getfrag, msg, ulen,
|
||||
sizeof(struct udphdr), &ipc, &rt,
|
||||
msg->msg_flags);
|
||||
err = PTR_ERR(skb);
|
||||
@ -1080,7 +1080,7 @@ back_from_confirm:
|
||||
|
||||
do_append_data:
|
||||
up->len += ulen;
|
||||
err = ip_append_data(sk, fl4, getfrag, msg->msg_iov, ulen,
|
||||
err = ip_append_data(sk, fl4, getfrag, msg, ulen,
|
||||
sizeof(struct udphdr), &ipc, &rt,
|
||||
corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
|
||||
if (err)
|
||||
|
@ -163,7 +163,8 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
||||
pfh.icmph.checksum = 0;
|
||||
pfh.icmph.un.echo.id = inet->inet_sport;
|
||||
pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence;
|
||||
pfh.iov = msg->msg_iov;
|
||||
/* XXX: stripping const */
|
||||
pfh.iov = (struct iovec *)msg->msg_iter.iov;
|
||||
pfh.wcheck = 0;
|
||||
pfh.family = AF_INET6;
|
||||
|
||||
|
119
net/ipv6/raw.c
119
net/ipv6/raw.c
@ -672,65 +672,62 @@ error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int rawv6_probe_proto_opt(struct flowi6 *fl6, struct msghdr *msg)
|
||||
struct raw6_frag_vec {
|
||||
struct msghdr *msg;
|
||||
int hlen;
|
||||
char c[4];
|
||||
};
|
||||
|
||||
static int rawv6_probe_proto_opt(struct raw6_frag_vec *rfv, struct flowi6 *fl6)
|
||||
{
|
||||
struct iovec *iov;
|
||||
u8 __user *type = NULL;
|
||||
u8 __user *code = NULL;
|
||||
u8 len = 0;
|
||||
int probed = 0;
|
||||
int i;
|
||||
|
||||
if (!msg->msg_iov)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < msg->msg_iovlen; i++) {
|
||||
iov = &msg->msg_iov[i];
|
||||
if (!iov)
|
||||
continue;
|
||||
|
||||
switch (fl6->flowi6_proto) {
|
||||
case IPPROTO_ICMPV6:
|
||||
/* check if one-byte field is readable or not. */
|
||||
if (iov->iov_base && iov->iov_len < 1)
|
||||
break;
|
||||
|
||||
if (!type) {
|
||||
type = iov->iov_base;
|
||||
/* check if code field is readable or not. */
|
||||
if (iov->iov_len > 1)
|
||||
code = type + 1;
|
||||
} else if (!code)
|
||||
code = iov->iov_base;
|
||||
|
||||
if (type && code) {
|
||||
if (get_user(fl6->fl6_icmp_type, type) ||
|
||||
get_user(fl6->fl6_icmp_code, code))
|
||||
return -EFAULT;
|
||||
probed = 1;
|
||||
}
|
||||
break;
|
||||
case IPPROTO_MH:
|
||||
if (iov->iov_base && iov->iov_len < 1)
|
||||
break;
|
||||
/* check if type field is readable or not. */
|
||||
if (iov->iov_len > 2 - len) {
|
||||
u8 __user *p = iov->iov_base;
|
||||
if (get_user(fl6->fl6_mh_type, &p[2 - len]))
|
||||
return -EFAULT;
|
||||
probed = 1;
|
||||
} else
|
||||
len += iov->iov_len;
|
||||
|
||||
break;
|
||||
default:
|
||||
probed = 1;
|
||||
break;
|
||||
int err = 0;
|
||||
switch (fl6->flowi6_proto) {
|
||||
case IPPROTO_ICMPV6:
|
||||
rfv->hlen = 2;
|
||||
err = memcpy_from_msg(rfv->c, rfv->msg, rfv->hlen);
|
||||
if (!err) {
|
||||
fl6->fl6_icmp_type = rfv->c[0];
|
||||
fl6->fl6_icmp_code = rfv->c[1];
|
||||
}
|
||||
if (probed)
|
||||
break;
|
||||
break;
|
||||
case IPPROTO_MH:
|
||||
rfv->hlen = 4;
|
||||
err = memcpy_from_msg(rfv->c, rfv->msg, rfv->hlen);
|
||||
if (!err)
|
||||
fl6->fl6_mh_type = rfv->c[2];
|
||||
}
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int raw6_getfrag(void *from, char *to, int offset, int len, int odd,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct raw6_frag_vec *rfv = from;
|
||||
|
||||
if (offset < rfv->hlen) {
|
||||
int copy = min(rfv->hlen - offset, len);
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL)
|
||||
memcpy(to, rfv->c + offset, copy);
|
||||
else
|
||||
skb->csum = csum_block_add(
|
||||
skb->csum,
|
||||
csum_partial_copy_nocheck(rfv->c + offset,
|
||||
to, copy, 0),
|
||||
odd);
|
||||
|
||||
odd = 0;
|
||||
offset += copy;
|
||||
to += copy;
|
||||
len -= copy;
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset -= rfv->hlen;
|
||||
|
||||
return ip_generic_getfrag(rfv->msg, to, offset, len, odd, skb);
|
||||
}
|
||||
|
||||
static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
|
||||
@ -745,6 +742,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
|
||||
struct ipv6_txoptions *opt = NULL;
|
||||
struct ip6_flowlabel *flowlabel = NULL;
|
||||
struct dst_entry *dst = NULL;
|
||||
struct raw6_frag_vec rfv;
|
||||
struct flowi6 fl6;
|
||||
int addr_len = msg->msg_namelen;
|
||||
int hlimit = -1;
|
||||
@ -848,7 +846,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
|
||||
opt = ipv6_fixup_options(&opt_space, opt);
|
||||
|
||||
fl6.flowi6_proto = proto;
|
||||
err = rawv6_probe_proto_opt(&fl6, msg);
|
||||
rfv.msg = msg;
|
||||
rfv.hlen = 0;
|
||||
err = rawv6_probe_proto_opt(&rfv, &fl6);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -886,10 +886,11 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
|
||||
|
||||
back_from_confirm:
|
||||
if (inet->hdrincl)
|
||||
err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl6, &dst, msg->msg_flags);
|
||||
/* XXX: stripping const */
|
||||
err = rawv6_send_hdrinc(sk, (struct iovec *)msg->msg_iter.iov, len, &fl6, &dst, msg->msg_flags);
|
||||
else {
|
||||
lock_sock(sk);
|
||||
err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov,
|
||||
err = ip6_append_data(sk, raw6_getfrag, &rfv,
|
||||
len, 0, hlimit, tclass, opt, &fl6, (struct rt6_info *)dst,
|
||||
msg->msg_flags, dontfrag);
|
||||
|
||||
|
@ -1312,7 +1312,7 @@ do_append_data:
|
||||
dontfrag = np->dontfrag;
|
||||
up->len += ulen;
|
||||
getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
|
||||
err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen,
|
||||
err = ip6_append_data(sk, getfrag, msg, ulen,
|
||||
sizeof(struct udphdr), hlimit, tclass, opt, &fl6,
|
||||
(struct rt6_info *)dst,
|
||||
corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag);
|
||||
|
@ -619,7 +619,7 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk,
|
||||
|
||||
back_from_confirm:
|
||||
lock_sock(sk);
|
||||
err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov,
|
||||
err = ip6_append_data(sk, ip_generic_getfrag, msg,
|
||||
ulen, transhdrlen, hlimit, tclass, opt,
|
||||
&fl6, (struct rt6_info *)dst,
|
||||
msg->msg_flags, dontfrag);
|
||||
|
@ -2305,7 +2305,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||||
}
|
||||
|
||||
if (netlink_tx_is_mmaped(sk) &&
|
||||
msg->msg_iov->iov_base == NULL) {
|
||||
msg->msg_iter.iov->iov_base == NULL) {
|
||||
err = netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group,
|
||||
siocb);
|
||||
goto out;
|
||||
|
@ -2408,11 +2408,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
|
||||
unsigned short gso_type = 0;
|
||||
int hlen, tlen;
|
||||
int extra_len = 0;
|
||||
struct iov_iter from;
|
||||
ssize_t n;
|
||||
|
||||
iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, len);
|
||||
|
||||
/*
|
||||
* Get and verify the address.
|
||||
*/
|
||||
@ -2451,7 +2448,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
|
||||
len -= vnet_hdr_len;
|
||||
|
||||
err = -EFAULT;
|
||||
n = copy_from_iter(&vnet_hdr, vnet_hdr_len, &from);
|
||||
n = copy_from_iter(&vnet_hdr, vnet_hdr_len, &msg->msg_iter);
|
||||
if (n != vnet_hdr_len)
|
||||
goto out_unlock;
|
||||
|
||||
@ -2522,7 +2519,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
|
||||
}
|
||||
|
||||
/* Returns -EFAULT on error */
|
||||
err = skb_copy_datagram_from_iter(skb, offset, &from, len);
|
||||
err = skb_copy_datagram_from_iter(skb, offset, &msg->msg_iter, len);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
|
@ -404,7 +404,6 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
|
||||
int ret = 0, nonblock = msg_flags & MSG_DONTWAIT;
|
||||
DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name);
|
||||
struct rds_incoming *inc = NULL;
|
||||
struct iov_iter to;
|
||||
|
||||
/* udp_recvmsg()->sock_recvtimeo() gets away without locking too.. */
|
||||
timeo = sock_rcvtimeo(sk, nonblock);
|
||||
@ -415,6 +414,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
|
||||
goto out;
|
||||
|
||||
while (1) {
|
||||
struct iov_iter save;
|
||||
/* If there are pending notifications, do those - and nothing else */
|
||||
if (!list_empty(&rs->rs_notify_queue)) {
|
||||
ret = rds_notify_queue_get(rs, msg);
|
||||
@ -450,8 +450,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
|
||||
rdsdebug("copying inc %p from %pI4:%u to user\n", inc,
|
||||
&inc->i_conn->c_faddr,
|
||||
ntohs(inc->i_hdr.h_sport));
|
||||
iov_iter_init(&to, READ, msg->msg_iov, msg->msg_iovlen, size);
|
||||
ret = inc->i_conn->c_trans->inc_copy_to_user(inc, &to);
|
||||
save = msg->msg_iter;
|
||||
ret = inc->i_conn->c_trans->inc_copy_to_user(inc, &msg->msg_iter);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
@ -464,6 +464,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
|
||||
rds_inc_put(inc);
|
||||
inc = NULL;
|
||||
rds_stats_inc(s_recv_deliver_raced);
|
||||
msg->msg_iter = save;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -934,9 +934,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
|
||||
int queued = 0, allocated_mr = 0;
|
||||
int nonblock = msg->msg_flags & MSG_DONTWAIT;
|
||||
long timeo = sock_sndtimeo(sk, nonblock);
|
||||
struct iov_iter from;
|
||||
|
||||
iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, payload_len);
|
||||
/* Mirror Linux UDP mirror of BSD error message compatibility */
|
||||
/* XXX: Perhaps MSG_MORE someday */
|
||||
if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_CMSG_COMPAT)) {
|
||||
@ -984,7 +982,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
ret = rds_message_copy_from_user(rm, &from);
|
||||
ret = rds_message_copy_from_user(rm, &msg->msg_iter);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
@ -531,14 +531,12 @@ static int rxrpc_send_data(struct kiocb *iocb,
|
||||
struct rxrpc_skb_priv *sp;
|
||||
unsigned char __user *from;
|
||||
struct sk_buff *skb;
|
||||
struct iovec *iov;
|
||||
const struct iovec *iov;
|
||||
struct sock *sk = &rx->sk;
|
||||
long timeo;
|
||||
bool more;
|
||||
int ret, ioc, segment, copied;
|
||||
|
||||
_enter(",,,{%zu},%zu", msg->msg_iovlen, len);
|
||||
|
||||
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
|
||||
|
||||
/* this should be in poll */
|
||||
@ -547,8 +545,8 @@ static int rxrpc_send_data(struct kiocb *iocb,
|
||||
if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
|
||||
return -EPIPE;
|
||||
|
||||
iov = msg->msg_iov;
|
||||
ioc = msg->msg_iovlen - 1;
|
||||
iov = msg->msg_iter.iov;
|
||||
ioc = msg->msg_iter.nr_segs - 1;
|
||||
from = iov->iov_base;
|
||||
segment = iov->iov_len;
|
||||
iov++;
|
||||
|
@ -1609,9 +1609,6 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
|
||||
__u16 sinfo_flags = 0;
|
||||
long timeo;
|
||||
int err;
|
||||
struct iov_iter from;
|
||||
|
||||
iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, msg_len);
|
||||
|
||||
err = 0;
|
||||
sp = sctp_sk(sk);
|
||||
@ -1950,7 +1947,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
|
||||
}
|
||||
|
||||
/* Break the message into multiple chunks of maximum size. */
|
||||
datamsg = sctp_datamsg_from_user(asoc, sinfo, &from);
|
||||
datamsg = sctp_datamsg_from_user(asoc, sinfo, &msg->msg_iter);
|
||||
if (IS_ERR(datamsg)) {
|
||||
err = PTR_ERR(datamsg);
|
||||
goto out_free;
|
||||
|
27
net/socket.c
27
net/socket.c
@ -689,8 +689,7 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg,
|
||||
* the following is safe, since for compiler definitions of kvec and
|
||||
* iovec are identical, yielding the same in-core layout and alignment
|
||||
*/
|
||||
msg->msg_iov = (struct iovec *)vec;
|
||||
msg->msg_iovlen = num;
|
||||
iov_iter_init(&msg->msg_iter, WRITE, (struct iovec *)vec, num, size);
|
||||
result = sock_sendmsg(sock, msg, size);
|
||||
set_fs(oldfs);
|
||||
return result;
|
||||
@ -853,7 +852,7 @@ int kernel_recvmsg(struct socket *sock, struct msghdr *msg,
|
||||
* the following is safe, since for compiler definitions of kvec and
|
||||
* iovec are identical, yielding the same in-core layout and alignment
|
||||
*/
|
||||
msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num;
|
||||
iov_iter_init(&msg->msg_iter, READ, (struct iovec *)vec, num, size);
|
||||
result = sock_recvmsg(sock, msg, size, flags);
|
||||
set_fs(oldfs);
|
||||
return result;
|
||||
@ -913,8 +912,7 @@ static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb,
|
||||
msg->msg_namelen = 0;
|
||||
msg->msg_control = NULL;
|
||||
msg->msg_controllen = 0;
|
||||
msg->msg_iov = (struct iovec *)iov;
|
||||
msg->msg_iovlen = nr_segs;
|
||||
iov_iter_init(&msg->msg_iter, READ, iov, nr_segs, size);
|
||||
msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
|
||||
|
||||
return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags);
|
||||
@ -953,8 +951,7 @@ static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb,
|
||||
msg->msg_namelen = 0;
|
||||
msg->msg_control = NULL;
|
||||
msg->msg_controllen = 0;
|
||||
msg->msg_iov = (struct iovec *)iov;
|
||||
msg->msg_iovlen = nr_segs;
|
||||
iov_iter_init(&msg->msg_iter, WRITE, iov, nr_segs, size);
|
||||
msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
|
||||
if (sock->type == SOCK_SEQPACKET)
|
||||
msg->msg_flags |= MSG_EOR;
|
||||
@ -1798,8 +1795,7 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
|
||||
iov.iov_base = buff;
|
||||
iov.iov_len = len;
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
iov_iter_init(&msg.msg_iter, WRITE, &iov, 1, len);
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_namelen = 0;
|
||||
@ -1856,10 +1852,9 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
|
||||
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_iov = &iov;
|
||||
iov.iov_len = size;
|
||||
iov.iov_base = ubuf;
|
||||
iov_iter_init(&msg.msg_iter, READ, &iov, 1, size);
|
||||
/* Save some cycles and don't copy the address if not needed */
|
||||
msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
|
||||
/* We assume all kernel code knows the size of sockaddr_storage */
|
||||
@ -1993,13 +1988,14 @@ static ssize_t copy_msghdr_from_user(struct msghdr *kmsg,
|
||||
{
|
||||
struct sockaddr __user *uaddr;
|
||||
struct iovec __user *uiov;
|
||||
size_t nr_segs;
|
||||
ssize_t err;
|
||||
|
||||
if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) ||
|
||||
__get_user(uaddr, &umsg->msg_name) ||
|
||||
__get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
|
||||
__get_user(uiov, &umsg->msg_iov) ||
|
||||
__get_user(kmsg->msg_iovlen, &umsg->msg_iovlen) ||
|
||||
__get_user(nr_segs, &umsg->msg_iovlen) ||
|
||||
__get_user(kmsg->msg_control, &umsg->msg_control) ||
|
||||
__get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
|
||||
__get_user(kmsg->msg_flags, &umsg->msg_flags))
|
||||
@ -2029,14 +2025,15 @@ static ssize_t copy_msghdr_from_user(struct msghdr *kmsg,
|
||||
kmsg->msg_namelen = 0;
|
||||
}
|
||||
|
||||
if (kmsg->msg_iovlen > UIO_MAXIOV)
|
||||
if (nr_segs > UIO_MAXIOV)
|
||||
return -EMSGSIZE;
|
||||
|
||||
err = rw_copy_check_uvector(save_addr ? READ : WRITE,
|
||||
uiov, kmsg->msg_iovlen,
|
||||
uiov, nr_segs,
|
||||
UIO_FASTIOV, *iov, iov);
|
||||
if (err >= 0)
|
||||
kmsg->msg_iov = *iov;
|
||||
iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE,
|
||||
*iov, nr_segs, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset,
|
||||
__skb_queue_tail(list, skb);
|
||||
skb_copy_to_linear_data(skb, mhdr, mhsz);
|
||||
pktpos = skb->data + mhsz;
|
||||
if (!dsz || !memcpy_fromiovecend(pktpos, m->msg_iov, offset,
|
||||
if (!dsz || !memcpy_fromiovecend(pktpos, m->msg_iter.iov, offset,
|
||||
dsz))
|
||||
return dsz;
|
||||
rc = -EFAULT;
|
||||
@ -224,7 +224,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset,
|
||||
if (drem < pktrem)
|
||||
pktrem = drem;
|
||||
|
||||
if (memcpy_fromiovecend(pktpos, m->msg_iov, offset, pktrem)) {
|
||||
if (memcpy_fromiovecend(pktpos, m->msg_iter.iov, offset, pktrem)) {
|
||||
rc = -EFAULT;
|
||||
goto error;
|
||||
}
|
||||
|
@ -1459,9 +1459,6 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||||
struct scm_cookie tmp_scm;
|
||||
int max_level;
|
||||
int data_len = 0;
|
||||
struct iov_iter from;
|
||||
|
||||
iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, len);
|
||||
|
||||
if (NULL == siocb->scm)
|
||||
siocb->scm = &tmp_scm;
|
||||
@ -1519,7 +1516,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||||
skb_put(skb, len - data_len);
|
||||
skb->data_len = data_len;
|
||||
skb->len = len;
|
||||
err = skb_copy_datagram_from_iter(skb, 0, &from, len);
|
||||
err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, len);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
@ -1641,9 +1638,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||||
bool fds_sent = false;
|
||||
int max_level;
|
||||
int data_len;
|
||||
struct iov_iter from;
|
||||
|
||||
iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, len);
|
||||
|
||||
if (NULL == siocb->scm)
|
||||
siocb->scm = &tmp_scm;
|
||||
@ -1700,7 +1694,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||||
skb_put(skb, size - data_len);
|
||||
skb->data_len = data_len;
|
||||
skb->len = size;
|
||||
err = skb_copy_datagram_from_iter(skb, 0, &from, size);
|
||||
err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size);
|
||||
if (err) {
|
||||
kfree_skb(skb);
|
||||
goto out_err;
|
||||
|
@ -1840,9 +1840,9 @@ static ssize_t vmci_transport_stream_dequeue(
|
||||
int flags)
|
||||
{
|
||||
if (flags & MSG_PEEK)
|
||||
return vmci_qpair_peekv(vmci_trans(vsk)->qpair, msg->msg_iov, len, 0);
|
||||
return vmci_qpair_peekv(vmci_trans(vsk)->qpair, msg, len, 0);
|
||||
else
|
||||
return vmci_qpair_dequev(vmci_trans(vsk)->qpair, msg->msg_iov, len, 0);
|
||||
return vmci_qpair_dequev(vmci_trans(vsk)->qpair, msg, len, 0);
|
||||
}
|
||||
|
||||
static ssize_t vmci_transport_stream_enqueue(
|
||||
@ -1850,7 +1850,8 @@ static ssize_t vmci_transport_stream_enqueue(
|
||||
struct msghdr *msg,
|
||||
size_t len)
|
||||
{
|
||||
return vmci_qpair_enquev(vmci_trans(vsk)->qpair, msg->msg_iov, len, 0);
|
||||
/* XXX: stripping const */
|
||||
return vmci_qpair_enquev(vmci_trans(vsk)->qpair, (struct iovec *)msg->msg_iter.iov, len, 0);
|
||||
}
|
||||
|
||||
static s64 vmci_transport_stream_has_data(struct vsock_sock *vsk)
|
||||
|
Loading…
Reference in New Issue
Block a user