diff options
author | David S. Miller <davem@davemloft.net> | 2014-12-10 13:17:23 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-12-10 13:17:23 -0500 |
commit | 6e5f59aacbf9527dfe425541c78cb8c56623e7eb (patch) | |
tree | dc5614e1546dba2bd6896d4aa21410e1d3297a09 | |
parent | 6c702fab626328c33b539b0c618a5511aed23bed (diff) | |
parent | 218321e7a0838c2be974539f0a5341b398d4432b (diff) |
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>
48 files changed, 628 insertions, 1038 deletions
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index 35c93ff11f35..83cd2cc49c9f 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c | |||
@@ -42,7 +42,7 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock, | |||
42 | struct alg_sock *ask = alg_sk(sk); | 42 | struct alg_sock *ask = alg_sk(sk); |
43 | struct hash_ctx *ctx = ask->private; | 43 | struct hash_ctx *ctx = ask->private; |
44 | unsigned long iovlen; | 44 | unsigned long iovlen; |
45 | struct iovec *iov; | 45 | const struct iovec *iov; |
46 | long copied = 0; | 46 | long copied = 0; |
47 | int err; | 47 | int err; |
48 | 48 | ||
@@ -58,7 +58,7 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock, | |||
58 | 58 | ||
59 | ctx->more = 0; | 59 | ctx->more = 0; |
60 | 60 | ||
61 | for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0; | 61 | for (iov = msg->msg_iter.iov, iovlen = msg->msg_iter.nr_segs; iovlen > 0; |
62 | iovlen--, iov++) { | 62 | iovlen--, iov++) { |
63 | unsigned long seglen = iov->iov_len; | 63 | unsigned long seglen = iov->iov_len; |
64 | char __user *from = iov->iov_base; | 64 | char __user *from = iov->iov_base; |
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index c3b482bee208..4f45dab24648 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c | |||
@@ -429,13 +429,13 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, | |||
429 | struct skcipher_sg_list *sgl; | 429 | struct skcipher_sg_list *sgl; |
430 | struct scatterlist *sg; | 430 | struct scatterlist *sg; |
431 | unsigned long iovlen; | 431 | unsigned long iovlen; |
432 | struct iovec *iov; | 432 | const struct iovec *iov; |
433 | int err = -EAGAIN; | 433 | int err = -EAGAIN; |
434 | int used; | 434 | int used; |
435 | long copied = 0; | 435 | long copied = 0; |
436 | 436 | ||
437 | lock_sock(sk); | 437 | lock_sock(sk); |
438 | for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0; | 438 | for (iov = msg->msg_iter.iov, iovlen = msg->msg_iter.nr_segs; iovlen > 0; |
439 | iovlen--, iov++) { | 439 | iovlen--, iov++) { |
440 | unsigned long seglen = iov->iov_len; | 440 | unsigned long seglen = iov->iov_len; |
441 | char __user *from = iov->iov_base; | 441 | char __user *from = iov->iov_base; |
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c index 1b7b303085d2..7aaaf51e1596 100644 --- a/drivers/misc/vmw_vmci/vmci_queue_pair.c +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/uio.h> | 27 | #include <linux/uio.h> |
28 | #include <linux/wait.h> | 28 | #include <linux/wait.h> |
29 | #include <linux/vmalloc.h> | 29 | #include <linux/vmalloc.h> |
30 | #include <linux/skbuff.h> | ||
30 | 31 | ||
31 | #include "vmci_handle_array.h" | 32 | #include "vmci_handle_array.h" |
32 | #include "vmci_queue_pair.h" | 33 | #include "vmci_queue_pair.h" |
@@ -429,11 +430,11 @@ static int __qp_memcpy_from_queue(void *dest, | |||
429 | to_copy = size - bytes_copied; | 430 | to_copy = size - bytes_copied; |
430 | 431 | ||
431 | if (is_iovec) { | 432 | if (is_iovec) { |
432 | struct iovec *iov = (struct iovec *)dest; | 433 | struct msghdr *msg = dest; |
433 | int err; | 434 | int err; |
434 | 435 | ||
435 | /* The iovec will track bytes_copied internally. */ | 436 | /* The iovec will track bytes_copied internally. */ |
436 | err = memcpy_toiovec(iov, (u8 *)va + page_offset, | 437 | err = memcpy_to_msg(msg, (u8 *)va + page_offset, |
437 | to_copy); | 438 | to_copy); |
438 | if (err != 0) { | 439 | if (err != 0) { |
439 | if (kernel_if->host) | 440 | if (kernel_if->host) |
@@ -3264,13 +3265,13 @@ EXPORT_SYMBOL_GPL(vmci_qpair_enquev); | |||
3264 | * of bytes dequeued or < 0 on error. | 3265 | * of bytes dequeued or < 0 on error. |
3265 | */ | 3266 | */ |
3266 | ssize_t vmci_qpair_dequev(struct vmci_qp *qpair, | 3267 | ssize_t vmci_qpair_dequev(struct vmci_qp *qpair, |
3267 | void *iov, | 3268 | struct msghdr *msg, |
3268 | size_t iov_size, | 3269 | size_t iov_size, |
3269 | int buf_type) | 3270 | int buf_type) |
3270 | { | 3271 | { |
3271 | ssize_t result; | 3272 | ssize_t result; |
3272 | 3273 | ||
3273 | if (!qpair || !iov) | 3274 | if (!qpair) |
3274 | return VMCI_ERROR_INVALID_ARGS; | 3275 | return VMCI_ERROR_INVALID_ARGS; |
3275 | 3276 | ||
3276 | qp_lock(qpair); | 3277 | qp_lock(qpair); |
@@ -3279,7 +3280,7 @@ ssize_t vmci_qpair_dequev(struct vmci_qp *qpair, | |||
3279 | result = qp_dequeue_locked(qpair->produce_q, | 3280 | result = qp_dequeue_locked(qpair->produce_q, |
3280 | qpair->consume_q, | 3281 | qpair->consume_q, |
3281 | qpair->consume_q_size, | 3282 | qpair->consume_q_size, |
3282 | iov, iov_size, | 3283 | msg, iov_size, |
3283 | qp_memcpy_from_queue_iov, | 3284 | qp_memcpy_from_queue_iov, |
3284 | true); | 3285 | true); |
3285 | 3286 | ||
@@ -3308,13 +3309,13 @@ EXPORT_SYMBOL_GPL(vmci_qpair_dequev); | |||
3308 | * of bytes peeked or < 0 on error. | 3309 | * of bytes peeked or < 0 on error. |
3309 | */ | 3310 | */ |
3310 | ssize_t vmci_qpair_peekv(struct vmci_qp *qpair, | 3311 | ssize_t vmci_qpair_peekv(struct vmci_qp *qpair, |
3311 | void *iov, | 3312 | struct msghdr *msg, |
3312 | size_t iov_size, | 3313 | size_t iov_size, |
3313 | int buf_type) | 3314 | int buf_type) |
3314 | { | 3315 | { |
3315 | ssize_t result; | 3316 | ssize_t result; |
3316 | 3317 | ||
3317 | if (!qpair || !iov) | 3318 | if (!qpair) |
3318 | return VMCI_ERROR_INVALID_ARGS; | 3319 | return VMCI_ERROR_INVALID_ARGS; |
3319 | 3320 | ||
3320 | qp_lock(qpair); | 3321 | qp_lock(qpair); |
@@ -3323,7 +3324,7 @@ ssize_t vmci_qpair_peekv(struct vmci_qp *qpair, | |||
3323 | result = qp_dequeue_locked(qpair->produce_q, | 3324 | result = qp_dequeue_locked(qpair->produce_q, |
3324 | qpair->consume_q, | 3325 | qpair->consume_q, |
3325 | qpair->consume_q_size, | 3326 | qpair->consume_q_size, |
3326 | iov, iov_size, | 3327 | msg, iov_size, |
3327 | qp_memcpy_from_queue_iov, | 3328 | qp_memcpy_from_queue_iov, |
3328 | false); | 3329 | false); |
3329 | 3330 | ||
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index ba1e5db2152e..2c157cced81f 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -1095,9 +1095,7 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1095 | struct msghdr *m, size_t total_len) | 1095 | struct msghdr *m, size_t total_len) |
1096 | { | 1096 | { |
1097 | struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); | 1097 | struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); |
1098 | struct iov_iter from; | 1098 | return macvtap_get_user(q, m, &m->msg_iter, m->msg_flags & MSG_DONTWAIT); |
1099 | iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len); | ||
1100 | return macvtap_get_user(q, m, &from, m->msg_flags & MSG_DONTWAIT); | ||
1101 | } | 1099 | } |
1102 | 1100 | ||
1103 | static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, | 1101 | static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, |
@@ -1105,12 +1103,10 @@ static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1105 | int flags) | 1103 | int flags) |
1106 | { | 1104 | { |
1107 | struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); | 1105 | struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); |
1108 | struct iov_iter to; | ||
1109 | int ret; | 1106 | int ret; |
1110 | if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) | 1107 | if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) |
1111 | return -EINVAL; | 1108 | return -EINVAL; |
1112 | iov_iter_init(&to, READ, m->msg_iov, m->msg_iovlen, total_len); | 1109 | ret = macvtap_do_read(q, &m->msg_iter, flags & MSG_DONTWAIT); |
1113 | ret = macvtap_do_read(q, &to, flags & MSG_DONTWAIT); | ||
1114 | if (ret > total_len) { | 1110 | if (ret > total_len) { |
1115 | m->msg_flags |= MSG_TRUNC; | 1111 | m->msg_flags |= MSG_TRUNC; |
1116 | ret = flags & MSG_TRUNC ? ret : total_len; | 1112 | ret = flags & MSG_TRUNC ? ret : total_len; |
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 794a47329368..af034dba9bd6 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c | |||
@@ -417,6 +417,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf, | |||
417 | ssize_t ret; | 417 | ssize_t ret; |
418 | struct sk_buff *skb = NULL; | 418 | struct sk_buff *skb = NULL; |
419 | struct iovec iov; | 419 | struct iovec iov; |
420 | struct iov_iter to; | ||
420 | 421 | ||
421 | ret = count; | 422 | ret = count; |
422 | 423 | ||
@@ -462,7 +463,8 @@ static ssize_t ppp_read(struct file *file, char __user *buf, | |||
462 | ret = -EFAULT; | 463 | ret = -EFAULT; |
463 | iov.iov_base = buf; | 464 | iov.iov_base = buf; |
464 | iov.iov_len = count; | 465 | iov.iov_len = count; |
465 | if (skb_copy_datagram_iovec(skb, 0, &iov, skb->len)) | 466 | iov_iter_init(&to, READ, &iov, 1, count); |
467 | if (skb_copy_datagram_iter(skb, 0, &to, skb->len)) | ||
466 | goto outf; | 468 | goto outf; |
467 | ret = skb->len; | 469 | ret = skb->len; |
468 | 470 | ||
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 9c58286b8a42..f3e992ed87ac 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -1449,13 +1449,11 @@ static int tun_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1449 | int ret; | 1449 | int ret; |
1450 | struct tun_file *tfile = container_of(sock, struct tun_file, socket); | 1450 | struct tun_file *tfile = container_of(sock, struct tun_file, socket); |
1451 | struct tun_struct *tun = __tun_get(tfile); | 1451 | struct tun_struct *tun = __tun_get(tfile); |
1452 | struct iov_iter from; | ||
1453 | 1452 | ||
1454 | if (!tun) | 1453 | if (!tun) |
1455 | return -EBADFD; | 1454 | return -EBADFD; |
1456 | 1455 | ||
1457 | iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len); | 1456 | ret = tun_get_user(tun, tfile, m->msg_control, &m->msg_iter, |
1458 | ret = tun_get_user(tun, tfile, m->msg_control, &from, | ||
1459 | m->msg_flags & MSG_DONTWAIT); | 1457 | m->msg_flags & MSG_DONTWAIT); |
1460 | tun_put(tun); | 1458 | tun_put(tun); |
1461 | return ret; | 1459 | return ret; |
@@ -1467,7 +1465,6 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1467 | { | 1465 | { |
1468 | struct tun_file *tfile = container_of(sock, struct tun_file, socket); | 1466 | struct tun_file *tfile = container_of(sock, struct tun_file, socket); |
1469 | struct tun_struct *tun = __tun_get(tfile); | 1467 | struct tun_struct *tun = __tun_get(tfile); |
1470 | struct iov_iter to; | ||
1471 | int ret; | 1468 | int ret; |
1472 | 1469 | ||
1473 | if (!tun) | 1470 | if (!tun) |
@@ -1482,8 +1479,7 @@ static int tun_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1482 | SOL_PACKET, TUN_TX_TIMESTAMP); | 1479 | SOL_PACKET, TUN_TX_TIMESTAMP); |
1483 | goto out; | 1480 | goto out; |
1484 | } | 1481 | } |
1485 | iov_iter_init(&to, READ, m->msg_iov, m->msg_iovlen, total_len); | 1482 | ret = tun_do_read(tun, tfile, &m->msg_iter, flags & MSG_DONTWAIT); |
1486 | ret = tun_do_read(tun, tfile, &to, flags & MSG_DONTWAIT); | ||
1487 | if (ret > total_len) { | 1483 | if (ret > total_len) { |
1488 | m->msg_flags |= MSG_TRUNC; | 1484 | m->msg_flags |= MSG_TRUNC; |
1489 | ret = flags & MSG_TRUNC ? ret : total_len; | 1485 | ret = flags & MSG_TRUNC ? ret : total_len; |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index ce87ce9bdb9c..7c6a95bcb35e 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
@@ -1326,21 +1326,19 @@ static int iscsit_do_rx_data( | |||
1326 | struct iscsi_conn *conn, | 1326 | struct iscsi_conn *conn, |
1327 | struct iscsi_data_count *count) | 1327 | struct iscsi_data_count *count) |
1328 | { | 1328 | { |
1329 | int data = count->data_length, rx_loop = 0, total_rx = 0, iov_len; | 1329 | int data = count->data_length, rx_loop = 0, total_rx = 0; |
1330 | struct kvec *iov_p; | ||
1331 | struct msghdr msg; | 1330 | struct msghdr msg; |
1332 | 1331 | ||
1333 | if (!conn || !conn->sock || !conn->conn_ops) | 1332 | if (!conn || !conn->sock || !conn->conn_ops) |
1334 | return -1; | 1333 | return -1; |
1335 | 1334 | ||
1336 | memset(&msg, 0, sizeof(struct msghdr)); | 1335 | memset(&msg, 0, sizeof(struct msghdr)); |
1337 | 1336 | iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, | |
1338 | iov_p = count->iov; | 1337 | count->iov, count->iov_count, data); |
1339 | iov_len = count->iov_count; | ||
1340 | 1338 | ||
1341 | while (total_rx < data) { | 1339 | while (total_rx < data) { |
1342 | rx_loop = kernel_recvmsg(conn->sock, &msg, iov_p, iov_len, | 1340 | rx_loop = sock_recvmsg(conn->sock, &msg, |
1343 | (data - total_rx), MSG_WAITALL); | 1341 | (data - total_rx), MSG_WAITALL); |
1344 | if (rx_loop <= 0) { | 1342 | if (rx_loop <= 0) { |
1345 | pr_debug("rx_loop: %d total_rx: %d\n", | 1343 | pr_debug("rx_loop: %d total_rx: %d\n", |
1346 | rx_loop, total_rx); | 1344 | rx_loop, total_rx); |
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 8dae2f724a35..9f06e70a2631 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
@@ -342,7 +342,6 @@ static void handle_tx(struct vhost_net *net) | |||
342 | .msg_namelen = 0, | 342 | .msg_namelen = 0, |
343 | .msg_control = NULL, | 343 | .msg_control = NULL, |
344 | .msg_controllen = 0, | 344 | .msg_controllen = 0, |
345 | .msg_iov = vq->iov, | ||
346 | .msg_flags = MSG_DONTWAIT, | 345 | .msg_flags = MSG_DONTWAIT, |
347 | }; | 346 | }; |
348 | size_t len, total_len = 0; | 347 | size_t len, total_len = 0; |
@@ -396,8 +395,8 @@ static void handle_tx(struct vhost_net *net) | |||
396 | } | 395 | } |
397 | /* Skip header. TODO: support TSO. */ | 396 | /* Skip header. TODO: support TSO. */ |
398 | s = move_iovec_hdr(vq->iov, nvq->hdr, hdr_size, out); | 397 | s = move_iovec_hdr(vq->iov, nvq->hdr, hdr_size, out); |
399 | msg.msg_iovlen = out; | ||
400 | len = iov_length(vq->iov, out); | 398 | len = iov_length(vq->iov, out); |
399 | iov_iter_init(&msg.msg_iter, WRITE, vq->iov, out, len); | ||
401 | /* Sanity check */ | 400 | /* Sanity check */ |
402 | if (!len) { | 401 | if (!len) { |
403 | vq_err(vq, "Unexpected header len for TX: " | 402 | vq_err(vq, "Unexpected header len for TX: " |
@@ -562,7 +561,6 @@ static void handle_rx(struct vhost_net *net) | |||
562 | .msg_namelen = 0, | 561 | .msg_namelen = 0, |
563 | .msg_control = NULL, /* FIXME: get and handle RX aux data. */ | 562 | .msg_control = NULL, /* FIXME: get and handle RX aux data. */ |
564 | .msg_controllen = 0, | 563 | .msg_controllen = 0, |
565 | .msg_iov = vq->iov, | ||
566 | .msg_flags = MSG_DONTWAIT, | 564 | .msg_flags = MSG_DONTWAIT, |
567 | }; | 565 | }; |
568 | struct virtio_net_hdr_mrg_rxbuf hdr = { | 566 | struct virtio_net_hdr_mrg_rxbuf hdr = { |
@@ -600,7 +598,7 @@ static void handle_rx(struct vhost_net *net) | |||
600 | break; | 598 | break; |
601 | /* On overrun, truncate and discard */ | 599 | /* On overrun, truncate and discard */ |
602 | if (unlikely(headcount > UIO_MAXIOV)) { | 600 | if (unlikely(headcount > UIO_MAXIOV)) { |
603 | msg.msg_iovlen = 1; | 601 | iov_iter_init(&msg.msg_iter, READ, vq->iov, 1, 1); |
604 | err = sock->ops->recvmsg(NULL, sock, &msg, | 602 | err = sock->ops->recvmsg(NULL, sock, &msg, |
605 | 1, MSG_DONTWAIT | MSG_TRUNC); | 603 | 1, MSG_DONTWAIT | MSG_TRUNC); |
606 | pr_debug("Discarded rx packet: len %zd\n", sock_len); | 604 | pr_debug("Discarded rx packet: len %zd\n", sock_len); |
@@ -626,7 +624,7 @@ static void handle_rx(struct vhost_net *net) | |||
626 | /* Copy the header for use in VIRTIO_NET_F_MRG_RXBUF: | 624 | /* Copy the header for use in VIRTIO_NET_F_MRG_RXBUF: |
627 | * needed because recvmsg can modify msg_iov. */ | 625 | * needed because recvmsg can modify msg_iov. */ |
628 | copy_iovec_hdr(vq->iov, nvq->hdr, sock_hlen, in); | 626 | copy_iovec_hdr(vq->iov, nvq->hdr, sock_hlen, in); |
629 | msg.msg_iovlen = in; | 627 | iov_iter_init(&msg.msg_iter, READ, vq->iov, in, sock_len); |
630 | err = sock->ops->recvmsg(NULL, sock, &msg, | 628 | err = sock->ops->recvmsg(NULL, sock, &msg, |
631 | sock_len, MSG_DONTWAIT | MSG_TRUNC); | 629 | sock_len, MSG_DONTWAIT | MSG_TRUNC); |
632 | /* Userspace might have consumed the packet meanwhile: | 630 | /* Userspace might have consumed the packet meanwhile: |
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 03a3beb17004..06e14bfb3496 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c | |||
@@ -306,8 +306,8 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg, | |||
306 | 306 | ||
307 | _debug("- range %u-%u%s", | 307 | _debug("- range %u-%u%s", |
308 | offset, to, msg->msg_flags ? " [more]" : ""); | 308 | offset, to, msg->msg_flags ? " [more]" : ""); |
309 | msg->msg_iov = (struct iovec *) iov; | 309 | iov_iter_init(&msg->msg_iter, WRITE, |
310 | msg->msg_iovlen = 1; | 310 | (struct iovec *) iov, 1, to - offset); |
311 | 311 | ||
312 | /* have to change the state *before* sending the last | 312 | /* have to change the state *before* sending the last |
313 | * packet as RxRPC might give us the reply before it | 313 | * 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, | |||
384 | 384 | ||
385 | msg.msg_name = NULL; | 385 | msg.msg_name = NULL; |
386 | msg.msg_namelen = 0; | 386 | msg.msg_namelen = 0; |
387 | msg.msg_iov = (struct iovec *) iov; | 387 | iov_iter_init(&msg.msg_iter, WRITE, (struct iovec *)iov, 1, |
388 | msg.msg_iovlen = 1; | 388 | call->request_size); |
389 | msg.msg_control = NULL; | 389 | msg.msg_control = NULL; |
390 | msg.msg_controllen = 0; | 390 | msg.msg_controllen = 0; |
391 | msg.msg_flags = (call->send_pages ? MSG_MORE : 0); | 391 | msg.msg_flags = (call->send_pages ? MSG_MORE : 0); |
@@ -778,8 +778,7 @@ void afs_send_empty_reply(struct afs_call *call) | |||
778 | iov[0].iov_len = 0; | 778 | iov[0].iov_len = 0; |
779 | msg.msg_name = NULL; | 779 | msg.msg_name = NULL; |
780 | msg.msg_namelen = 0; | 780 | msg.msg_namelen = 0; |
781 | msg.msg_iov = iov; | 781 | iov_iter_init(&msg.msg_iter, WRITE, iov, 0, 0); /* WTF? */ |
782 | msg.msg_iovlen = 0; | ||
783 | msg.msg_control = NULL; | 782 | msg.msg_control = NULL; |
784 | msg.msg_controllen = 0; | 783 | msg.msg_controllen = 0; |
785 | msg.msg_flags = 0; | 784 | msg.msg_flags = 0; |
@@ -815,8 +814,7 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len) | |||
815 | iov[0].iov_len = len; | 814 | iov[0].iov_len = len; |
816 | msg.msg_name = NULL; | 815 | msg.msg_name = NULL; |
817 | msg.msg_namelen = 0; | 816 | msg.msg_namelen = 0; |
818 | msg.msg_iov = iov; | 817 | iov_iter_init(&msg.msg_iter, WRITE, iov, 1, len); |
819 | msg.msg_iovlen = 1; | ||
820 | msg.msg_control = NULL; | 818 | msg.msg_control = NULL; |
821 | msg.msg_controllen = 0; | 819 | msg.msg_controllen = 0; |
822 | msg.msg_flags = 0; | 820 | msg.msg_flags = 0; |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index ef64cec42804..ab0bc43c82a4 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -2644,24 +2644,17 @@ struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, | |||
2644 | int *err); | 2644 | int *err); |
2645 | unsigned int datagram_poll(struct file *file, struct socket *sock, | 2645 | unsigned int datagram_poll(struct file *file, struct socket *sock, |
2646 | struct poll_table_struct *wait); | 2646 | struct poll_table_struct *wait); |
2647 | int skb_copy_datagram_iovec(const struct sk_buff *from, int offset, | 2647 | int skb_copy_datagram_iter(const struct sk_buff *from, int offset, |
2648 | struct iovec *to, int size); | 2648 | struct iov_iter *to, int size); |
2649 | static inline int skb_copy_datagram_msg(const struct sk_buff *from, int offset, | 2649 | static inline int skb_copy_datagram_msg(const struct sk_buff *from, int offset, |
2650 | struct msghdr *msg, int size) | 2650 | struct msghdr *msg, int size) |
2651 | { | 2651 | { |
2652 | return skb_copy_datagram_iovec(from, offset, msg->msg_iov, size); | 2652 | return skb_copy_datagram_iter(from, offset, &msg->msg_iter, size); |
2653 | } | ||
2654 | int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen, | ||
2655 | struct iovec *iov); | ||
2656 | static inline int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen, | ||
2657 | struct msghdr *msg) | ||
2658 | { | ||
2659 | return skb_copy_and_csum_datagram_iovec(skb, hlen, msg->msg_iov); | ||
2660 | } | 2653 | } |
2654 | int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, int hlen, | ||
2655 | struct msghdr *msg); | ||
2661 | int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset, | 2656 | int skb_copy_datagram_from_iter(struct sk_buff *skb, int offset, |
2662 | struct iov_iter *from, int len); | 2657 | struct iov_iter *from, int len); |
2663 | int skb_copy_datagram_iter(const struct sk_buff *from, int offset, | ||
2664 | struct iov_iter *to, int size); | ||
2665 | int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *frm); | 2658 | int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *frm); |
2666 | void skb_free_datagram(struct sock *sk, struct sk_buff *skb); | 2659 | void skb_free_datagram(struct sock *sk, struct sk_buff *skb); |
2667 | void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb); | 2660 | 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); | |||
2689 | 2682 | ||
2690 | static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len) | 2683 | static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len) |
2691 | { | 2684 | { |
2692 | return memcpy_fromiovec(data, msg->msg_iov, len); | 2685 | /* XXX: stripping const */ |
2686 | return memcpy_fromiovec(data, (struct iovec *)msg->msg_iter.iov, len); | ||
2693 | } | 2687 | } |
2694 | 2688 | ||
2695 | static inline int memcpy_to_msg(struct msghdr *msg, void *data, int len) | 2689 | static inline int memcpy_to_msg(struct msghdr *msg, void *data, int len) |
2696 | { | 2690 | { |
2697 | return memcpy_toiovec(msg->msg_iov, data, len); | 2691 | return copy_to_iter(data, len, &msg->msg_iter) == len ? 0 : -EFAULT; |
2698 | } | 2692 | } |
2699 | 2693 | ||
2700 | struct skb_checksum_ops { | 2694 | struct skb_checksum_ops { |
diff --git a/include/linux/socket.h b/include/linux/socket.h index de5222832be4..048d6d6eed6d 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h | |||
@@ -47,8 +47,7 @@ struct linger { | |||
47 | struct msghdr { | 47 | struct msghdr { |
48 | void *msg_name; /* ptr to socket address structure */ | 48 | void *msg_name; /* ptr to socket address structure */ |
49 | int msg_namelen; /* size of socket address structure */ | 49 | int msg_namelen; /* size of socket address structure */ |
50 | struct iovec *msg_iov; /* scatter/gather array */ | 50 | struct iov_iter msg_iter; /* data */ |
51 | __kernel_size_t msg_iovlen; /* # elements in msg_iov */ | ||
52 | void *msg_control; /* ancillary data */ | 51 | void *msg_control; /* ancillary data */ |
53 | __kernel_size_t msg_controllen; /* ancillary data buffer length */ | 52 | __kernel_size_t msg_controllen; /* ancillary data buffer length */ |
54 | unsigned int msg_flags; /* flags on received message */ | 53 | unsigned int msg_flags; /* flags on received message */ |
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 3fa0a9669a3a..67309ece0772 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h | |||
@@ -162,7 +162,7 @@ struct tcp_sock { | |||
162 | struct { | 162 | struct { |
163 | struct sk_buff_head prequeue; | 163 | struct sk_buff_head prequeue; |
164 | struct task_struct *task; | 164 | struct task_struct *task; |
165 | struct iovec *iov; | 165 | struct msghdr *msg; |
166 | int memory; | 166 | int memory; |
167 | int len; | 167 | int len; |
168 | } ucopy; | 168 | } ucopy; |
diff --git a/include/linux/uio.h b/include/linux/uio.h index 9b1581414cd4..a41e252396c0 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h | |||
@@ -31,6 +31,7 @@ struct iov_iter { | |||
31 | size_t count; | 31 | size_t count; |
32 | union { | 32 | union { |
33 | const struct iovec *iov; | 33 | const struct iovec *iov; |
34 | const struct kvec *kvec; | ||
34 | const struct bio_vec *bvec; | 35 | const struct bio_vec *bvec; |
35 | }; | 36 | }; |
36 | unsigned long nr_segs; | 37 | unsigned long nr_segs; |
@@ -82,10 +83,13 @@ size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, | |||
82 | struct iov_iter *i); | 83 | struct iov_iter *i); |
83 | size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i); | 84 | size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i); |
84 | size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i); | 85 | size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i); |
86 | size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i); | ||
85 | size_t iov_iter_zero(size_t bytes, struct iov_iter *); | 87 | size_t iov_iter_zero(size_t bytes, struct iov_iter *); |
86 | unsigned long iov_iter_alignment(const struct iov_iter *i); | 88 | unsigned long iov_iter_alignment(const struct iov_iter *i); |
87 | void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov, | 89 | void iov_iter_init(struct iov_iter *i, int direction, const struct iovec *iov, |
88 | unsigned long nr_segs, size_t count); | 90 | unsigned long nr_segs, size_t count); |
91 | void iov_iter_kvec(struct iov_iter *i, int direction, const struct kvec *iov, | ||
92 | unsigned long nr_segs, size_t count); | ||
89 | ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages, | 93 | ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages, |
90 | size_t maxsize, unsigned maxpages, size_t *start); | 94 | size_t maxsize, unsigned maxpages, size_t *start); |
91 | ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages, | 95 | 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) | |||
123 | { | 127 | { |
124 | i->count = count; | 128 | i->count = count; |
125 | } | 129 | } |
130 | size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); | ||
131 | size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); | ||
126 | 132 | ||
127 | int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); | 133 | int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); |
128 | int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len); | ||
129 | int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, | 134 | int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, |
130 | int offset, int len); | 135 | int offset, int len); |
131 | int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata, | 136 | int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata, |
diff --git a/include/linux/vmw_vmci_api.h b/include/linux/vmw_vmci_api.h index 023430e265fe..5691f752ce8f 100644 --- a/include/linux/vmw_vmci_api.h +++ b/include/linux/vmw_vmci_api.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #define VMCI_KERNEL_API_VERSION_2 2 | 24 | #define VMCI_KERNEL_API_VERSION_2 2 |
25 | #define VMCI_KERNEL_API_VERSION VMCI_KERNEL_API_VERSION_2 | 25 | #define VMCI_KERNEL_API_VERSION VMCI_KERNEL_API_VERSION_2 |
26 | 26 | ||
27 | struct msghdr; | ||
27 | typedef void (vmci_device_shutdown_fn) (void *device_registration, | 28 | typedef void (vmci_device_shutdown_fn) (void *device_registration, |
28 | void *user_data); | 29 | void *user_data); |
29 | 30 | ||
@@ -75,8 +76,8 @@ ssize_t vmci_qpair_peek(struct vmci_qp *qpair, void *buf, size_t buf_size, | |||
75 | ssize_t vmci_qpair_enquev(struct vmci_qp *qpair, | 76 | ssize_t vmci_qpair_enquev(struct vmci_qp *qpair, |
76 | void *iov, size_t iov_size, int mode); | 77 | void *iov, size_t iov_size, int mode); |
77 | ssize_t vmci_qpair_dequev(struct vmci_qp *qpair, | 78 | ssize_t vmci_qpair_dequev(struct vmci_qp *qpair, |
78 | void *iov, size_t iov_size, int mode); | 79 | struct msghdr *msg, size_t iov_size, int mode); |
79 | ssize_t vmci_qpair_peekv(struct vmci_qp *qpair, void *iov, size_t iov_size, | 80 | ssize_t vmci_qpair_peekv(struct vmci_qp *qpair, struct msghdr *msg, size_t iov_size, |
80 | int mode); | 81 | int mode); |
81 | 82 | ||
82 | #endif /* !__VMW_VMCI_API_H__ */ | 83 | #endif /* !__VMW_VMCI_API_H__ */ |
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index eee3ef530e79..d1bb342d083f 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -608,10 +608,6 @@ struct l2cap_ops { | |||
608 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, | 608 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, |
609 | unsigned long hdr_len, | 609 | unsigned long hdr_len, |
610 | unsigned long len, int nb); | 610 | unsigned long len, int nb); |
611 | int (*memcpy_fromiovec) (struct l2cap_chan *chan, | ||
612 | unsigned char *kdata, | ||
613 | struct iovec *iov, | ||
614 | int len); | ||
615 | }; | 611 | }; |
616 | 612 | ||
617 | struct l2cap_conn { | 613 | struct l2cap_conn { |
@@ -905,31 +901,6 @@ static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan) | |||
905 | return 0; | 901 | return 0; |
906 | } | 902 | } |
907 | 903 | ||
908 | static inline int l2cap_chan_no_memcpy_fromiovec(struct l2cap_chan *chan, | ||
909 | unsigned char *kdata, | ||
910 | struct iovec *iov, | ||
911 | int len) | ||
912 | { | ||
913 | /* Following is safe since for compiler definitions of kvec and | ||
914 | * iovec are identical, yielding the same in-core layout and alignment | ||
915 | */ | ||
916 | struct kvec *vec = (struct kvec *)iov; | ||
917 | |||
918 | while (len > 0) { | ||
919 | if (vec->iov_len) { | ||
920 | int copy = min_t(unsigned int, len, vec->iov_len); | ||
921 | memcpy(kdata, vec->iov_base, copy); | ||
922 | len -= copy; | ||
923 | kdata += copy; | ||
924 | vec->iov_base += copy; | ||
925 | vec->iov_len -= copy; | ||
926 | } | ||
927 | vec++; | ||
928 | } | ||
929 | |||
930 | return 0; | ||
931 | } | ||
932 | |||
933 | extern bool disable_ertm; | 904 | extern bool disable_ertm; |
934 | 905 | ||
935 | int l2cap_init_sockets(void); | 906 | int l2cap_init_sockets(void); |
diff --git a/include/net/udplite.h b/include/net/udplite.h index 9a28a5179400..ae7c8d1fbcad 100644 --- a/include/net/udplite.h +++ b/include/net/udplite.h | |||
@@ -19,7 +19,9 @@ extern struct udp_table udplite_table; | |||
19 | static __inline__ int udplite_getfrag(void *from, char *to, int offset, | 19 | static __inline__ int udplite_getfrag(void *from, char *to, int offset, |
20 | int len, int odd, struct sk_buff *skb) | 20 | int len, int odd, struct sk_buff *skb) |
21 | { | 21 | { |
22 | return memcpy_fromiovecend(to, (struct iovec *) from, offset, len); | 22 | struct msghdr *msg = from; |
23 | /* XXX: stripping const */ | ||
24 | return memcpy_fromiovecend(to, (struct iovec *)msg->msg_iter.iov, offset, len); | ||
23 | } | 25 | } |
24 | 26 | ||
25 | /* Designate sk as UDP-Lite socket */ | 27 | /* Designate sk as UDP-Lite socket */ |
diff --git a/lib/iovec.c b/lib/iovec.c index df3abd1eaa4a..2d99cb4a5006 100644 --- a/lib/iovec.c +++ b/lib/iovec.c | |||
@@ -29,31 +29,6 @@ EXPORT_SYMBOL(memcpy_fromiovec); | |||
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Copy kernel to iovec. Returns -EFAULT on error. | 31 | * Copy kernel to iovec. Returns -EFAULT on error. |
32 | * | ||
33 | * Note: this modifies the original iovec. | ||
34 | */ | ||
35 | |||
36 | int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len) | ||
37 | { | ||
38 | while (len > 0) { | ||
39 | if (iov->iov_len) { | ||
40 | int copy = min_t(unsigned int, iov->iov_len, len); | ||
41 | if (copy_to_user(iov->iov_base, kdata, copy)) | ||
42 | return -EFAULT; | ||
43 | kdata += copy; | ||
44 | len -= copy; | ||
45 | iov->iov_len -= copy; | ||
46 | iov->iov_base += copy; | ||
47 | } | ||
48 | iov++; | ||
49 | } | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | EXPORT_SYMBOL(memcpy_toiovec); | ||
54 | |||
55 | /* | ||
56 | * Copy kernel to iovec. Returns -EFAULT on error. | ||
57 | */ | 32 | */ |
58 | 33 | ||
59 | int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata, | 34 | int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata, |
diff --git a/mm/iov_iter.c b/mm/iov_iter.c index e34a3cb6aad6..a1599ca4ab0e 100644 --- a/mm/iov_iter.c +++ b/mm/iov_iter.c | |||
@@ -3,95 +3,136 @@ | |||
3 | #include <linux/pagemap.h> | 3 | #include <linux/pagemap.h> |
4 | #include <linux/slab.h> | 4 | #include <linux/slab.h> |
5 | #include <linux/vmalloc.h> | 5 | #include <linux/vmalloc.h> |
6 | 6 | #include <net/checksum.h> | |
7 | static size_t copy_to_iter_iovec(void *from, size_t bytes, struct iov_iter *i) | 7 | |
8 | { | 8 | #define iterate_iovec(i, n, __v, __p, skip, STEP) { \ |
9 | size_t skip, copy, left, wanted; | 9 | size_t left; \ |
10 | const struct iovec *iov; | 10 | size_t wanted = n; \ |
11 | char __user *buf; | 11 | __p = i->iov; \ |
12 | 12 | __v.iov_len = min(n, __p->iov_len - skip); \ | |
13 | if (unlikely(bytes > i->count)) | 13 | if (likely(__v.iov_len)) { \ |
14 | bytes = i->count; | 14 | __v.iov_base = __p->iov_base + skip; \ |
15 | 15 | left = (STEP); \ | |
16 | if (unlikely(!bytes)) | 16 | __v.iov_len -= left; \ |
17 | return 0; | 17 | skip += __v.iov_len; \ |
18 | 18 | n -= __v.iov_len; \ | |
19 | wanted = bytes; | 19 | } else { \ |
20 | iov = i->iov; | 20 | left = 0; \ |
21 | skip = i->iov_offset; | 21 | } \ |
22 | buf = iov->iov_base + skip; | 22 | while (unlikely(!left && n)) { \ |
23 | copy = min(bytes, iov->iov_len - skip); | 23 | __p++; \ |
24 | 24 | __v.iov_len = min(n, __p->iov_len); \ | |
25 | left = __copy_to_user(buf, from, copy); | 25 | if (unlikely(!__v.iov_len)) \ |
26 | copy -= left; | 26 | continue; \ |
27 | skip += copy; | 27 | __v.iov_base = __p->iov_base; \ |
28 | from += copy; | 28 | left = (STEP); \ |
29 | bytes -= copy; | 29 | __v.iov_len -= left; \ |
30 | while (unlikely(!left && bytes)) { | 30 | skip = __v.iov_len; \ |
31 | iov++; | 31 | n -= __v.iov_len; \ |
32 | buf = iov->iov_base; | 32 | } \ |
33 | copy = min(bytes, iov->iov_len); | 33 | n = wanted - n; \ |
34 | left = __copy_to_user(buf, from, copy); | 34 | } |
35 | copy -= left; | 35 | |
36 | skip = copy; | 36 | #define iterate_kvec(i, n, __v, __p, skip, STEP) { \ |
37 | from += copy; | 37 | size_t wanted = n; \ |
38 | bytes -= copy; | 38 | __p = i->kvec; \ |
39 | } | 39 | __v.iov_len = min(n, __p->iov_len - skip); \ |
40 | 40 | if (likely(__v.iov_len)) { \ | |
41 | if (skip == iov->iov_len) { | 41 | __v.iov_base = __p->iov_base + skip; \ |
42 | iov++; | 42 | (void)(STEP); \ |
43 | skip = 0; | 43 | skip += __v.iov_len; \ |
44 | } | 44 | n -= __v.iov_len; \ |
45 | i->count -= wanted - bytes; | 45 | } \ |
46 | i->nr_segs -= iov - i->iov; | 46 | while (unlikely(n)) { \ |
47 | i->iov = iov; | 47 | __p++; \ |
48 | i->iov_offset = skip; | 48 | __v.iov_len = min(n, __p->iov_len); \ |
49 | return wanted - bytes; | 49 | if (unlikely(!__v.iov_len)) \ |
50 | } | 50 | continue; \ |
51 | 51 | __v.iov_base = __p->iov_base; \ | |
52 | static size_t copy_from_iter_iovec(void *to, size_t bytes, struct iov_iter *i) | 52 | (void)(STEP); \ |
53 | { | 53 | skip = __v.iov_len; \ |
54 | size_t skip, copy, left, wanted; | 54 | n -= __v.iov_len; \ |
55 | const struct iovec *iov; | 55 | } \ |
56 | char __user *buf; | 56 | n = wanted; \ |
57 | 57 | } | |
58 | if (unlikely(bytes > i->count)) | 58 | |
59 | bytes = i->count; | 59 | #define iterate_bvec(i, n, __v, __p, skip, STEP) { \ |
60 | 60 | size_t wanted = n; \ | |
61 | if (unlikely(!bytes)) | 61 | __p = i->bvec; \ |
62 | return 0; | 62 | __v.bv_len = min_t(size_t, n, __p->bv_len - skip); \ |
63 | 63 | if (likely(__v.bv_len)) { \ | |
64 | wanted = bytes; | 64 | __v.bv_page = __p->bv_page; \ |
65 | iov = i->iov; | 65 | __v.bv_offset = __p->bv_offset + skip; \ |
66 | skip = i->iov_offset; | 66 | (void)(STEP); \ |
67 | buf = iov->iov_base + skip; | 67 | skip += __v.bv_len; \ |
68 | copy = min(bytes, iov->iov_len - skip); | 68 | n -= __v.bv_len; \ |
69 | 69 | } \ | |
70 | left = __copy_from_user(to, buf, copy); | 70 | while (unlikely(n)) { \ |
71 | copy -= left; | 71 | __p++; \ |
72 | skip += copy; | 72 | __v.bv_len = min_t(size_t, n, __p->bv_len); \ |
73 | to += copy; | 73 | if (unlikely(!__v.bv_len)) \ |
74 | bytes -= copy; | 74 | continue; \ |
75 | while (unlikely(!left && bytes)) { | 75 | __v.bv_page = __p->bv_page; \ |
76 | iov++; | 76 | __v.bv_offset = __p->bv_offset; \ |
77 | buf = iov->iov_base; | 77 | (void)(STEP); \ |
78 | copy = min(bytes, iov->iov_len); | 78 | skip = __v.bv_len; \ |
79 | left = __copy_from_user(to, buf, copy); | 79 | n -= __v.bv_len; \ |
80 | copy -= left; | 80 | } \ |
81 | skip = copy; | 81 | n = wanted; \ |
82 | to += copy; | 82 | } |
83 | bytes -= copy; | 83 | |
84 | } | 84 | #define iterate_all_kinds(i, n, v, I, B, K) { \ |
85 | 85 | size_t skip = i->iov_offset; \ | |
86 | if (skip == iov->iov_len) { | 86 | if (unlikely(i->type & ITER_BVEC)) { \ |
87 | iov++; | 87 | const struct bio_vec *bvec; \ |
88 | skip = 0; | 88 | struct bio_vec v; \ |
89 | } | 89 | iterate_bvec(i, n, v, bvec, skip, (B)) \ |
90 | i->count -= wanted - bytes; | 90 | } else if (unlikely(i->type & ITER_KVEC)) { \ |
91 | i->nr_segs -= iov - i->iov; | 91 | const struct kvec *kvec; \ |
92 | i->iov = iov; | 92 | struct kvec v; \ |
93 | i->iov_offset = skip; | 93 | iterate_kvec(i, n, v, kvec, skip, (K)) \ |
94 | return wanted - bytes; | 94 | } else { \ |
95 | const struct iovec *iov; \ | ||
96 | struct iovec v; \ | ||
97 | iterate_iovec(i, n, v, iov, skip, (I)) \ | ||
98 | } \ | ||
99 | } | ||
100 | |||
101 | #define iterate_and_advance(i, n, v, I, B, K) { \ | ||
102 | size_t skip = i->iov_offset; \ | ||
103 | if (unlikely(i->type & ITER_BVEC)) { \ | ||
104 | const struct bio_vec *bvec; \ | ||
105 | struct bio_vec v; \ | ||
106 | iterate_bvec(i, n, v, bvec, skip, (B)) \ | ||
107 | if (skip == bvec->bv_len) { \ | ||
108 | bvec++; \ | ||
109 | skip = 0; \ | ||
110 | } \ | ||
111 | i->nr_segs -= bvec - i->bvec; \ | ||
112 | i->bvec = bvec; \ | ||
113 | } else if (unlikely(i->type & ITER_KVEC)) { \ | ||
114 | const struct kvec *kvec; \ | ||
115 | struct kvec v; \ | ||
116 | iterate_kvec(i, n, v, kvec, skip, (K)) \ | ||
117 | if (skip == kvec->iov_len) { \ | ||
118 | kvec++; \ | ||
119 | skip = 0; \ | ||
120 | } \ | ||
121 | i->nr_segs -= kvec - i->kvec; \ | ||
122 | i->kvec = kvec; \ | ||
123 | } else { \ | ||
124 | const struct iovec *iov; \ | ||
125 | struct iovec v; \ | ||
126 | iterate_iovec(i, n, v, iov, skip, (I)) \ | ||
127 | if (skip == iov->iov_len) { \ | ||
128 | iov++; \ | ||
129 | skip = 0; \ | ||
130 | } \ | ||
131 | i->nr_segs -= iov - i->iov; \ | ||
132 | i->iov = iov; \ | ||
133 | } \ | ||
134 | i->count -= n; \ | ||
135 | i->iov_offset = skip; \ | ||
95 | } | 136 | } |
96 | 137 | ||
97 | static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes, | 138 | static size_t copy_page_to_iter_iovec(struct page *page, size_t offset, size_t bytes, |
@@ -256,134 +297,6 @@ done: | |||
256 | return wanted - bytes; | 297 | return wanted - bytes; |
257 | } | 298 | } |
258 | 299 | ||
259 | static size_t zero_iovec(size_t bytes, struct iov_iter *i) | ||
260 | { | ||
261 | size_t skip, copy, left, wanted; | ||
262 | const struct iovec *iov; | ||
263 | char __user *buf; | ||
264 | |||
265 | if (unlikely(bytes > i->count)) | ||
266 | bytes = i->count; | ||
267 | |||
268 | if (unlikely(!bytes)) | ||
269 | return 0; | ||
270 | |||
271 | wanted = bytes; | ||
272 | iov = i->iov; | ||
273 | skip = i->iov_offset; | ||
274 | buf = iov->iov_base + skip; | ||
275 | copy = min(bytes, iov->iov_len - skip); | ||
276 | |||
277 | left = __clear_user(buf, copy); | ||
278 | copy -= left; | ||
279 | skip += copy; | ||
280 | bytes -= copy; | ||
281 | |||
282 | while (unlikely(!left && bytes)) { | ||
283 | iov++; | ||
284 | buf = iov->iov_base; | ||
285 | copy = min(bytes, iov->iov_len); | ||
286 | left = __clear_user(buf, copy); | ||
287 | copy -= left; | ||
288 | skip = copy; | ||
289 | bytes -= copy; | ||
290 | } | ||
291 | |||
292 | if (skip == iov->iov_len) { | ||
293 | iov++; | ||
294 | skip = 0; | ||
295 | } | ||
296 | i->count -= wanted - bytes; | ||
297 | i->nr_segs -= iov - i->iov; | ||
298 | i->iov = iov; | ||
299 | i->iov_offset = skip; | ||
300 | return wanted - bytes; | ||
301 | } | ||
302 | |||
303 | static size_t __iovec_copy_from_user_inatomic(char *vaddr, | ||
304 | const struct iovec *iov, size_t base, size_t bytes) | ||
305 | { | ||
306 | size_t copied = 0, left = 0; | ||
307 | |||
308 | while (bytes) { | ||
309 | char __user *buf = iov->iov_base + base; | ||
310 | int copy = min(bytes, iov->iov_len - base); | ||
311 | |||
312 | base = 0; | ||
313 | left = __copy_from_user_inatomic(vaddr, buf, copy); | ||
314 | copied += copy; | ||
315 | bytes -= copy; | ||
316 | vaddr += copy; | ||
317 | iov++; | ||
318 | |||
319 | if (unlikely(left)) | ||
320 | break; | ||
321 | } | ||
322 | return copied - left; | ||
323 | } | ||
324 | |||
325 | /* | ||
326 | * Copy as much as we can into the page and return the number of bytes which | ||
327 | * were successfully copied. If a fault is encountered then return the number of | ||
328 | * bytes which were copied. | ||
329 | */ | ||
330 | static size_t copy_from_user_atomic_iovec(struct page *page, | ||
331 | struct iov_iter *i, unsigned long offset, size_t bytes) | ||
332 | { | ||
333 | char *kaddr; | ||
334 | size_t copied; | ||
335 | |||
336 | kaddr = kmap_atomic(page); | ||
337 | if (likely(i->nr_segs == 1)) { | ||
338 | int left; | ||
339 | char __user *buf = i->iov->iov_base + i->iov_offset; | ||
340 | left = __copy_from_user_inatomic(kaddr + offset, buf, bytes); | ||
341 | copied = bytes - left; | ||
342 | } else { | ||
343 | copied = __iovec_copy_from_user_inatomic(kaddr + offset, | ||
344 | i->iov, i->iov_offset, bytes); | ||
345 | } | ||
346 | kunmap_atomic(kaddr); | ||
347 | |||
348 | return copied; | ||
349 | } | ||
350 | |||
351 | static void advance_iovec(struct iov_iter *i, size_t bytes) | ||
352 | { | ||
353 | BUG_ON(i->count < bytes); | ||
354 | |||
355 | if (likely(i->nr_segs == 1)) { | ||
356 | i->iov_offset += bytes; | ||
357 | i->count -= bytes; | ||
358 | } else { | ||
359 | const struct iovec *iov = i->iov; | ||
360 | size_t base = i->iov_offset; | ||
361 | unsigned long nr_segs = i->nr_segs; | ||
362 | |||
363 | /* | ||
364 | * The !iov->iov_len check ensures we skip over unlikely | ||
365 | * zero-length segments (without overruning the iovec). | ||
366 | */ | ||
367 | while (bytes || unlikely(i->count && !iov->iov_len)) { | ||
368 | int copy; | ||
369 | |||
370 | copy = min(bytes, iov->iov_len - base); | ||
371 | BUG_ON(!i->count || i->count < copy); | ||
372 | i->count -= copy; | ||
373 | bytes -= copy; | ||
374 | base += copy; | ||
375 | if (iov->iov_len == base) { | ||
376 | iov++; | ||
377 | nr_segs--; | ||
378 | base = 0; | ||
379 | } | ||
380 | } | ||
381 | i->iov = iov; | ||
382 | i->iov_offset = base; | ||
383 | i->nr_segs = nr_segs; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | /* | 300 | /* |
388 | * Fault in the first iovec of the given iov_iter, to a maximum length | 301 | * Fault in the first iovec of the given iov_iter, to a maximum length |
389 | * of bytes. Returns 0 on success, or non-zero if the memory could not be | 302 | * of bytes. Returns 0 on success, or non-zero if the memory could not be |
@@ -395,7 +308,7 @@ static void advance_iovec(struct iov_iter *i, size_t bytes) | |||
395 | */ | 308 | */ |
396 | int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes) | 309 | int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes) |
397 | { | 310 | { |
398 | if (!(i->type & ITER_BVEC)) { | 311 | if (!(i->type & (ITER_BVEC|ITER_KVEC))) { |
399 | char __user *buf = i->iov->iov_base + i->iov_offset; | 312 | char __user *buf = i->iov->iov_base + i->iov_offset; |
400 | bytes = min(bytes, i->iov->iov_len - i->iov_offset); | 313 | bytes = min(bytes, i->iov->iov_len - i->iov_offset); |
401 | return fault_in_pages_readable(buf, bytes); | 314 | return fault_in_pages_readable(buf, bytes); |
@@ -404,136 +317,25 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes) | |||
404 | } | 317 | } |
405 | EXPORT_SYMBOL(iov_iter_fault_in_readable); | 318 | EXPORT_SYMBOL(iov_iter_fault_in_readable); |
406 | 319 | ||
407 | static unsigned long alignment_iovec(const struct iov_iter *i) | ||
408 | { | ||
409 | const struct iovec *iov = i->iov; | ||
410 | unsigned long res; | ||
411 | size_t size = i->count; | ||
412 | size_t n; | ||
413 | |||
414 | if (!size) | ||
415 | return 0; | ||
416 | |||
417 | res = (unsigned long)iov->iov_base + i->iov_offset; | ||
418 | n = iov->iov_len - i->iov_offset; | ||
419 | if (n >= size) | ||
420 | return res | size; | ||
421 | size -= n; | ||
422 | res |= n; | ||
423 | while (size > (++iov)->iov_len) { | ||
424 | res |= (unsigned long)iov->iov_base | iov->iov_len; | ||
425 | size -= iov->iov_len; | ||
426 | } | ||
427 | res |= (unsigned long)iov->iov_base | size; | ||
428 | return res; | ||
429 | } | ||
430 | |||
431 | void iov_iter_init(struct iov_iter *i, int direction, | 320 | void iov_iter_init(struct iov_iter *i, int direction, |
432 | const struct iovec *iov, unsigned long nr_segs, | 321 | const struct iovec *iov, unsigned long nr_segs, |
433 | size_t count) | 322 | size_t count) |
434 | { | 323 | { |
435 | /* It will get better. Eventually... */ | 324 | /* It will get better. Eventually... */ |
436 | if (segment_eq(get_fs(), KERNEL_DS)) | 325 | if (segment_eq(get_fs(), KERNEL_DS)) { |
437 | direction |= ITER_KVEC; | 326 | direction |= ITER_KVEC; |
438 | i->type = direction; | 327 | i->type = direction; |
439 | i->iov = iov; | 328 | i->kvec = (struct kvec *)iov; |
329 | } else { | ||
330 | i->type = direction; | ||
331 | i->iov = iov; | ||
332 | } | ||
440 | i->nr_segs = nr_segs; | 333 | i->nr_segs = nr_segs; |
441 | i->iov_offset = 0; | 334 | i->iov_offset = 0; |
442 | i->count = count; | 335 | i->count = count; |
443 | } | 336 | } |
444 | EXPORT_SYMBOL(iov_iter_init); | 337 | EXPORT_SYMBOL(iov_iter_init); |
445 | 338 | ||
446 | static ssize_t get_pages_iovec(struct iov_iter *i, | ||
447 | struct page **pages, size_t maxsize, unsigned maxpages, | ||
448 | size_t *start) | ||
449 | { | ||
450 | size_t offset = i->iov_offset; | ||
451 | const struct iovec *iov = i->iov; | ||
452 | size_t len; | ||
453 | unsigned long addr; | ||
454 | int n; | ||
455 | int res; | ||
456 | |||
457 | len = iov->iov_len - offset; | ||
458 | if (len > i->count) | ||
459 | len = i->count; | ||
460 | if (len > maxsize) | ||
461 | len = maxsize; | ||
462 | addr = (unsigned long)iov->iov_base + offset; | ||
463 | len += *start = addr & (PAGE_SIZE - 1); | ||
464 | if (len > maxpages * PAGE_SIZE) | ||
465 | len = maxpages * PAGE_SIZE; | ||
466 | addr &= ~(PAGE_SIZE - 1); | ||
467 | n = (len + PAGE_SIZE - 1) / PAGE_SIZE; | ||
468 | res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, pages); | ||
469 | if (unlikely(res < 0)) | ||
470 | return res; | ||
471 | return (res == n ? len : res * PAGE_SIZE) - *start; | ||
472 | } | ||
473 | |||
474 | static ssize_t get_pages_alloc_iovec(struct iov_iter *i, | ||
475 | struct page ***pages, size_t maxsize, | ||
476 | size_t *start) | ||
477 | { | ||
478 | size_t offset = i->iov_offset; | ||
479 | const struct iovec *iov = i->iov; | ||
480 | size_t len; | ||
481 | unsigned long addr; | ||
482 | void *p; | ||
483 | int n; | ||
484 | int res; | ||
485 | |||
486 | len = iov->iov_len - offset; | ||
487 | if (len > i->count) | ||
488 | len = i->count; | ||
489 | if (len > maxsize) | ||
490 | len = maxsize; | ||
491 | addr = (unsigned long)iov->iov_base + offset; | ||
492 | len += *start = addr & (PAGE_SIZE - 1); | ||
493 | addr &= ~(PAGE_SIZE - 1); | ||
494 | n = (len + PAGE_SIZE - 1) / PAGE_SIZE; | ||
495 | |||
496 | p = kmalloc(n * sizeof(struct page *), GFP_KERNEL); | ||
497 | if (!p) | ||
498 | p = vmalloc(n * sizeof(struct page *)); | ||
499 | if (!p) | ||
500 | return -ENOMEM; | ||
501 | |||
502 | res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, p); | ||
503 | if (unlikely(res < 0)) { | ||
504 | kvfree(p); | ||
505 | return res; | ||
506 | } | ||
507 | *pages = p; | ||
508 | return (res == n ? len : res * PAGE_SIZE) - *start; | ||
509 | } | ||
510 | |||
511 | static int iov_iter_npages_iovec(const struct iov_iter *i, int maxpages) | ||
512 | { | ||
513 | size_t offset = i->iov_offset; | ||
514 | size_t size = i->count; | ||
515 | const struct iovec *iov = i->iov; | ||
516 | int npages = 0; | ||
517 | int n; | ||
518 | |||
519 | for (n = 0; size && n < i->nr_segs; n++, iov++) { | ||
520 | unsigned long addr = (unsigned long)iov->iov_base + offset; | ||
521 | size_t len = iov->iov_len - offset; | ||
522 | offset = 0; | ||
523 | if (unlikely(!len)) /* empty segment */ | ||
524 | continue; | ||
525 | if (len > size) | ||
526 | len = size; | ||
527 | npages += (addr + len + PAGE_SIZE - 1) / PAGE_SIZE | ||
528 | - addr / PAGE_SIZE; | ||
529 | if (npages >= maxpages) /* don't bother going further */ | ||
530 | return maxpages; | ||
531 | size -= len; | ||
532 | offset = 0; | ||
533 | } | ||
534 | return min(npages, maxpages); | ||
535 | } | ||
536 | |||
537 | static void memcpy_from_page(char *to, struct page *page, size_t offset, size_t len) | 339 | static void memcpy_from_page(char *to, struct page *page, size_t offset, size_t len) |
538 | { | 340 | { |
539 | char *from = kmap_atomic(page); | 341 | char *from = kmap_atomic(page); |
@@ -555,293 +357,78 @@ static void memzero_page(struct page *page, size_t offset, size_t len) | |||
555 | kunmap_atomic(addr); | 357 | kunmap_atomic(addr); |
556 | } | 358 | } |
557 | 359 | ||
558 | static size_t copy_to_iter_bvec(void *from, size_t bytes, struct iov_iter *i) | 360 | size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i) |
559 | { | 361 | { |
560 | size_t skip, copy, wanted; | 362 | char *from = addr; |
561 | const struct bio_vec *bvec; | ||
562 | |||
563 | if (unlikely(bytes > i->count)) | 363 | if (unlikely(bytes > i->count)) |
564 | bytes = i->count; | 364 | bytes = i->count; |
565 | 365 | ||
566 | if (unlikely(!bytes)) | 366 | if (unlikely(!bytes)) |
567 | return 0; | 367 | return 0; |
568 | 368 | ||
569 | wanted = bytes; | 369 | iterate_and_advance(i, bytes, v, |
570 | bvec = i->bvec; | 370 | __copy_to_user(v.iov_base, (from += v.iov_len) - v.iov_len, |
571 | skip = i->iov_offset; | 371 | v.iov_len), |
572 | copy = min_t(size_t, bytes, bvec->bv_len - skip); | 372 | memcpy_to_page(v.bv_page, v.bv_offset, |
373 | (from += v.bv_len) - v.bv_len, v.bv_len), | ||
374 | memcpy(v.iov_base, (from += v.iov_len) - v.iov_len, v.iov_len) | ||
375 | ) | ||
573 | 376 | ||
574 | memcpy_to_page(bvec->bv_page, skip + bvec->bv_offset, from, copy); | 377 | return bytes; |
575 | skip += copy; | ||
576 | from += copy; | ||
577 | bytes -= copy; | ||
578 | while (bytes) { | ||
579 | bvec++; | ||
580 | copy = min(bytes, (size_t)bvec->bv_len); | ||
581 | memcpy_to_page(bvec->bv_page, bvec->bv_offset, from, copy); | ||
582 | skip = copy; | ||
583 | from += copy; | ||
584 | bytes -= copy; | ||
585 | } | ||
586 | if (skip == bvec->bv_len) { | ||
587 | bvec++; | ||
588 | skip = 0; | ||
589 | } | ||
590 | i->count -= wanted - bytes; | ||
591 | i->nr_segs -= bvec - i->bvec; | ||
592 | i->bvec = bvec; | ||
593 | i->iov_offset = skip; | ||
594 | return wanted - bytes; | ||
595 | } | 378 | } |
379 | EXPORT_SYMBOL(copy_to_iter); | ||
596 | 380 | ||
597 | static size_t copy_from_iter_bvec(void *to, size_t bytes, struct iov_iter *i) | 381 | size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) |
598 | { | 382 | { |
599 | size_t skip, copy, wanted; | 383 | char *to = addr; |
600 | const struct bio_vec *bvec; | ||
601 | |||
602 | if (unlikely(bytes > i->count)) | 384 | if (unlikely(bytes > i->count)) |
603 | bytes = i->count; | 385 | bytes = i->count; |
604 | 386 | ||
605 | if (unlikely(!bytes)) | 387 | if (unlikely(!bytes)) |
606 | return 0; | 388 | return 0; |
607 | 389 | ||
608 | wanted = bytes; | 390 | iterate_and_advance(i, bytes, v, |
609 | bvec = i->bvec; | 391 | __copy_from_user((to += v.iov_len) - v.iov_len, v.iov_base, |
610 | skip = i->iov_offset; | 392 | v.iov_len), |
611 | 393 | memcpy_from_page((to += v.bv_len) - v.bv_len, v.bv_page, | |
612 | copy = min(bytes, bvec->bv_len - skip); | 394 | v.bv_offset, v.bv_len), |
395 | memcpy((to += v.iov_len) - v.iov_len, v.iov_base, v.iov_len) | ||
396 | ) | ||
613 | 397 | ||
614 | memcpy_from_page(to, bvec->bv_page, bvec->bv_offset + skip, copy); | 398 | return bytes; |
615 | |||
616 | to += copy; | ||
617 | skip += copy; | ||
618 | bytes -= copy; | ||
619 | |||
620 | while (bytes) { | ||
621 | bvec++; | ||
622 | copy = min(bytes, (size_t)bvec->bv_len); | ||
623 | memcpy_from_page(to, bvec->bv_page, bvec->bv_offset, copy); | ||
624 | skip = copy; | ||
625 | to += copy; | ||
626 | bytes -= copy; | ||
627 | } | ||
628 | if (skip == bvec->bv_len) { | ||
629 | bvec++; | ||
630 | skip = 0; | ||
631 | } | ||
632 | i->count -= wanted; | ||
633 | i->nr_segs -= bvec - i->bvec; | ||
634 | i->bvec = bvec; | ||
635 | i->iov_offset = skip; | ||
636 | return wanted; | ||
637 | } | ||
638 | |||
639 | static size_t copy_page_to_iter_bvec(struct page *page, size_t offset, | ||
640 | size_t bytes, struct iov_iter *i) | ||
641 | { | ||
642 | void *kaddr = kmap_atomic(page); | ||
643 | size_t wanted = copy_to_iter_bvec(kaddr + offset, bytes, i); | ||
644 | kunmap_atomic(kaddr); | ||
645 | return wanted; | ||
646 | } | ||
647 | |||
648 | static size_t copy_page_from_iter_bvec(struct page *page, size_t offset, | ||
649 | size_t bytes, struct iov_iter *i) | ||
650 | { | ||
651 | void *kaddr = kmap_atomic(page); | ||
652 | size_t wanted = copy_from_iter_bvec(kaddr + offset, bytes, i); | ||
653 | kunmap_atomic(kaddr); | ||
654 | return wanted; | ||
655 | } | 399 | } |
400 | EXPORT_SYMBOL(copy_from_iter); | ||
656 | 401 | ||
657 | static size_t zero_bvec(size_t bytes, struct iov_iter *i) | 402 | size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) |
658 | { | 403 | { |
659 | size_t skip, copy, wanted; | 404 | char *to = addr; |
660 | const struct bio_vec *bvec; | ||
661 | |||
662 | if (unlikely(bytes > i->count)) | 405 | if (unlikely(bytes > i->count)) |
663 | bytes = i->count; | 406 | bytes = i->count; |
664 | 407 | ||
665 | if (unlikely(!bytes)) | 408 | if (unlikely(!bytes)) |
666 | return 0; | 409 | return 0; |
667 | 410 | ||
668 | wanted = bytes; | 411 | iterate_and_advance(i, bytes, v, |
669 | bvec = i->bvec; | 412 | __copy_from_user_nocache((to += v.iov_len) - v.iov_len, |
670 | skip = i->iov_offset; | 413 | v.iov_base, v.iov_len), |
671 | copy = min_t(size_t, bytes, bvec->bv_len - skip); | 414 | memcpy_from_page((to += v.bv_len) - v.bv_len, v.bv_page, |
672 | 415 | v.bv_offset, v.bv_len), | |
673 | memzero_page(bvec->bv_page, skip + bvec->bv_offset, copy); | 416 | memcpy((to += v.iov_len) - v.iov_len, v.iov_base, v.iov_len) |
674 | skip += copy; | 417 | ) |
675 | bytes -= copy; | ||
676 | while (bytes) { | ||
677 | bvec++; | ||
678 | copy = min(bytes, (size_t)bvec->bv_len); | ||
679 | memzero_page(bvec->bv_page, bvec->bv_offset, copy); | ||
680 | skip = copy; | ||
681 | bytes -= copy; | ||
682 | } | ||
683 | if (skip == bvec->bv_len) { | ||
684 | bvec++; | ||
685 | skip = 0; | ||
686 | } | ||
687 | i->count -= wanted - bytes; | ||
688 | i->nr_segs -= bvec - i->bvec; | ||
689 | i->bvec = bvec; | ||
690 | i->iov_offset = skip; | ||
691 | return wanted - bytes; | ||
692 | } | ||
693 | 418 | ||
694 | static size_t copy_from_user_bvec(struct page *page, | ||
695 | struct iov_iter *i, unsigned long offset, size_t bytes) | ||
696 | { | ||
697 | char *kaddr; | ||
698 | size_t left; | ||
699 | const struct bio_vec *bvec; | ||
700 | size_t base = i->iov_offset; | ||
701 | |||
702 | kaddr = kmap_atomic(page); | ||
703 | for (left = bytes, bvec = i->bvec; left; bvec++, base = 0) { | ||
704 | size_t copy = min(left, bvec->bv_len - base); | ||
705 | if (!bvec->bv_len) | ||
706 | continue; | ||
707 | memcpy_from_page(kaddr + offset, bvec->bv_page, | ||
708 | bvec->bv_offset + base, copy); | ||
709 | offset += copy; | ||
710 | left -= copy; | ||
711 | } | ||
712 | kunmap_atomic(kaddr); | ||
713 | return bytes; | 419 | return bytes; |
714 | } | 420 | } |
715 | 421 | EXPORT_SYMBOL(copy_from_iter_nocache); | |
716 | static void advance_bvec(struct iov_iter *i, size_t bytes) | ||
717 | { | ||
718 | BUG_ON(i->count < bytes); | ||
719 | |||
720 | if (likely(i->nr_segs == 1)) { | ||
721 | i->iov_offset += bytes; | ||
722 | i->count -= bytes; | ||
723 | } else { | ||
724 | const struct bio_vec *bvec = i->bvec; | ||
725 | size_t base = i->iov_offset; | ||
726 | unsigned long nr_segs = i->nr_segs; | ||
727 | |||
728 | /* | ||
729 | * The !iov->iov_len check ensures we skip over unlikely | ||
730 | * zero-length segments (without overruning the iovec). | ||
731 | */ | ||
732 | while (bytes || unlikely(i->count && !bvec->bv_len)) { | ||
733 | int copy; | ||
734 | |||
735 | copy = min(bytes, bvec->bv_len - base); | ||
736 | BUG_ON(!i->count || i->count < copy); | ||
737 | i->count -= copy; | ||
738 | bytes -= copy; | ||
739 | base += copy; | ||
740 | if (bvec->bv_len == base) { | ||
741 | bvec++; | ||
742 | nr_segs--; | ||
743 | base = 0; | ||
744 | } | ||
745 | } | ||
746 | i->bvec = bvec; | ||
747 | i->iov_offset = base; | ||
748 | i->nr_segs = nr_segs; | ||
749 | } | ||
750 | } | ||
751 | |||
752 | static unsigned long alignment_bvec(const struct iov_iter *i) | ||
753 | { | ||
754 | const struct bio_vec *bvec = i->bvec; | ||
755 | unsigned long res; | ||
756 | size_t size = i->count; | ||
757 | size_t n; | ||
758 | |||
759 | if (!size) | ||
760 | return 0; | ||
761 | |||
762 | res = bvec->bv_offset + i->iov_offset; | ||
763 | n = bvec->bv_len - i->iov_offset; | ||
764 | if (n >= size) | ||
765 | return res | size; | ||
766 | size -= n; | ||
767 | res |= n; | ||
768 | while (size > (++bvec)->bv_len) { | ||
769 | res |= bvec->bv_offset | bvec->bv_len; | ||
770 | size -= bvec->bv_len; | ||
771 | } | ||
772 | res |= bvec->bv_offset | size; | ||
773 | return res; | ||
774 | } | ||
775 | |||
776 | static ssize_t get_pages_bvec(struct iov_iter *i, | ||
777 | struct page **pages, size_t maxsize, unsigned maxpages, | ||
778 | size_t *start) | ||
779 | { | ||
780 | const struct bio_vec *bvec = i->bvec; | ||
781 | size_t len = bvec->bv_len - i->iov_offset; | ||
782 | if (len > i->count) | ||
783 | len = i->count; | ||
784 | if (len > maxsize) | ||
785 | len = maxsize; | ||
786 | /* can't be more than PAGE_SIZE */ | ||
787 | *start = bvec->bv_offset + i->iov_offset; | ||
788 | |||
789 | get_page(*pages = bvec->bv_page); | ||
790 | |||
791 | return len; | ||
792 | } | ||
793 | |||
794 | static ssize_t get_pages_alloc_bvec(struct iov_iter *i, | ||
795 | struct page ***pages, size_t maxsize, | ||
796 | size_t *start) | ||
797 | { | ||
798 | const struct bio_vec *bvec = i->bvec; | ||
799 | size_t len = bvec->bv_len - i->iov_offset; | ||
800 | if (len > i->count) | ||
801 | len = i->count; | ||
802 | if (len > maxsize) | ||
803 | len = maxsize; | ||
804 | *start = bvec->bv_offset + i->iov_offset; | ||
805 | |||
806 | *pages = kmalloc(sizeof(struct page *), GFP_KERNEL); | ||
807 | if (!*pages) | ||
808 | return -ENOMEM; | ||
809 | |||
810 | get_page(**pages = bvec->bv_page); | ||
811 | |||
812 | return len; | ||
813 | } | ||
814 | |||
815 | static int iov_iter_npages_bvec(const struct iov_iter *i, int maxpages) | ||
816 | { | ||
817 | size_t offset = i->iov_offset; | ||
818 | size_t size = i->count; | ||
819 | const struct bio_vec *bvec = i->bvec; | ||
820 | int npages = 0; | ||
821 | int n; | ||
822 | |||
823 | for (n = 0; size && n < i->nr_segs; n++, bvec++) { | ||
824 | size_t len = bvec->bv_len - offset; | ||
825 | offset = 0; | ||
826 | if (unlikely(!len)) /* empty segment */ | ||
827 | continue; | ||
828 | if (len > size) | ||
829 | len = size; | ||
830 | npages++; | ||
831 | if (npages >= maxpages) /* don't bother going further */ | ||
832 | return maxpages; | ||
833 | size -= len; | ||
834 | offset = 0; | ||
835 | } | ||
836 | return min(npages, maxpages); | ||
837 | } | ||
838 | 422 | ||
839 | size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, | 423 | size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, |
840 | struct iov_iter *i) | 424 | struct iov_iter *i) |
841 | { | 425 | { |
842 | if (i->type & ITER_BVEC) | 426 | if (i->type & (ITER_BVEC|ITER_KVEC)) { |
843 | return copy_page_to_iter_bvec(page, offset, bytes, i); | 427 | void *kaddr = kmap_atomic(page); |
844 | else | 428 | size_t wanted = copy_to_iter(kaddr + offset, bytes, i); |
429 | kunmap_atomic(kaddr); | ||
430 | return wanted; | ||
431 | } else | ||
845 | return copy_page_to_iter_iovec(page, offset, bytes, i); | 432 | return copy_page_to_iter_iovec(page, offset, bytes, i); |
846 | } | 433 | } |
847 | EXPORT_SYMBOL(copy_page_to_iter); | 434 | EXPORT_SYMBOL(copy_page_to_iter); |
@@ -849,57 +436,53 @@ EXPORT_SYMBOL(copy_page_to_iter); | |||
849 | size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, | 436 | size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, |
850 | struct iov_iter *i) | 437 | struct iov_iter *i) |
851 | { | 438 | { |
852 | if (i->type & ITER_BVEC) | 439 | if (i->type & (ITER_BVEC|ITER_KVEC)) { |
853 | return copy_page_from_iter_bvec(page, offset, bytes, i); | 440 | void *kaddr = kmap_atomic(page); |
854 | else | 441 | size_t wanted = copy_from_iter(kaddr + offset, bytes, i); |
442 | kunmap_atomic(kaddr); | ||
443 | return wanted; | ||
444 | } else | ||
855 | return copy_page_from_iter_iovec(page, offset, bytes, i); | 445 | return copy_page_from_iter_iovec(page, offset, bytes, i); |
856 | } | 446 | } |
857 | EXPORT_SYMBOL(copy_page_from_iter); | 447 | EXPORT_SYMBOL(copy_page_from_iter); |
858 | 448 | ||
859 | size_t copy_to_iter(void *addr, size_t bytes, struct iov_iter *i) | 449 | size_t iov_iter_zero(size_t bytes, struct iov_iter *i) |
860 | { | 450 | { |
861 | if (i->type & ITER_BVEC) | 451 | if (unlikely(bytes > i->count)) |
862 | return copy_to_iter_bvec(addr, bytes, i); | 452 | bytes = i->count; |
863 | else | ||
864 | return copy_to_iter_iovec(addr, bytes, i); | ||
865 | } | ||
866 | EXPORT_SYMBOL(copy_to_iter); | ||
867 | 453 | ||
868 | size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) | 454 | if (unlikely(!bytes)) |
869 | { | 455 | return 0; |
870 | if (i->type & ITER_BVEC) | ||
871 | return copy_from_iter_bvec(addr, bytes, i); | ||
872 | else | ||
873 | return copy_from_iter_iovec(addr, bytes, i); | ||
874 | } | ||
875 | EXPORT_SYMBOL(copy_from_iter); | ||
876 | 456 | ||
877 | size_t iov_iter_zero(size_t bytes, struct iov_iter *i) | 457 | iterate_and_advance(i, bytes, v, |
878 | { | 458 | __clear_user(v.iov_base, v.iov_len), |
879 | if (i->type & ITER_BVEC) { | 459 | memzero_page(v.bv_page, v.bv_offset, v.bv_len), |
880 | return zero_bvec(bytes, i); | 460 | memset(v.iov_base, 0, v.iov_len) |
881 | } else { | 461 | ) |
882 | return zero_iovec(bytes, i); | 462 | |
883 | } | 463 | return bytes; |
884 | } | 464 | } |
885 | EXPORT_SYMBOL(iov_iter_zero); | 465 | EXPORT_SYMBOL(iov_iter_zero); |
886 | 466 | ||
887 | size_t iov_iter_copy_from_user_atomic(struct page *page, | 467 | size_t iov_iter_copy_from_user_atomic(struct page *page, |
888 | struct iov_iter *i, unsigned long offset, size_t bytes) | 468 | struct iov_iter *i, unsigned long offset, size_t bytes) |
889 | { | 469 | { |
890 | if (i->type & ITER_BVEC) | 470 | char *kaddr = kmap_atomic(page), *p = kaddr + offset; |
891 | return copy_from_user_bvec(page, i, offset, bytes); | 471 | iterate_all_kinds(i, bytes, v, |
892 | else | 472 | __copy_from_user_inatomic((p += v.iov_len) - v.iov_len, |
893 | return copy_from_user_atomic_iovec(page, i, offset, bytes); | 473 | v.iov_base, v.iov_len), |
474 | memcpy_from_page((p += v.bv_len) - v.bv_len, v.bv_page, | ||
475 | v.bv_offset, v.bv_len), | ||
476 | memcpy((p += v.iov_len) - v.iov_len, v.iov_base, v.iov_len) | ||
477 | ) | ||
478 | kunmap_atomic(kaddr); | ||
479 | return bytes; | ||
894 | } | 480 | } |
895 | EXPORT_SYMBOL(iov_iter_copy_from_user_atomic); | 481 | EXPORT_SYMBOL(iov_iter_copy_from_user_atomic); |
896 | 482 | ||
897 | void iov_iter_advance(struct iov_iter *i, size_t size) | 483 | void iov_iter_advance(struct iov_iter *i, size_t size) |
898 | { | 484 | { |
899 | if (i->type & ITER_BVEC) | 485 | iterate_and_advance(i, size, v, 0, 0, 0) |
900 | advance_bvec(i, size); | ||
901 | else | ||
902 | advance_iovec(i, size); | ||
903 | } | 486 | } |
904 | EXPORT_SYMBOL(iov_iter_advance); | 487 | EXPORT_SYMBOL(iov_iter_advance); |
905 | 488 | ||
@@ -917,12 +500,33 @@ size_t iov_iter_single_seg_count(const struct iov_iter *i) | |||
917 | } | 500 | } |
918 | EXPORT_SYMBOL(iov_iter_single_seg_count); | 501 | EXPORT_SYMBOL(iov_iter_single_seg_count); |
919 | 502 | ||
503 | void iov_iter_kvec(struct iov_iter *i, int direction, | ||
504 | const struct kvec *iov, unsigned long nr_segs, | ||
505 | size_t count) | ||
506 | { | ||
507 | BUG_ON(!(direction & ITER_KVEC)); | ||
508 | i->type = direction; | ||
509 | i->kvec = (struct kvec *)iov; | ||
510 | i->nr_segs = nr_segs; | ||
511 | i->iov_offset = 0; | ||
512 | i->count = count; | ||
513 | } | ||
514 | EXPORT_SYMBOL(iov_iter_kvec); | ||
515 | |||
920 | unsigned long iov_iter_alignment(const struct iov_iter *i) | 516 | unsigned long iov_iter_alignment(const struct iov_iter *i) |
921 | { | 517 | { |
922 | if (i->type & ITER_BVEC) | 518 | unsigned long res = 0; |
923 | return alignment_bvec(i); | 519 | size_t size = i->count; |
924 | else | 520 | |
925 | return alignment_iovec(i); | 521 | if (!size) |
522 | return 0; | ||
523 | |||
524 | iterate_all_kinds(i, size, v, | ||
525 | (res |= (unsigned long)v.iov_base | v.iov_len, 0), | ||
526 | res |= v.bv_offset | v.bv_len, | ||
527 | res |= (unsigned long)v.iov_base | v.iov_len | ||
528 | ) | ||
529 | return res; | ||
926 | } | 530 | } |
927 | EXPORT_SYMBOL(iov_iter_alignment); | 531 | EXPORT_SYMBOL(iov_iter_alignment); |
928 | 532 | ||
@@ -930,29 +534,207 @@ ssize_t iov_iter_get_pages(struct iov_iter *i, | |||
930 | struct page **pages, size_t maxsize, unsigned maxpages, | 534 | struct page **pages, size_t maxsize, unsigned maxpages, |
931 | size_t *start) | 535 | size_t *start) |
932 | { | 536 | { |
933 | if (i->type & ITER_BVEC) | 537 | if (maxsize > i->count) |
934 | return get_pages_bvec(i, pages, maxsize, maxpages, start); | 538 | maxsize = i->count; |
935 | else | 539 | |
936 | return get_pages_iovec(i, pages, maxsize, maxpages, start); | 540 | if (!maxsize) |
541 | return 0; | ||
542 | |||
543 | iterate_all_kinds(i, maxsize, v, ({ | ||
544 | unsigned long addr = (unsigned long)v.iov_base; | ||
545 | size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1)); | ||
546 | int n; | ||
547 | int res; | ||
548 | |||
549 | if (len > maxpages * PAGE_SIZE) | ||
550 | len = maxpages * PAGE_SIZE; | ||
551 | addr &= ~(PAGE_SIZE - 1); | ||
552 | n = DIV_ROUND_UP(len, PAGE_SIZE); | ||
553 | res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, pages); | ||
554 | if (unlikely(res < 0)) | ||
555 | return res; | ||
556 | return (res == n ? len : res * PAGE_SIZE) - *start; | ||
557 | 0;}),({ | ||
558 | /* can't be more than PAGE_SIZE */ | ||
559 | *start = v.bv_offset; | ||
560 | get_page(*pages = v.bv_page); | ||
561 | return v.bv_len; | ||
562 | }),({ | ||
563 | return -EFAULT; | ||
564 | }) | ||
565 | ) | ||
566 | return 0; | ||
937 | } | 567 | } |
938 | EXPORT_SYMBOL(iov_iter_get_pages); | 568 | EXPORT_SYMBOL(iov_iter_get_pages); |
939 | 569 | ||
570 | static struct page **get_pages_array(size_t n) | ||
571 | { | ||
572 | struct page **p = kmalloc(n * sizeof(struct page *), GFP_KERNEL); | ||
573 | if (!p) | ||
574 | p = vmalloc(n * sizeof(struct page *)); | ||
575 | return p; | ||
576 | } | ||
577 | |||
940 | ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, | 578 | ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, |
941 | struct page ***pages, size_t maxsize, | 579 | struct page ***pages, size_t maxsize, |
942 | size_t *start) | 580 | size_t *start) |
943 | { | 581 | { |
944 | if (i->type & ITER_BVEC) | 582 | struct page **p; |
945 | return get_pages_alloc_bvec(i, pages, maxsize, start); | 583 | |
946 | else | 584 | if (maxsize > i->count) |
947 | return get_pages_alloc_iovec(i, pages, maxsize, start); | 585 | maxsize = i->count; |
586 | |||
587 | if (!maxsize) | ||
588 | return 0; | ||
589 | |||
590 | iterate_all_kinds(i, maxsize, v, ({ | ||
591 | unsigned long addr = (unsigned long)v.iov_base; | ||
592 | size_t len = v.iov_len + (*start = addr & (PAGE_SIZE - 1)); | ||
593 | int n; | ||
594 | int res; | ||
595 | |||
596 | addr &= ~(PAGE_SIZE - 1); | ||
597 | n = DIV_ROUND_UP(len, PAGE_SIZE); | ||
598 | p = get_pages_array(n); | ||
599 | if (!p) | ||
600 | return -ENOMEM; | ||
601 | res = get_user_pages_fast(addr, n, (i->type & WRITE) != WRITE, p); | ||
602 | if (unlikely(res < 0)) { | ||
603 | kvfree(p); | ||
604 | return res; | ||
605 | } | ||
606 | *pages = p; | ||
607 | return (res == n ? len : res * PAGE_SIZE) - *start; | ||
608 | 0;}),({ | ||
609 | /* can't be more than PAGE_SIZE */ | ||
610 | *start = v.bv_offset; | ||
611 | *pages = p = get_pages_array(1); | ||
612 | if (!p) | ||
613 | return -ENOMEM; | ||
614 | get_page(*p = v.bv_page); | ||
615 | return v.bv_len; | ||
616 | }),({ | ||
617 | return -EFAULT; | ||
618 | }) | ||
619 | ) | ||
620 | return 0; | ||
948 | } | 621 | } |
949 | EXPORT_SYMBOL(iov_iter_get_pages_alloc); | 622 | EXPORT_SYMBOL(iov_iter_get_pages_alloc); |
950 | 623 | ||
624 | size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, | ||
625 | struct iov_iter *i) | ||
626 | { | ||
627 | char *to = addr; | ||
628 | __wsum sum, next; | ||
629 | size_t off = 0; | ||
630 | if (unlikely(bytes > i->count)) | ||
631 | bytes = i->count; | ||
632 | |||
633 | if (unlikely(!bytes)) | ||
634 | return 0; | ||
635 | |||
636 | sum = *csum; | ||
637 | iterate_and_advance(i, bytes, v, ({ | ||
638 | int err = 0; | ||
639 | next = csum_and_copy_from_user(v.iov_base, | ||
640 | (to += v.iov_len) - v.iov_len, | ||
641 | v.iov_len, 0, &err); | ||
642 | if (!err) { | ||
643 | sum = csum_block_add(sum, next, off); | ||
644 | off += v.iov_len; | ||
645 | } | ||
646 | err ? v.iov_len : 0; | ||
647 | }), ({ | ||
648 | char *p = kmap_atomic(v.bv_page); | ||
649 | next = csum_partial_copy_nocheck(p + v.bv_offset, | ||
650 | (to += v.bv_len) - v.bv_len, | ||
651 | v.bv_len, 0); | ||
652 | kunmap_atomic(p); | ||
653 | sum = csum_block_add(sum, next, off); | ||
654 | off += v.bv_len; | ||
655 | }),({ | ||
656 | next = csum_partial_copy_nocheck(v.iov_base, | ||
657 | (to += v.iov_len) - v.iov_len, | ||
658 | v.iov_len, 0); | ||
659 | sum = csum_block_add(sum, next, off); | ||
660 | off += v.iov_len; | ||
661 | }) | ||
662 | ) | ||
663 | *csum = sum; | ||
664 | return bytes; | ||
665 | } | ||
666 | EXPORT_SYMBOL(csum_and_copy_from_iter); | ||
667 | |||
668 | size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, | ||
669 | struct iov_iter *i) | ||
670 | { | ||
671 | char *from = addr; | ||
672 | __wsum sum, next; | ||
673 | size_t off = 0; | ||
674 | if (unlikely(bytes > i->count)) | ||
675 | bytes = i->count; | ||
676 | |||
677 | if (unlikely(!bytes)) | ||
678 | return 0; | ||
679 | |||
680 | sum = *csum; | ||
681 | iterate_and_advance(i, bytes, v, ({ | ||
682 | int err = 0; | ||
683 | next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len, | ||
684 | v.iov_base, | ||
685 | v.iov_len, 0, &err); | ||
686 | if (!err) { | ||
687 | sum = csum_block_add(sum, next, off); | ||
688 | off += v.iov_len; | ||
689 | } | ||
690 | err ? v.iov_len : 0; | ||
691 | }), ({ | ||
692 | char *p = kmap_atomic(v.bv_page); | ||
693 | next = csum_partial_copy_nocheck((from += v.bv_len) - v.bv_len, | ||
694 | p + v.bv_offset, | ||
695 | v.bv_len, 0); | ||
696 | kunmap_atomic(p); | ||
697 | sum = csum_block_add(sum, next, off); | ||
698 | off += v.bv_len; | ||
699 | }),({ | ||
700 | next = csum_partial_copy_nocheck((from += v.iov_len) - v.iov_len, | ||
701 | v.iov_base, | ||
702 | v.iov_len, 0); | ||
703 | sum = csum_block_add(sum, next, off); | ||
704 | off += v.iov_len; | ||
705 | }) | ||
706 | ) | ||
707 | *csum = sum; | ||
708 | return bytes; | ||
709 | } | ||
710 | EXPORT_SYMBOL(csum_and_copy_to_iter); | ||
711 | |||
951 | int iov_iter_npages(const struct iov_iter *i, int maxpages) | 712 | int iov_iter_npages(const struct iov_iter *i, int maxpages) |
952 | { | 713 | { |
953 | if (i->type & ITER_BVEC) | 714 | size_t size = i->count; |
954 | return iov_iter_npages_bvec(i, maxpages); | 715 | int npages = 0; |
955 | else | 716 | |
956 | return iov_iter_npages_iovec(i, maxpages); | 717 | if (!size) |
718 | return 0; | ||
719 | |||
720 | iterate_all_kinds(i, size, v, ({ | ||
721 | unsigned long p = (unsigned long)v.iov_base; | ||
722 | npages += DIV_ROUND_UP(p + v.iov_len, PAGE_SIZE) | ||
723 | - p / PAGE_SIZE; | ||
724 | if (npages >= maxpages) | ||
725 | return maxpages; | ||
726 | 0;}),({ | ||
727 | npages++; | ||
728 | if (npages >= maxpages) | ||
729 | return maxpages; | ||
730 | }),({ | ||
731 | unsigned long p = (unsigned long)v.iov_base; | ||
732 | npages += DIV_ROUND_UP(p + v.iov_len, PAGE_SIZE) | ||
733 | - p / PAGE_SIZE; | ||
734 | if (npages >= maxpages) | ||
735 | return maxpages; | ||
736 | }) | ||
737 | ) | ||
738 | return npages; | ||
957 | } | 739 | } |
958 | EXPORT_SYMBOL(iov_iter_npages); | 740 | EXPORT_SYMBOL(iov_iter_npages); |
diff --git a/net/atm/common.c b/net/atm/common.c index f59112944c91..b84057e41bd6 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
@@ -577,9 +577,6 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, | |||
577 | struct atm_vcc *vcc; | 577 | struct atm_vcc *vcc; |
578 | struct sk_buff *skb; | 578 | struct sk_buff *skb; |
579 | int eff, error; | 579 | int eff, error; |
580 | struct iov_iter from; | ||
581 | |||
582 | iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, size); | ||
583 | 580 | ||
584 | lock_sock(sk); | 581 | lock_sock(sk); |
585 | if (sock->state != SS_CONNECTED) { | 582 | if (sock->state != SS_CONNECTED) { |
@@ -634,7 +631,7 @@ int vcc_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, | |||
634 | goto out; | 631 | goto out; |
635 | skb->dev = NULL; /* for paths shared with net_device interfaces */ | 632 | skb->dev = NULL; /* for paths shared with net_device interfaces */ |
636 | ATM_SKB(skb)->atm_options = vcc->atm_options; | 633 | ATM_SKB(skb)->atm_options = vcc->atm_options; |
637 | if (copy_from_iter(skb_put(skb, size), size, &from) != size) { | 634 | if (copy_from_iter(skb_put(skb, size), size, &m->msg_iter) != size) { |
638 | kfree_skb(skb); | 635 | kfree_skb(skb); |
639 | error = -EFAULT; | 636 | error = -EFAULT; |
640 | goto out; | 637 | goto out; |
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index bdcaefd2db12..76617be1e797 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c | |||
@@ -537,12 +537,12 @@ static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb, | |||
537 | */ | 537 | */ |
538 | chan->data = skb; | 538 | chan->data = skb; |
539 | 539 | ||
540 | memset(&msg, 0, sizeof(msg)); | ||
541 | msg.msg_iov = (struct iovec *) &iv; | ||
542 | msg.msg_iovlen = 1; | ||
543 | iv.iov_base = skb->data; | 540 | iv.iov_base = skb->data; |
544 | iv.iov_len = skb->len; | 541 | iv.iov_len = skb->len; |
545 | 542 | ||
543 | memset(&msg, 0, sizeof(msg)); | ||
544 | iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, skb->len); | ||
545 | |||
546 | err = l2cap_chan_send(chan, &msg, skb->len); | 546 | err = l2cap_chan_send(chan, &msg, skb->len); |
547 | if (err > 0) { | 547 | if (err > 0) { |
548 | netdev->stats.tx_bytes += err; | 548 | netdev->stats.tx_bytes += err; |
@@ -1050,7 +1050,6 @@ static const struct l2cap_ops bt_6lowpan_chan_ops = { | |||
1050 | .suspend = chan_suspend_cb, | 1050 | .suspend = chan_suspend_cb, |
1051 | .get_sndtimeo = chan_get_sndtimeo_cb, | 1051 | .get_sndtimeo = chan_get_sndtimeo_cb, |
1052 | .alloc_skb = chan_alloc_skb_cb, | 1052 | .alloc_skb = chan_alloc_skb_cb, |
1053 | .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec, | ||
1054 | 1053 | ||
1055 | .teardown = l2cap_chan_no_teardown, | 1054 | .teardown = l2cap_chan_no_teardown, |
1056 | .defer = l2cap_chan_no_defer, | 1055 | .defer = l2cap_chan_no_defer, |
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 5dcade511fdb..cedfbda15dad 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -60,8 +60,7 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data) | |||
60 | 60 | ||
61 | memset(&msg, 0, sizeof(msg)); | 61 | memset(&msg, 0, sizeof(msg)); |
62 | 62 | ||
63 | msg.msg_iov = (struct iovec *) &iv; | 63 | iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, total_len); |
64 | msg.msg_iovlen = 1; | ||
65 | 64 | ||
66 | l2cap_chan_send(chan, &msg, total_len); | 65 | l2cap_chan_send(chan, &msg, total_len); |
67 | 66 | ||
@@ -720,7 +719,6 @@ static const struct l2cap_ops a2mp_chan_ops = { | |||
720 | .resume = l2cap_chan_no_resume, | 719 | .resume = l2cap_chan_no_resume, |
721 | .set_shutdown = l2cap_chan_no_set_shutdown, | 720 | .set_shutdown = l2cap_chan_no_set_shutdown, |
722 | .get_sndtimeo = l2cap_chan_no_get_sndtimeo, | 721 | .get_sndtimeo = l2cap_chan_no_get_sndtimeo, |
723 | .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec, | ||
724 | }; | 722 | }; |
725 | 723 | ||
726 | static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) | 724 | static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a8da7ea9c2c0..a2b6dfa38a0c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -2103,8 +2103,7 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, | |||
2103 | struct sk_buff **frag; | 2103 | struct sk_buff **frag; |
2104 | int sent = 0; | 2104 | int sent = 0; |
2105 | 2105 | ||
2106 | if (chan->ops->memcpy_fromiovec(chan, skb_put(skb, count), | 2106 | if (copy_from_iter(skb_put(skb, count), count, &msg->msg_iter) != count) |
2107 | msg->msg_iov, count)) | ||
2108 | return -EFAULT; | 2107 | return -EFAULT; |
2109 | 2108 | ||
2110 | sent += count; | 2109 | sent += count; |
@@ -2124,8 +2123,8 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, | |||
2124 | 2123 | ||
2125 | *frag = tmp; | 2124 | *frag = tmp; |
2126 | 2125 | ||
2127 | if (chan->ops->memcpy_fromiovec(chan, skb_put(*frag, count), | 2126 | if (copy_from_iter(skb_put(*frag, count), count, |
2128 | msg->msg_iov, count)) | 2127 | &msg->msg_iter) != count) |
2129 | return -EFAULT; | 2128 | return -EFAULT; |
2130 | 2129 | ||
2131 | sent += count; | 2130 | sent += count; |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index b0efb7202957..f65caf41953f 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -1336,13 +1336,6 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, | |||
1336 | return skb; | 1336 | return skb; |
1337 | } | 1337 | } |
1338 | 1338 | ||
1339 | static int l2cap_sock_memcpy_fromiovec_cb(struct l2cap_chan *chan, | ||
1340 | unsigned char *kdata, | ||
1341 | struct iovec *iov, int len) | ||
1342 | { | ||
1343 | return memcpy_fromiovec(kdata, iov, len); | ||
1344 | } | ||
1345 | |||
1346 | static void l2cap_sock_ready_cb(struct l2cap_chan *chan) | 1339 | static void l2cap_sock_ready_cb(struct l2cap_chan *chan) |
1347 | { | 1340 | { |
1348 | struct sock *sk = chan->data; | 1341 | struct sock *sk = chan->data; |
@@ -1427,7 +1420,6 @@ static const struct l2cap_ops l2cap_chan_ops = { | |||
1427 | .set_shutdown = l2cap_sock_set_shutdown_cb, | 1420 | .set_shutdown = l2cap_sock_set_shutdown_cb, |
1428 | .get_sndtimeo = l2cap_sock_get_sndtimeo_cb, | 1421 | .get_sndtimeo = l2cap_sock_get_sndtimeo_cb, |
1429 | .alloc_skb = l2cap_sock_alloc_skb_cb, | 1422 | .alloc_skb = l2cap_sock_alloc_skb_cb, |
1430 | .memcpy_fromiovec = l2cap_sock_memcpy_fromiovec_cb, | ||
1431 | }; | 1423 | }; |
1432 | 1424 | ||
1433 | static void l2cap_sock_destruct(struct sock *sk) | 1425 | static void l2cap_sock_destruct(struct sock *sk) |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 96bf16dcd9e9..6a46252fe66f 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -539,8 +539,7 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data) | |||
539 | 539 | ||
540 | memset(&msg, 0, sizeof(msg)); | 540 | memset(&msg, 0, sizeof(msg)); |
541 | 541 | ||
542 | msg.msg_iov = (struct iovec *) &iv; | 542 | iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, iv, 2, 1 + len); |
543 | msg.msg_iovlen = 2; | ||
544 | 543 | ||
545 | l2cap_chan_send(chan, &msg, 1 + len); | 544 | l2cap_chan_send(chan, &msg, 1 + len); |
546 | 545 | ||
@@ -2865,7 +2864,6 @@ static const struct l2cap_ops smp_chan_ops = { | |||
2865 | .suspend = l2cap_chan_no_suspend, | 2864 | .suspend = l2cap_chan_no_suspend, |
2866 | .set_shutdown = l2cap_chan_no_set_shutdown, | 2865 | .set_shutdown = l2cap_chan_no_set_shutdown, |
2867 | .get_sndtimeo = l2cap_chan_no_get_sndtimeo, | 2866 | .get_sndtimeo = l2cap_chan_no_get_sndtimeo, |
2868 | .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec, | ||
2869 | }; | 2867 | }; |
2870 | 2868 | ||
2871 | static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan) | 2869 | 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 = { | |||
2914 | .resume = l2cap_chan_no_resume, | 2912 | .resume = l2cap_chan_no_resume, |
2915 | .set_shutdown = l2cap_chan_no_set_shutdown, | 2913 | .set_shutdown = l2cap_chan_no_set_shutdown, |
2916 | .get_sndtimeo = l2cap_chan_no_get_sndtimeo, | 2914 | .get_sndtimeo = l2cap_chan_no_get_sndtimeo, |
2917 | .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec, | ||
2918 | }; | 2915 | }; |
2919 | 2916 | ||
2920 | static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) | 2917 | static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) |
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index ac618b0b8a4f..769b185fefbd 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c | |||
@@ -535,7 +535,7 @@ static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
535 | goto err; | 535 | goto err; |
536 | 536 | ||
537 | ret = -EINVAL; | 537 | ret = -EINVAL; |
538 | if (unlikely(msg->msg_iov->iov_base == NULL)) | 538 | if (unlikely(msg->msg_iter.iov->iov_base == NULL)) |
539 | goto err; | 539 | goto err; |
540 | noblock = msg->msg_flags & MSG_DONTWAIT; | 540 | noblock = msg->msg_flags & MSG_DONTWAIT; |
541 | 541 | ||
diff --git a/net/compat.c b/net/compat.c index 062f157d2a6b..3236b4167a32 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -37,13 +37,14 @@ ssize_t get_compat_msghdr(struct msghdr *kmsg, | |||
37 | struct iovec **iov) | 37 | struct iovec **iov) |
38 | { | 38 | { |
39 | compat_uptr_t uaddr, uiov, tmp3; | 39 | compat_uptr_t uaddr, uiov, tmp3; |
40 | compat_size_t nr_segs; | ||
40 | ssize_t err; | 41 | ssize_t err; |
41 | 42 | ||
42 | if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || | 43 | if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || |
43 | __get_user(uaddr, &umsg->msg_name) || | 44 | __get_user(uaddr, &umsg->msg_name) || |
44 | __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || | 45 | __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || |
45 | __get_user(uiov, &umsg->msg_iov) || | 46 | __get_user(uiov, &umsg->msg_iov) || |
46 | __get_user(kmsg->msg_iovlen, &umsg->msg_iovlen) || | 47 | __get_user(nr_segs, &umsg->msg_iovlen) || |
47 | __get_user(tmp3, &umsg->msg_control) || | 48 | __get_user(tmp3, &umsg->msg_control) || |
48 | __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || | 49 | __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || |
49 | __get_user(kmsg->msg_flags, &umsg->msg_flags)) | 50 | __get_user(kmsg->msg_flags, &umsg->msg_flags)) |
@@ -68,14 +69,15 @@ ssize_t get_compat_msghdr(struct msghdr *kmsg, | |||
68 | kmsg->msg_namelen = 0; | 69 | kmsg->msg_namelen = 0; |
69 | } | 70 | } |
70 | 71 | ||
71 | if (kmsg->msg_iovlen > UIO_MAXIOV) | 72 | if (nr_segs > UIO_MAXIOV) |
72 | return -EMSGSIZE; | 73 | return -EMSGSIZE; |
73 | 74 | ||
74 | err = compat_rw_copy_check_uvector(save_addr ? READ : WRITE, | 75 | err = compat_rw_copy_check_uvector(save_addr ? READ : WRITE, |
75 | compat_ptr(uiov), kmsg->msg_iovlen, | 76 | compat_ptr(uiov), nr_segs, |
76 | UIO_FASTIOV, *iov, iov); | 77 | UIO_FASTIOV, *iov, iov); |
77 | if (err >= 0) | 78 | if (err >= 0) |
78 | kmsg->msg_iov = *iov; | 79 | iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE, |
80 | *iov, nr_segs, err); | ||
79 | return err; | 81 | return err; |
80 | } | 82 | } |
81 | 83 | ||
diff --git a/net/core/datagram.c b/net/core/datagram.c index b6e303b0f01f..df493d68330c 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -310,90 +310,6 @@ int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags) | |||
310 | EXPORT_SYMBOL(skb_kill_datagram); | 310 | EXPORT_SYMBOL(skb_kill_datagram); |
311 | 311 | ||
312 | /** | 312 | /** |
313 | * skb_copy_datagram_iovec - Copy a datagram to an iovec. | ||
314 | * @skb: buffer to copy | ||
315 | * @offset: offset in the buffer to start copying from | ||
316 | * @to: io vector to copy to | ||
317 | * @len: amount of data to copy from buffer to iovec | ||
318 | * | ||
319 | * Note: the iovec is modified during the copy. | ||
320 | */ | ||
321 | int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, | ||
322 | struct iovec *to, int len) | ||
323 | { | ||
324 | int start = skb_headlen(skb); | ||
325 | int i, copy = start - offset; | ||
326 | struct sk_buff *frag_iter; | ||
327 | |||
328 | trace_skb_copy_datagram_iovec(skb, len); | ||
329 | |||
330 | /* Copy header. */ | ||
331 | if (copy > 0) { | ||
332 | if (copy > len) | ||
333 | copy = len; | ||
334 | if (memcpy_toiovec(to, skb->data + offset, copy)) | ||
335 | goto fault; | ||
336 | if ((len -= copy) == 0) | ||
337 | return 0; | ||
338 | offset += copy; | ||
339 | } | ||
340 | |||
341 | /* Copy paged appendix. Hmm... why does this look so complicated? */ | ||
342 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | ||
343 | int end; | ||
344 | const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | ||
345 | |||
346 | WARN_ON(start > offset + len); | ||
347 | |||
348 | end = start + skb_frag_size(frag); | ||
349 | if ((copy = end - offset) > 0) { | ||
350 | int err; | ||
351 | u8 *vaddr; | ||
352 | struct page *page = skb_frag_page(frag); | ||
353 | |||
354 | if (copy > len) | ||
355 | copy = len; | ||
356 | vaddr = kmap(page); | ||
357 | err = memcpy_toiovec(to, vaddr + frag->page_offset + | ||
358 | offset - start, copy); | ||
359 | kunmap(page); | ||
360 | if (err) | ||
361 | goto fault; | ||
362 | if (!(len -= copy)) | ||
363 | return 0; | ||
364 | offset += copy; | ||
365 | } | ||
366 | start = end; | ||
367 | } | ||
368 | |||
369 | skb_walk_frags(skb, frag_iter) { | ||
370 | int end; | ||
371 | |||
372 | WARN_ON(start > offset + len); | ||
373 | |||
374 | end = start + frag_iter->len; | ||
375 | if ((copy = end - offset) > 0) { | ||
376 | if (copy > len) | ||
377 | copy = len; | ||
378 | if (skb_copy_datagram_iovec(frag_iter, | ||
379 | offset - start, | ||
380 | to, copy)) | ||
381 | goto fault; | ||
382 | if ((len -= copy) == 0) | ||
383 | return 0; | ||
384 | offset += copy; | ||
385 | } | ||
386 | start = end; | ||
387 | } | ||
388 | if (!len) | ||
389 | return 0; | ||
390 | |||
391 | fault: | ||
392 | return -EFAULT; | ||
393 | } | ||
394 | EXPORT_SYMBOL(skb_copy_datagram_iovec); | ||
395 | |||
396 | /** | ||
397 | * skb_copy_datagram_iter - Copy a datagram to an iovec iterator. | 313 | * skb_copy_datagram_iter - Copy a datagram to an iovec iterator. |
398 | * @skb: buffer to copy | 314 | * @skb: buffer to copy |
399 | * @offset: offset in the buffer to start copying from | 315 | * @offset: offset in the buffer to start copying from |
@@ -615,27 +531,25 @@ int zerocopy_sg_from_iter(struct sk_buff *skb, struct iov_iter *from) | |||
615 | EXPORT_SYMBOL(zerocopy_sg_from_iter); | 531 | EXPORT_SYMBOL(zerocopy_sg_from_iter); |
616 | 532 | ||
617 | static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, | 533 | static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, |
618 | u8 __user *to, int len, | 534 | struct iov_iter *to, int len, |
619 | __wsum *csump) | 535 | __wsum *csump) |
620 | { | 536 | { |
621 | int start = skb_headlen(skb); | 537 | int start = skb_headlen(skb); |
622 | int i, copy = start - offset; | 538 | int i, copy = start - offset; |
623 | struct sk_buff *frag_iter; | 539 | struct sk_buff *frag_iter; |
624 | int pos = 0; | 540 | int pos = 0; |
541 | int n; | ||
625 | 542 | ||
626 | /* Copy header. */ | 543 | /* Copy header. */ |
627 | if (copy > 0) { | 544 | if (copy > 0) { |
628 | int err = 0; | ||
629 | if (copy > len) | 545 | if (copy > len) |
630 | copy = len; | 546 | copy = len; |
631 | *csump = csum_and_copy_to_user(skb->data + offset, to, copy, | 547 | n = csum_and_copy_to_iter(skb->data + offset, copy, csump, to); |
632 | *csump, &err); | 548 | if (n != copy) |
633 | if (err) | ||
634 | goto fault; | 549 | goto fault; |
635 | if ((len -= copy) == 0) | 550 | if ((len -= copy) == 0) |
636 | return 0; | 551 | return 0; |
637 | offset += copy; | 552 | offset += copy; |
638 | to += copy; | ||
639 | pos = copy; | 553 | pos = copy; |
640 | } | 554 | } |
641 | 555 | ||
@@ -647,26 +561,22 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, | |||
647 | 561 | ||
648 | end = start + skb_frag_size(frag); | 562 | end = start + skb_frag_size(frag); |
649 | if ((copy = end - offset) > 0) { | 563 | if ((copy = end - offset) > 0) { |
650 | __wsum csum2; | 564 | __wsum csum2 = 0; |
651 | int err = 0; | ||
652 | u8 *vaddr; | ||
653 | struct page *page = skb_frag_page(frag); | 565 | struct page *page = skb_frag_page(frag); |
566 | u8 *vaddr = kmap(page); | ||
654 | 567 | ||
655 | if (copy > len) | 568 | if (copy > len) |
656 | copy = len; | 569 | copy = len; |
657 | vaddr = kmap(page); | 570 | n = csum_and_copy_to_iter(vaddr + frag->page_offset + |
658 | csum2 = csum_and_copy_to_user(vaddr + | 571 | offset - start, copy, |
659 | frag->page_offset + | 572 | &csum2, to); |
660 | offset - start, | ||
661 | to, copy, 0, &err); | ||
662 | kunmap(page); | 573 | kunmap(page); |
663 | if (err) | 574 | if (n != copy) |
664 | goto fault; | 575 | goto fault; |
665 | *csump = csum_block_add(*csump, csum2, pos); | 576 | *csump = csum_block_add(*csump, csum2, pos); |
666 | if (!(len -= copy)) | 577 | if (!(len -= copy)) |
667 | return 0; | 578 | return 0; |
668 | offset += copy; | 579 | offset += copy; |
669 | to += copy; | ||
670 | pos += copy; | 580 | pos += copy; |
671 | } | 581 | } |
672 | start = end; | 582 | start = end; |
@@ -691,7 +601,6 @@ static int skb_copy_and_csum_datagram(const struct sk_buff *skb, int offset, | |||
691 | if ((len -= copy) == 0) | 601 | if ((len -= copy) == 0) |
692 | return 0; | 602 | return 0; |
693 | offset += copy; | 603 | offset += copy; |
694 | to += copy; | ||
695 | pos += copy; | 604 | pos += copy; |
696 | } | 605 | } |
697 | start = end; | 606 | start = end; |
@@ -744,20 +653,19 @@ __sum16 __skb_checksum_complete(struct sk_buff *skb) | |||
744 | EXPORT_SYMBOL(__skb_checksum_complete); | 653 | EXPORT_SYMBOL(__skb_checksum_complete); |
745 | 654 | ||
746 | /** | 655 | /** |
747 | * skb_copy_and_csum_datagram_iovec - Copy and checksum skb to user iovec. | 656 | * skb_copy_and_csum_datagram_msg - Copy and checksum skb to user iovec. |
748 | * @skb: skbuff | 657 | * @skb: skbuff |
749 | * @hlen: hardware length | 658 | * @hlen: hardware length |
750 | * @iov: io vector | 659 | * @msg: destination |
751 | * | 660 | * |
752 | * Caller _must_ check that skb will fit to this iovec. | 661 | * Caller _must_ check that skb will fit to this iovec. |
753 | * | 662 | * |
754 | * Returns: 0 - success. | 663 | * Returns: 0 - success. |
755 | * -EINVAL - checksum failure. | 664 | * -EINVAL - checksum failure. |
756 | * -EFAULT - fault during copy. Beware, in this case iovec | 665 | * -EFAULT - fault during copy. |
757 | * can be modified! | ||
758 | */ | 666 | */ |
759 | int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, | 667 | int skb_copy_and_csum_datagram_msg(struct sk_buff *skb, |
760 | int hlen, struct iovec *iov) | 668 | int hlen, struct msghdr *msg) |
761 | { | 669 | { |
762 | __wsum csum; | 670 | __wsum csum; |
763 | int chunk = skb->len - hlen; | 671 | int chunk = skb->len - hlen; |
@@ -765,28 +673,20 @@ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, | |||
765 | if (!chunk) | 673 | if (!chunk) |
766 | return 0; | 674 | return 0; |
767 | 675 | ||
768 | /* Skip filled elements. | 676 | if (iov_iter_count(&msg->msg_iter) < chunk) { |
769 | * Pretty silly, look at memcpy_toiovec, though 8) | ||
770 | */ | ||
771 | while (!iov->iov_len) | ||
772 | iov++; | ||
773 | |||
774 | if (iov->iov_len < chunk) { | ||
775 | if (__skb_checksum_complete(skb)) | 677 | if (__skb_checksum_complete(skb)) |
776 | goto csum_error; | 678 | goto csum_error; |
777 | if (skb_copy_datagram_iovec(skb, hlen, iov, chunk)) | 679 | if (skb_copy_datagram_msg(skb, hlen, msg, chunk)) |
778 | goto fault; | 680 | goto fault; |
779 | } else { | 681 | } else { |
780 | csum = csum_partial(skb->data, hlen, skb->csum); | 682 | csum = csum_partial(skb->data, hlen, skb->csum); |
781 | if (skb_copy_and_csum_datagram(skb, hlen, iov->iov_base, | 683 | if (skb_copy_and_csum_datagram(skb, hlen, &msg->msg_iter, |
782 | chunk, &csum)) | 684 | chunk, &csum)) |
783 | goto fault; | 685 | goto fault; |
784 | if (csum_fold(csum)) | 686 | if (csum_fold(csum)) |
785 | goto csum_error; | 687 | goto csum_error; |
786 | if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) | 688 | if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) |
787 | netdev_rx_csum_fault(skb->dev); | 689 | netdev_rx_csum_fault(skb->dev); |
788 | iov->iov_len -= chunk; | ||
789 | iov->iov_base += chunk; | ||
790 | } | 690 | } |
791 | return 0; | 691 | return 0; |
792 | csum_error: | 692 | csum_error: |
@@ -794,7 +694,7 @@ csum_error: | |||
794 | fault: | 694 | fault: |
795 | return -EFAULT; | 695 | return -EFAULT; |
796 | } | 696 | } |
797 | EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec); | 697 | EXPORT_SYMBOL(skb_copy_and_csum_datagram_msg); |
798 | 698 | ||
799 | /** | 699 | /** |
800 | * datagram_poll - generic datagram poll | 700 | * datagram_poll - generic datagram poll |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 4a929adf2ab7..b50861b22b6b 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -752,14 +752,16 @@ EXPORT_SYMBOL(ip_fragment); | |||
752 | int | 752 | int |
753 | ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) | 753 | ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) |
754 | { | 754 | { |
755 | struct iovec *iov = from; | 755 | struct msghdr *msg = from; |
756 | 756 | ||
757 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 757 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
758 | if (memcpy_fromiovecend(to, iov, offset, len) < 0) | 758 | /* XXX: stripping const */ |
759 | if (memcpy_fromiovecend(to, (struct iovec *)msg->msg_iter.iov, offset, len) < 0) | ||
759 | return -EFAULT; | 760 | return -EFAULT; |
760 | } else { | 761 | } else { |
761 | __wsum csum = 0; | 762 | __wsum csum = 0; |
762 | if (csum_partial_copy_fromiovecend(to, iov, offset, len, &csum) < 0) | 763 | /* XXX: stripping const */ |
764 | if (csum_partial_copy_fromiovecend(to, (struct iovec *)msg->msg_iter.iov, offset, len, &csum) < 0) | ||
763 | return -EFAULT; | 765 | return -EFAULT; |
764 | skb->csum = csum_block_add(skb->csum, csum, odd); | 766 | skb->csum = csum_block_add(skb->csum, csum, odd); |
765 | } | 767 | } |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 8dd4ae0424fc..c0d82f78d364 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -811,7 +811,8 @@ back_from_confirm: | |||
811 | pfh.icmph.checksum = 0; | 811 | pfh.icmph.checksum = 0; |
812 | pfh.icmph.un.echo.id = inet->inet_sport; | 812 | pfh.icmph.un.echo.id = inet->inet_sport; |
813 | pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence; | 813 | pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence; |
814 | pfh.iov = msg->msg_iov; | 814 | /* XXX: stripping const */ |
815 | pfh.iov = (struct iovec *)msg->msg_iter.iov; | ||
815 | pfh.wcheck = 0; | 816 | pfh.wcheck = 0; |
816 | pfh.family = AF_INET; | 817 | pfh.family = AF_INET; |
817 | 818 | ||
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 43385a9fa441..0bb68df5055d 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -82,7 +82,7 @@ | |||
82 | #include <linux/uio.h> | 82 | #include <linux/uio.h> |
83 | 83 | ||
84 | struct raw_frag_vec { | 84 | struct raw_frag_vec { |
85 | struct iovec *iov; | 85 | struct msghdr *msg; |
86 | union { | 86 | union { |
87 | struct icmphdr icmph; | 87 | struct icmphdr icmph; |
88 | char c[1]; | 88 | char c[1]; |
@@ -440,7 +440,7 @@ static int raw_probe_proto_opt(struct raw_frag_vec *rfv, struct flowi4 *fl4) | |||
440 | /* We only need the first two bytes. */ | 440 | /* We only need the first two bytes. */ |
441 | rfv->hlen = 2; | 441 | rfv->hlen = 2; |
442 | 442 | ||
443 | err = memcpy_fromiovec(rfv->hdr.c, rfv->iov, rfv->hlen); | 443 | err = memcpy_from_msg(rfv->hdr.c, rfv->msg, rfv->hlen); |
444 | if (err) | 444 | if (err) |
445 | return err; | 445 | return err; |
446 | 446 | ||
@@ -478,7 +478,7 @@ static int raw_getfrag(void *from, char *to, int offset, int len, int odd, | |||
478 | 478 | ||
479 | offset -= rfv->hlen; | 479 | offset -= rfv->hlen; |
480 | 480 | ||
481 | return ip_generic_getfrag(rfv->iov, to, offset, len, odd, skb); | 481 | return ip_generic_getfrag(rfv->msg, to, offset, len, odd, skb); |
482 | } | 482 | } |
483 | 483 | ||
484 | static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | 484 | 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, | |||
600 | daddr, saddr, 0, 0); | 600 | daddr, saddr, 0, 0); |
601 | 601 | ||
602 | if (!inet->hdrincl) { | 602 | if (!inet->hdrincl) { |
603 | rfv.iov = msg->msg_iov; | 603 | rfv.msg = msg; |
604 | rfv.hlen = 0; | 604 | rfv.hlen = 0; |
605 | 605 | ||
606 | err = raw_probe_proto_opt(&rfv, &fl4); | 606 | err = raw_probe_proto_opt(&rfv, &fl4); |
@@ -625,7 +625,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
625 | back_from_confirm: | 625 | back_from_confirm: |
626 | 626 | ||
627 | if (inet->hdrincl) | 627 | if (inet->hdrincl) |
628 | err = raw_send_hdrinc(sk, &fl4, msg->msg_iov, len, | 628 | /* XXX: stripping const */ |
629 | err = raw_send_hdrinc(sk, &fl4, (struct iovec *)msg->msg_iter.iov, len, | ||
629 | &rt, msg->msg_flags); | 630 | &rt, msg->msg_flags); |
630 | 631 | ||
631 | else { | 632 | else { |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 427aee33ffc0..3075723c729b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -1067,7 +1067,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, | |||
1067 | int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | 1067 | int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, |
1068 | size_t size) | 1068 | size_t size) |
1069 | { | 1069 | { |
1070 | struct iovec *iov; | 1070 | const struct iovec *iov; |
1071 | struct tcp_sock *tp = tcp_sk(sk); | 1071 | struct tcp_sock *tp = tcp_sk(sk); |
1072 | struct sk_buff *skb; | 1072 | struct sk_buff *skb; |
1073 | int iovlen, flags, err, copied = 0; | 1073 | int iovlen, flags, err, copied = 0; |
@@ -1118,8 +1118,8 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1118 | mss_now = tcp_send_mss(sk, &size_goal, flags); | 1118 | mss_now = tcp_send_mss(sk, &size_goal, flags); |
1119 | 1119 | ||
1120 | /* Ok commence sending. */ | 1120 | /* Ok commence sending. */ |
1121 | iovlen = msg->msg_iovlen; | 1121 | iovlen = msg->msg_iter.nr_segs; |
1122 | iov = msg->msg_iov; | 1122 | iov = msg->msg_iter.iov; |
1123 | copied = 0; | 1123 | copied = 0; |
1124 | 1124 | ||
1125 | err = -EPIPE; | 1125 | err = -EPIPE; |
@@ -1711,7 +1711,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1711 | if (!user_recv && !(flags & (MSG_TRUNC | MSG_PEEK))) { | 1711 | if (!user_recv && !(flags & (MSG_TRUNC | MSG_PEEK))) { |
1712 | user_recv = current; | 1712 | user_recv = current; |
1713 | tp->ucopy.task = user_recv; | 1713 | tp->ucopy.task = user_recv; |
1714 | tp->ucopy.iov = msg->msg_iov; | 1714 | tp->ucopy.msg = msg; |
1715 | } | 1715 | } |
1716 | 1716 | ||
1717 | tp->ucopy.len = len; | 1717 | tp->ucopy.len = len; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 69de1a1c05c9..075ab4d5af5e 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -4421,7 +4421,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) | |||
4421 | __set_current_state(TASK_RUNNING); | 4421 | __set_current_state(TASK_RUNNING); |
4422 | 4422 | ||
4423 | local_bh_enable(); | 4423 | local_bh_enable(); |
4424 | if (!skb_copy_datagram_iovec(skb, 0, tp->ucopy.iov, chunk)) { | 4424 | if (!skb_copy_datagram_msg(skb, 0, tp->ucopy.msg, chunk)) { |
4425 | tp->ucopy.len -= chunk; | 4425 | tp->ucopy.len -= chunk; |
4426 | tp->copied_seq += chunk; | 4426 | tp->copied_seq += chunk; |
4427 | eaten = (chunk == skb->len); | 4427 | eaten = (chunk == skb->len); |
@@ -4941,10 +4941,9 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen) | |||
4941 | 4941 | ||
4942 | local_bh_enable(); | 4942 | local_bh_enable(); |
4943 | if (skb_csum_unnecessary(skb)) | 4943 | if (skb_csum_unnecessary(skb)) |
4944 | err = skb_copy_datagram_iovec(skb, hlen, tp->ucopy.iov, chunk); | 4944 | err = skb_copy_datagram_msg(skb, hlen, tp->ucopy.msg, chunk); |
4945 | else | 4945 | else |
4946 | err = skb_copy_and_csum_datagram_iovec(skb, hlen, | 4946 | err = skb_copy_and_csum_datagram_msg(skb, hlen, tp->ucopy.msg); |
4947 | tp->ucopy.iov); | ||
4948 | 4947 | ||
4949 | if (!err) { | 4948 | if (!err) { |
4950 | tp->ucopy.len -= chunk; | 4949 | tp->ucopy.len -= chunk; |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f37ecf53ee8a..7f18262e2326 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -3073,7 +3073,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) | |||
3073 | syn_data->ip_summed = CHECKSUM_PARTIAL; | 3073 | syn_data->ip_summed = CHECKSUM_PARTIAL; |
3074 | memcpy(syn_data->cb, syn->cb, sizeof(syn->cb)); | 3074 | memcpy(syn_data->cb, syn->cb, sizeof(syn->cb)); |
3075 | if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space), | 3075 | if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space), |
3076 | fo->data->msg_iov, 0, space))) { | 3076 | fo->data->msg_iter.iov, 0, space))) { |
3077 | kfree_skb(syn_data); | 3077 | kfree_skb(syn_data); |
3078 | goto fallback; | 3078 | goto fallback; |
3079 | } | 3079 | } |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index dd8e00634563..13b4dcf86ef6 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1049,7 +1049,7 @@ back_from_confirm: | |||
1049 | 1049 | ||
1050 | /* Lockless fast path for the non-corking case. */ | 1050 | /* Lockless fast path for the non-corking case. */ |
1051 | if (!corkreq) { | 1051 | if (!corkreq) { |
1052 | skb = ip_make_skb(sk, fl4, getfrag, msg->msg_iov, ulen, | 1052 | skb = ip_make_skb(sk, fl4, getfrag, msg, ulen, |
1053 | sizeof(struct udphdr), &ipc, &rt, | 1053 | sizeof(struct udphdr), &ipc, &rt, |
1054 | msg->msg_flags); | 1054 | msg->msg_flags); |
1055 | err = PTR_ERR(skb); | 1055 | err = PTR_ERR(skb); |
@@ -1080,7 +1080,7 @@ back_from_confirm: | |||
1080 | 1080 | ||
1081 | do_append_data: | 1081 | do_append_data: |
1082 | up->len += ulen; | 1082 | up->len += ulen; |
1083 | err = ip_append_data(sk, fl4, getfrag, msg->msg_iov, ulen, | 1083 | err = ip_append_data(sk, fl4, getfrag, msg, ulen, |
1084 | sizeof(struct udphdr), &ipc, &rt, | 1084 | sizeof(struct udphdr), &ipc, &rt, |
1085 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); | 1085 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); |
1086 | if (err) | 1086 | if (err) |
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index 5b7a1ed2aba9..2d3148378a1f 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c | |||
@@ -163,7 +163,8 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
163 | pfh.icmph.checksum = 0; | 163 | pfh.icmph.checksum = 0; |
164 | pfh.icmph.un.echo.id = inet->inet_sport; | 164 | pfh.icmph.un.echo.id = inet->inet_sport; |
165 | pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence; | 165 | pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence; |
166 | pfh.iov = msg->msg_iov; | 166 | /* XXX: stripping const */ |
167 | pfh.iov = (struct iovec *)msg->msg_iter.iov; | ||
167 | pfh.wcheck = 0; | 168 | pfh.wcheck = 0; |
168 | pfh.family = AF_INET6; | 169 | pfh.family = AF_INET6; |
169 | 170 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 8baa53e17a30..ee25631f8c29 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -672,65 +672,62 @@ error: | |||
672 | return err; | 672 | return err; |
673 | } | 673 | } |
674 | 674 | ||
675 | static int rawv6_probe_proto_opt(struct flowi6 *fl6, struct msghdr *msg) | 675 | struct raw6_frag_vec { |
676 | struct msghdr *msg; | ||
677 | int hlen; | ||
678 | char c[4]; | ||
679 | }; | ||
680 | |||
681 | static int rawv6_probe_proto_opt(struct raw6_frag_vec *rfv, struct flowi6 *fl6) | ||
676 | { | 682 | { |
677 | struct iovec *iov; | 683 | int err = 0; |
678 | u8 __user *type = NULL; | 684 | switch (fl6->flowi6_proto) { |
679 | u8 __user *code = NULL; | 685 | case IPPROTO_ICMPV6: |
680 | u8 len = 0; | 686 | rfv->hlen = 2; |
681 | int probed = 0; | 687 | err = memcpy_from_msg(rfv->c, rfv->msg, rfv->hlen); |
682 | int i; | 688 | if (!err) { |
683 | 689 | fl6->fl6_icmp_type = rfv->c[0]; | |
684 | if (!msg->msg_iov) | 690 | fl6->fl6_icmp_code = rfv->c[1]; |
685 | return 0; | 691 | } |
692 | break; | ||
693 | case IPPROTO_MH: | ||
694 | rfv->hlen = 4; | ||
695 | err = memcpy_from_msg(rfv->c, rfv->msg, rfv->hlen); | ||
696 | if (!err) | ||
697 | fl6->fl6_mh_type = rfv->c[2]; | ||
698 | } | ||
699 | return err; | ||
700 | } | ||
686 | 701 | ||
687 | for (i = 0; i < msg->msg_iovlen; i++) { | 702 | static int raw6_getfrag(void *from, char *to, int offset, int len, int odd, |
688 | iov = &msg->msg_iov[i]; | 703 | struct sk_buff *skb) |
689 | if (!iov) | 704 | { |
690 | continue; | 705 | struct raw6_frag_vec *rfv = from; |
691 | 706 | ||
692 | switch (fl6->flowi6_proto) { | 707 | if (offset < rfv->hlen) { |
693 | case IPPROTO_ICMPV6: | 708 | int copy = min(rfv->hlen - offset, len); |
694 | /* check if one-byte field is readable or not. */ | ||
695 | if (iov->iov_base && iov->iov_len < 1) | ||
696 | break; | ||
697 | |||
698 | if (!type) { | ||
699 | type = iov->iov_base; | ||
700 | /* check if code field is readable or not. */ | ||
701 | if (iov->iov_len > 1) | ||
702 | code = type + 1; | ||
703 | } else if (!code) | ||
704 | code = iov->iov_base; | ||
705 | |||
706 | if (type && code) { | ||
707 | if (get_user(fl6->fl6_icmp_type, type) || | ||
708 | get_user(fl6->fl6_icmp_code, code)) | ||
709 | return -EFAULT; | ||
710 | probed = 1; | ||
711 | } | ||
712 | break; | ||
713 | case IPPROTO_MH: | ||
714 | if (iov->iov_base && iov->iov_len < 1) | ||
715 | break; | ||
716 | /* check if type field is readable or not. */ | ||
717 | if (iov->iov_len > 2 - len) { | ||
718 | u8 __user *p = iov->iov_base; | ||
719 | if (get_user(fl6->fl6_mh_type, &p[2 - len])) | ||
720 | return -EFAULT; | ||
721 | probed = 1; | ||
722 | } else | ||
723 | len += iov->iov_len; | ||
724 | 709 | ||
725 | break; | 710 | if (skb->ip_summed == CHECKSUM_PARTIAL) |
726 | default: | 711 | memcpy(to, rfv->c + offset, copy); |
727 | probed = 1; | 712 | else |
728 | break; | 713 | skb->csum = csum_block_add( |
729 | } | 714 | skb->csum, |
730 | if (probed) | 715 | csum_partial_copy_nocheck(rfv->c + offset, |
731 | break; | 716 | to, copy, 0), |
717 | odd); | ||
718 | |||
719 | odd = 0; | ||
720 | offset += copy; | ||
721 | to += copy; | ||
722 | len -= copy; | ||
723 | |||
724 | if (!len) | ||
725 | return 0; | ||
732 | } | 726 | } |
733 | return 0; | 727 | |
728 | offset -= rfv->hlen; | ||
729 | |||
730 | return ip_generic_getfrag(rfv->msg, to, offset, len, odd, skb); | ||
734 | } | 731 | } |
735 | 732 | ||
736 | static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | 733 | static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, |
@@ -745,6 +742,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
745 | struct ipv6_txoptions *opt = NULL; | 742 | struct ipv6_txoptions *opt = NULL; |
746 | struct ip6_flowlabel *flowlabel = NULL; | 743 | struct ip6_flowlabel *flowlabel = NULL; |
747 | struct dst_entry *dst = NULL; | 744 | struct dst_entry *dst = NULL; |
745 | struct raw6_frag_vec rfv; | ||
748 | struct flowi6 fl6; | 746 | struct flowi6 fl6; |
749 | int addr_len = msg->msg_namelen; | 747 | int addr_len = msg->msg_namelen; |
750 | int hlimit = -1; | 748 | int hlimit = -1; |
@@ -848,7 +846,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
848 | opt = ipv6_fixup_options(&opt_space, opt); | 846 | opt = ipv6_fixup_options(&opt_space, opt); |
849 | 847 | ||
850 | fl6.flowi6_proto = proto; | 848 | fl6.flowi6_proto = proto; |
851 | err = rawv6_probe_proto_opt(&fl6, msg); | 849 | rfv.msg = msg; |
850 | rfv.hlen = 0; | ||
851 | err = rawv6_probe_proto_opt(&rfv, &fl6); | ||
852 | if (err) | 852 | if (err) |
853 | goto out; | 853 | goto out; |
854 | 854 | ||
@@ -886,10 +886,11 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
886 | 886 | ||
887 | back_from_confirm: | 887 | back_from_confirm: |
888 | if (inet->hdrincl) | 888 | if (inet->hdrincl) |
889 | err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl6, &dst, msg->msg_flags); | 889 | /* XXX: stripping const */ |
890 | err = rawv6_send_hdrinc(sk, (struct iovec *)msg->msg_iter.iov, len, &fl6, &dst, msg->msg_flags); | ||
890 | else { | 891 | else { |
891 | lock_sock(sk); | 892 | lock_sock(sk); |
892 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, | 893 | err = ip6_append_data(sk, raw6_getfrag, &rfv, |
893 | len, 0, hlimit, tclass, opt, &fl6, (struct rt6_info *)dst, | 894 | len, 0, hlimit, tclass, opt, &fl6, (struct rt6_info *)dst, |
894 | msg->msg_flags, dontfrag); | 895 | msg->msg_flags, dontfrag); |
895 | 896 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 7f96432292ce..189dc4ae3eca 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -1312,7 +1312,7 @@ do_append_data: | |||
1312 | dontfrag = np->dontfrag; | 1312 | dontfrag = np->dontfrag; |
1313 | up->len += ulen; | 1313 | up->len += ulen; |
1314 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; | 1314 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; |
1315 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, | 1315 | err = ip6_append_data(sk, getfrag, msg, ulen, |
1316 | sizeof(struct udphdr), hlimit, tclass, opt, &fl6, | 1316 | sizeof(struct udphdr), hlimit, tclass, opt, &fl6, |
1317 | (struct rt6_info *)dst, | 1317 | (struct rt6_info *)dst, |
1318 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); | 1318 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag); |
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 2177b960da87..8611f1b63141 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c | |||
@@ -619,7 +619,7 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
619 | 619 | ||
620 | back_from_confirm: | 620 | back_from_confirm: |
621 | lock_sock(sk); | 621 | lock_sock(sk); |
622 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, | 622 | err = ip6_append_data(sk, ip_generic_getfrag, msg, |
623 | ulen, transhdrlen, hlimit, tclass, opt, | 623 | ulen, transhdrlen, hlimit, tclass, opt, |
624 | &fl6, (struct rt6_info *)dst, | 624 | &fl6, (struct rt6_info *)dst, |
625 | msg->msg_flags, dontfrag); | 625 | msg->msg_flags, dontfrag); |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 63aa5c8acf12..cc9bcf008b03 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -2305,7 +2305,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
2305 | } | 2305 | } |
2306 | 2306 | ||
2307 | if (netlink_tx_is_mmaped(sk) && | 2307 | if (netlink_tx_is_mmaped(sk) && |
2308 | msg->msg_iov->iov_base == NULL) { | 2308 | msg->msg_iter.iov->iov_base == NULL) { |
2309 | err = netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group, | 2309 | err = netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group, |
2310 | siocb); | 2310 | siocb); |
2311 | goto out; | 2311 | goto out; |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index efa844501136..ed2e620b61df 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -2408,11 +2408,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) | |||
2408 | unsigned short gso_type = 0; | 2408 | unsigned short gso_type = 0; |
2409 | int hlen, tlen; | 2409 | int hlen, tlen; |
2410 | int extra_len = 0; | 2410 | int extra_len = 0; |
2411 | struct iov_iter from; | ||
2412 | ssize_t n; | 2411 | ssize_t n; |
2413 | 2412 | ||
2414 | iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, len); | ||
2415 | |||
2416 | /* | 2413 | /* |
2417 | * Get and verify the address. | 2414 | * Get and verify the address. |
2418 | */ | 2415 | */ |
@@ -2451,7 +2448,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) | |||
2451 | len -= vnet_hdr_len; | 2448 | len -= vnet_hdr_len; |
2452 | 2449 | ||
2453 | err = -EFAULT; | 2450 | err = -EFAULT; |
2454 | n = copy_from_iter(&vnet_hdr, vnet_hdr_len, &from); | 2451 | n = copy_from_iter(&vnet_hdr, vnet_hdr_len, &msg->msg_iter); |
2455 | if (n != vnet_hdr_len) | 2452 | if (n != vnet_hdr_len) |
2456 | goto out_unlock; | 2453 | goto out_unlock; |
2457 | 2454 | ||
@@ -2522,7 +2519,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) | |||
2522 | } | 2519 | } |
2523 | 2520 | ||
2524 | /* Returns -EFAULT on error */ | 2521 | /* Returns -EFAULT on error */ |
2525 | err = skb_copy_datagram_from_iter(skb, offset, &from, len); | 2522 | err = skb_copy_datagram_from_iter(skb, offset, &msg->msg_iter, len); |
2526 | if (err) | 2523 | if (err) |
2527 | goto out_free; | 2524 | goto out_free; |
2528 | 2525 | ||
diff --git a/net/rds/recv.c b/net/rds/recv.c index 47d7b1029b33..f9ec1acd801c 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c | |||
@@ -404,7 +404,6 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
404 | int ret = 0, nonblock = msg_flags & MSG_DONTWAIT; | 404 | int ret = 0, nonblock = msg_flags & MSG_DONTWAIT; |
405 | DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name); | 405 | DECLARE_SOCKADDR(struct sockaddr_in *, sin, msg->msg_name); |
406 | struct rds_incoming *inc = NULL; | 406 | struct rds_incoming *inc = NULL; |
407 | struct iov_iter to; | ||
408 | 407 | ||
409 | /* udp_recvmsg()->sock_recvtimeo() gets away without locking too.. */ | 408 | /* udp_recvmsg()->sock_recvtimeo() gets away without locking too.. */ |
410 | timeo = sock_rcvtimeo(sk, nonblock); | 409 | timeo = sock_rcvtimeo(sk, nonblock); |
@@ -415,6 +414,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
415 | goto out; | 414 | goto out; |
416 | 415 | ||
417 | while (1) { | 416 | while (1) { |
417 | struct iov_iter save; | ||
418 | /* If there are pending notifications, do those - and nothing else */ | 418 | /* If there are pending notifications, do those - and nothing else */ |
419 | if (!list_empty(&rs->rs_notify_queue)) { | 419 | if (!list_empty(&rs->rs_notify_queue)) { |
420 | ret = rds_notify_queue_get(rs, msg); | 420 | ret = rds_notify_queue_get(rs, msg); |
@@ -450,8 +450,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
450 | rdsdebug("copying inc %p from %pI4:%u to user\n", inc, | 450 | rdsdebug("copying inc %p from %pI4:%u to user\n", inc, |
451 | &inc->i_conn->c_faddr, | 451 | &inc->i_conn->c_faddr, |
452 | ntohs(inc->i_hdr.h_sport)); | 452 | ntohs(inc->i_hdr.h_sport)); |
453 | iov_iter_init(&to, READ, msg->msg_iov, msg->msg_iovlen, size); | 453 | save = msg->msg_iter; |
454 | ret = inc->i_conn->c_trans->inc_copy_to_user(inc, &to); | 454 | ret = inc->i_conn->c_trans->inc_copy_to_user(inc, &msg->msg_iter); |
455 | if (ret < 0) | 455 | if (ret < 0) |
456 | break; | 456 | break; |
457 | 457 | ||
@@ -464,6 +464,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
464 | rds_inc_put(inc); | 464 | rds_inc_put(inc); |
465 | inc = NULL; | 465 | inc = NULL; |
466 | rds_stats_inc(s_recv_deliver_raced); | 466 | rds_stats_inc(s_recv_deliver_raced); |
467 | msg->msg_iter = save; | ||
467 | continue; | 468 | continue; |
468 | } | 469 | } |
469 | 470 | ||
diff --git a/net/rds/send.c b/net/rds/send.c index 4de62ead1c71..40a5629a0a13 100644 --- a/net/rds/send.c +++ b/net/rds/send.c | |||
@@ -934,9 +934,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
934 | int queued = 0, allocated_mr = 0; | 934 | int queued = 0, allocated_mr = 0; |
935 | int nonblock = msg->msg_flags & MSG_DONTWAIT; | 935 | int nonblock = msg->msg_flags & MSG_DONTWAIT; |
936 | long timeo = sock_sndtimeo(sk, nonblock); | 936 | long timeo = sock_sndtimeo(sk, nonblock); |
937 | struct iov_iter from; | ||
938 | 937 | ||
939 | iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, payload_len); | ||
940 | /* Mirror Linux UDP mirror of BSD error message compatibility */ | 938 | /* Mirror Linux UDP mirror of BSD error message compatibility */ |
941 | /* XXX: Perhaps MSG_MORE someday */ | 939 | /* XXX: Perhaps MSG_MORE someday */ |
942 | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_CMSG_COMPAT)) { | 940 | 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, | |||
984 | ret = -ENOMEM; | 982 | ret = -ENOMEM; |
985 | goto out; | 983 | goto out; |
986 | } | 984 | } |
987 | ret = rds_message_copy_from_user(rm, &from); | 985 | ret = rds_message_copy_from_user(rm, &msg->msg_iter); |
988 | if (ret) | 986 | if (ret) |
989 | goto out; | 987 | goto out; |
990 | } | 988 | } |
diff --git a/net/rxrpc/ar-output.c b/net/rxrpc/ar-output.c index 0b4b9a79f5ab..86e0f10aa2c0 100644 --- a/net/rxrpc/ar-output.c +++ b/net/rxrpc/ar-output.c | |||
@@ -531,14 +531,12 @@ static int rxrpc_send_data(struct kiocb *iocb, | |||
531 | struct rxrpc_skb_priv *sp; | 531 | struct rxrpc_skb_priv *sp; |
532 | unsigned char __user *from; | 532 | unsigned char __user *from; |
533 | struct sk_buff *skb; | 533 | struct sk_buff *skb; |
534 | struct iovec *iov; | 534 | const struct iovec *iov; |
535 | struct sock *sk = &rx->sk; | 535 | struct sock *sk = &rx->sk; |
536 | long timeo; | 536 | long timeo; |
537 | bool more; | 537 | bool more; |
538 | int ret, ioc, segment, copied; | 538 | int ret, ioc, segment, copied; |
539 | 539 | ||
540 | _enter(",,,{%zu},%zu", msg->msg_iovlen, len); | ||
541 | |||
542 | timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); | 540 | timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); |
543 | 541 | ||
544 | /* this should be in poll */ | 542 | /* this should be in poll */ |
@@ -547,8 +545,8 @@ static int rxrpc_send_data(struct kiocb *iocb, | |||
547 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) | 545 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) |
548 | return -EPIPE; | 546 | return -EPIPE; |
549 | 547 | ||
550 | iov = msg->msg_iov; | 548 | iov = msg->msg_iter.iov; |
551 | ioc = msg->msg_iovlen - 1; | 549 | ioc = msg->msg_iter.nr_segs - 1; |
552 | from = iov->iov_base; | 550 | from = iov->iov_base; |
553 | segment = iov->iov_len; | 551 | segment = iov->iov_len; |
554 | iov++; | 552 | iov++; |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 0397ac9fd98c..c92f96cda699 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1609,9 +1609,6 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1609 | __u16 sinfo_flags = 0; | 1609 | __u16 sinfo_flags = 0; |
1610 | long timeo; | 1610 | long timeo; |
1611 | int err; | 1611 | int err; |
1612 | struct iov_iter from; | ||
1613 | |||
1614 | iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, msg_len); | ||
1615 | 1612 | ||
1616 | err = 0; | 1613 | err = 0; |
1617 | sp = sctp_sk(sk); | 1614 | sp = sctp_sk(sk); |
@@ -1950,7 +1947,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1950 | } | 1947 | } |
1951 | 1948 | ||
1952 | /* Break the message into multiple chunks of maximum size. */ | 1949 | /* Break the message into multiple chunks of maximum size. */ |
1953 | datamsg = sctp_datamsg_from_user(asoc, sinfo, &from); | 1950 | datamsg = sctp_datamsg_from_user(asoc, sinfo, &msg->msg_iter); |
1954 | if (IS_ERR(datamsg)) { | 1951 | if (IS_ERR(datamsg)) { |
1955 | err = PTR_ERR(datamsg); | 1952 | err = PTR_ERR(datamsg); |
1956 | goto out_free; | 1953 | goto out_free; |
diff --git a/net/socket.c b/net/socket.c index f676ac4a3701..8809afccf7fa 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -689,8 +689,7 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg, | |||
689 | * the following is safe, since for compiler definitions of kvec and | 689 | * the following is safe, since for compiler definitions of kvec and |
690 | * iovec are identical, yielding the same in-core layout and alignment | 690 | * iovec are identical, yielding the same in-core layout and alignment |
691 | */ | 691 | */ |
692 | msg->msg_iov = (struct iovec *)vec; | 692 | iov_iter_init(&msg->msg_iter, WRITE, (struct iovec *)vec, num, size); |
693 | msg->msg_iovlen = num; | ||
694 | result = sock_sendmsg(sock, msg, size); | 693 | result = sock_sendmsg(sock, msg, size); |
695 | set_fs(oldfs); | 694 | set_fs(oldfs); |
696 | return result; | 695 | return result; |
@@ -853,7 +852,7 @@ int kernel_recvmsg(struct socket *sock, struct msghdr *msg, | |||
853 | * the following is safe, since for compiler definitions of kvec and | 852 | * the following is safe, since for compiler definitions of kvec and |
854 | * iovec are identical, yielding the same in-core layout and alignment | 853 | * iovec are identical, yielding the same in-core layout and alignment |
855 | */ | 854 | */ |
856 | msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num; | 855 | iov_iter_init(&msg->msg_iter, READ, (struct iovec *)vec, num, size); |
857 | result = sock_recvmsg(sock, msg, size, flags); | 856 | result = sock_recvmsg(sock, msg, size, flags); |
858 | set_fs(oldfs); | 857 | set_fs(oldfs); |
859 | return result; | 858 | return result; |
@@ -913,8 +912,7 @@ static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb, | |||
913 | msg->msg_namelen = 0; | 912 | msg->msg_namelen = 0; |
914 | msg->msg_control = NULL; | 913 | msg->msg_control = NULL; |
915 | msg->msg_controllen = 0; | 914 | msg->msg_controllen = 0; |
916 | msg->msg_iov = (struct iovec *)iov; | 915 | iov_iter_init(&msg->msg_iter, READ, iov, nr_segs, size); |
917 | msg->msg_iovlen = nr_segs; | ||
918 | msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; | 916 | msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; |
919 | 917 | ||
920 | return __sock_recvmsg(iocb, sock, msg, size, msg->msg_flags); | 918 | 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, | |||
953 | msg->msg_namelen = 0; | 951 | msg->msg_namelen = 0; |
954 | msg->msg_control = NULL; | 952 | msg->msg_control = NULL; |
955 | msg->msg_controllen = 0; | 953 | msg->msg_controllen = 0; |
956 | msg->msg_iov = (struct iovec *)iov; | 954 | iov_iter_init(&msg->msg_iter, WRITE, iov, nr_segs, size); |
957 | msg->msg_iovlen = nr_segs; | ||
958 | msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; | 955 | msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; |
959 | if (sock->type == SOCK_SEQPACKET) | 956 | if (sock->type == SOCK_SEQPACKET) |
960 | msg->msg_flags |= MSG_EOR; | 957 | msg->msg_flags |= MSG_EOR; |
@@ -1798,8 +1795,7 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, | |||
1798 | iov.iov_base = buff; | 1795 | iov.iov_base = buff; |
1799 | iov.iov_len = len; | 1796 | iov.iov_len = len; |
1800 | msg.msg_name = NULL; | 1797 | msg.msg_name = NULL; |
1801 | msg.msg_iov = &iov; | 1798 | iov_iter_init(&msg.msg_iter, WRITE, &iov, 1, len); |
1802 | msg.msg_iovlen = 1; | ||
1803 | msg.msg_control = NULL; | 1799 | msg.msg_control = NULL; |
1804 | msg.msg_controllen = 0; | 1800 | msg.msg_controllen = 0; |
1805 | msg.msg_namelen = 0; | 1801 | msg.msg_namelen = 0; |
@@ -1856,10 +1852,9 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, | |||
1856 | 1852 | ||
1857 | msg.msg_control = NULL; | 1853 | msg.msg_control = NULL; |
1858 | msg.msg_controllen = 0; | 1854 | msg.msg_controllen = 0; |
1859 | msg.msg_iovlen = 1; | ||
1860 | msg.msg_iov = &iov; | ||
1861 | iov.iov_len = size; | 1855 | iov.iov_len = size; |
1862 | iov.iov_base = ubuf; | 1856 | iov.iov_base = ubuf; |
1857 | iov_iter_init(&msg.msg_iter, READ, &iov, 1, size); | ||
1863 | /* Save some cycles and don't copy the address if not needed */ | 1858 | /* Save some cycles and don't copy the address if not needed */ |
1864 | msg.msg_name = addr ? (struct sockaddr *)&address : NULL; | 1859 | msg.msg_name = addr ? (struct sockaddr *)&address : NULL; |
1865 | /* We assume all kernel code knows the size of sockaddr_storage */ | 1860 | /* 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, | |||
1993 | { | 1988 | { |
1994 | struct sockaddr __user *uaddr; | 1989 | struct sockaddr __user *uaddr; |
1995 | struct iovec __user *uiov; | 1990 | struct iovec __user *uiov; |
1991 | size_t nr_segs; | ||
1996 | ssize_t err; | 1992 | ssize_t err; |
1997 | 1993 | ||
1998 | if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || | 1994 | if (!access_ok(VERIFY_READ, umsg, sizeof(*umsg)) || |
1999 | __get_user(uaddr, &umsg->msg_name) || | 1995 | __get_user(uaddr, &umsg->msg_name) || |
2000 | __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || | 1996 | __get_user(kmsg->msg_namelen, &umsg->msg_namelen) || |
2001 | __get_user(uiov, &umsg->msg_iov) || | 1997 | __get_user(uiov, &umsg->msg_iov) || |
2002 | __get_user(kmsg->msg_iovlen, &umsg->msg_iovlen) || | 1998 | __get_user(nr_segs, &umsg->msg_iovlen) || |
2003 | __get_user(kmsg->msg_control, &umsg->msg_control) || | 1999 | __get_user(kmsg->msg_control, &umsg->msg_control) || |
2004 | __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || | 2000 | __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || |
2005 | __get_user(kmsg->msg_flags, &umsg->msg_flags)) | 2001 | __get_user(kmsg->msg_flags, &umsg->msg_flags)) |
@@ -2029,14 +2025,15 @@ static ssize_t copy_msghdr_from_user(struct msghdr *kmsg, | |||
2029 | kmsg->msg_namelen = 0; | 2025 | kmsg->msg_namelen = 0; |
2030 | } | 2026 | } |
2031 | 2027 | ||
2032 | if (kmsg->msg_iovlen > UIO_MAXIOV) | 2028 | if (nr_segs > UIO_MAXIOV) |
2033 | return -EMSGSIZE; | 2029 | return -EMSGSIZE; |
2034 | 2030 | ||
2035 | err = rw_copy_check_uvector(save_addr ? READ : WRITE, | 2031 | err = rw_copy_check_uvector(save_addr ? READ : WRITE, |
2036 | uiov, kmsg->msg_iovlen, | 2032 | uiov, nr_segs, |
2037 | UIO_FASTIOV, *iov, iov); | 2033 | UIO_FASTIOV, *iov, iov); |
2038 | if (err >= 0) | 2034 | if (err >= 0) |
2039 | kmsg->msg_iov = *iov; | 2035 | iov_iter_init(&kmsg->msg_iter, save_addr ? READ : WRITE, |
2036 | *iov, nr_segs, err); | ||
2040 | return err; | 2037 | return err; |
2041 | } | 2038 | } |
2042 | 2039 | ||
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 5b0659791c07..a687b30a699c 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -194,7 +194,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, | |||
194 | __skb_queue_tail(list, skb); | 194 | __skb_queue_tail(list, skb); |
195 | skb_copy_to_linear_data(skb, mhdr, mhsz); | 195 | skb_copy_to_linear_data(skb, mhdr, mhsz); |
196 | pktpos = skb->data + mhsz; | 196 | pktpos = skb->data + mhsz; |
197 | if (!dsz || !memcpy_fromiovecend(pktpos, m->msg_iov, offset, | 197 | if (!dsz || !memcpy_fromiovecend(pktpos, m->msg_iter.iov, offset, |
198 | dsz)) | 198 | dsz)) |
199 | return dsz; | 199 | return dsz; |
200 | rc = -EFAULT; | 200 | rc = -EFAULT; |
@@ -224,7 +224,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, | |||
224 | if (drem < pktrem) | 224 | if (drem < pktrem) |
225 | pktrem = drem; | 225 | pktrem = drem; |
226 | 226 | ||
227 | if (memcpy_fromiovecend(pktpos, m->msg_iov, offset, pktrem)) { | 227 | if (memcpy_fromiovecend(pktpos, m->msg_iter.iov, offset, pktrem)) { |
228 | rc = -EFAULT; | 228 | rc = -EFAULT; |
229 | goto error; | 229 | goto error; |
230 | } | 230 | } |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 4450d6226602..8e1b10274b02 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -1459,9 +1459,6 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1459 | struct scm_cookie tmp_scm; | 1459 | struct scm_cookie tmp_scm; |
1460 | int max_level; | 1460 | int max_level; |
1461 | int data_len = 0; | 1461 | int data_len = 0; |
1462 | struct iov_iter from; | ||
1463 | |||
1464 | iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, len); | ||
1465 | 1462 | ||
1466 | if (NULL == siocb->scm) | 1463 | if (NULL == siocb->scm) |
1467 | siocb->scm = &tmp_scm; | 1464 | siocb->scm = &tmp_scm; |
@@ -1519,7 +1516,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1519 | skb_put(skb, len - data_len); | 1516 | skb_put(skb, len - data_len); |
1520 | skb->data_len = data_len; | 1517 | skb->data_len = data_len; |
1521 | skb->len = len; | 1518 | skb->len = len; |
1522 | err = skb_copy_datagram_from_iter(skb, 0, &from, len); | 1519 | err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, len); |
1523 | if (err) | 1520 | if (err) |
1524 | goto out_free; | 1521 | goto out_free; |
1525 | 1522 | ||
@@ -1641,9 +1638,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1641 | bool fds_sent = false; | 1638 | bool fds_sent = false; |
1642 | int max_level; | 1639 | int max_level; |
1643 | int data_len; | 1640 | int data_len; |
1644 | struct iov_iter from; | ||
1645 | |||
1646 | iov_iter_init(&from, WRITE, msg->msg_iov, msg->msg_iovlen, len); | ||
1647 | 1641 | ||
1648 | if (NULL == siocb->scm) | 1642 | if (NULL == siocb->scm) |
1649 | siocb->scm = &tmp_scm; | 1643 | siocb->scm = &tmp_scm; |
@@ -1700,7 +1694,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1700 | skb_put(skb, size - data_len); | 1694 | skb_put(skb, size - data_len); |
1701 | skb->data_len = data_len; | 1695 | skb->data_len = data_len; |
1702 | skb->len = size; | 1696 | skb->len = size; |
1703 | err = skb_copy_datagram_from_iter(skb, 0, &from, size); | 1697 | err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size); |
1704 | if (err) { | 1698 | if (err) { |
1705 | kfree_skb(skb); | 1699 | kfree_skb(skb); |
1706 | goto out_err; | 1700 | goto out_err; |
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c index c1c038952973..02d2e5229240 100644 --- a/net/vmw_vsock/vmci_transport.c +++ b/net/vmw_vsock/vmci_transport.c | |||
@@ -1840,9 +1840,9 @@ static ssize_t vmci_transport_stream_dequeue( | |||
1840 | int flags) | 1840 | int flags) |
1841 | { | 1841 | { |
1842 | if (flags & MSG_PEEK) | 1842 | if (flags & MSG_PEEK) |
1843 | return vmci_qpair_peekv(vmci_trans(vsk)->qpair, msg->msg_iov, len, 0); | 1843 | return vmci_qpair_peekv(vmci_trans(vsk)->qpair, msg, len, 0); |
1844 | else | 1844 | else |
1845 | return vmci_qpair_dequev(vmci_trans(vsk)->qpair, msg->msg_iov, len, 0); | 1845 | return vmci_qpair_dequev(vmci_trans(vsk)->qpair, msg, len, 0); |
1846 | } | 1846 | } |
1847 | 1847 | ||
1848 | static ssize_t vmci_transport_stream_enqueue( | 1848 | static ssize_t vmci_transport_stream_enqueue( |
@@ -1850,7 +1850,8 @@ static ssize_t vmci_transport_stream_enqueue( | |||
1850 | struct msghdr *msg, | 1850 | struct msghdr *msg, |
1851 | size_t len) | 1851 | size_t len) |
1852 | { | 1852 | { |
1853 | return vmci_qpair_enquev(vmci_trans(vsk)->qpair, msg->msg_iov, len, 0); | 1853 | /* XXX: stripping const */ |
1854 | return vmci_qpair_enquev(vmci_trans(vsk)->qpair, (struct iovec *)msg->msg_iter.iov, len, 0); | ||
1854 | } | 1855 | } |
1855 | 1856 | ||
1856 | static s64 vmci_transport_stream_has_data(struct vsock_sock *vsk) | 1857 | static s64 vmci_transport_stream_has_data(struct vsock_sock *vsk) |