diff options
author | Jason Wang <jasowang@redhat.com> | 2017-05-17 00:14:44 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-05-18 10:07:41 -0400 |
commit | 3b4ba04acca8f98a62fd014a0826ea10bc93cde3 (patch) | |
tree | d070e9d5ecf191c65a3759bf2f95a0b1ddf0f5b2 /drivers/net/tap.c | |
parent | ac77cfd4258fb8174766a92d118436da7f9dabf1 (diff) |
tap: support receiving skb from msg_control
This patch makes tap_recvmsg() can receive from skb from its caller
through msg_control. Vhost_net will be the first user.
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tap.c')
-rw-r--r-- | drivers/net/tap.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/drivers/net/tap.c b/drivers/net/tap.c index abdaf867774d..9af3239d6ad5 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c | |||
@@ -824,15 +824,17 @@ done: | |||
824 | 824 | ||
825 | static ssize_t tap_do_read(struct tap_queue *q, | 825 | static ssize_t tap_do_read(struct tap_queue *q, |
826 | struct iov_iter *to, | 826 | struct iov_iter *to, |
827 | int noblock) | 827 | int noblock, struct sk_buff *skb) |
828 | { | 828 | { |
829 | DEFINE_WAIT(wait); | 829 | DEFINE_WAIT(wait); |
830 | struct sk_buff *skb; | ||
831 | ssize_t ret = 0; | 830 | ssize_t ret = 0; |
832 | 831 | ||
833 | if (!iov_iter_count(to)) | 832 | if (!iov_iter_count(to)) |
834 | return 0; | 833 | return 0; |
835 | 834 | ||
835 | if (skb) | ||
836 | goto put; | ||
837 | |||
836 | while (1) { | 838 | while (1) { |
837 | if (!noblock) | 839 | if (!noblock) |
838 | prepare_to_wait(sk_sleep(&q->sk), &wait, | 840 | prepare_to_wait(sk_sleep(&q->sk), &wait, |
@@ -856,6 +858,7 @@ static ssize_t tap_do_read(struct tap_queue *q, | |||
856 | if (!noblock) | 858 | if (!noblock) |
857 | finish_wait(sk_sleep(&q->sk), &wait); | 859 | finish_wait(sk_sleep(&q->sk), &wait); |
858 | 860 | ||
861 | put: | ||
859 | if (skb) { | 862 | if (skb) { |
860 | ret = tap_put_user(q, skb, to); | 863 | ret = tap_put_user(q, skb, to); |
861 | if (unlikely(ret < 0)) | 864 | if (unlikely(ret < 0)) |
@@ -872,7 +875,7 @@ static ssize_t tap_read_iter(struct kiocb *iocb, struct iov_iter *to) | |||
872 | struct tap_queue *q = file->private_data; | 875 | struct tap_queue *q = file->private_data; |
873 | ssize_t len = iov_iter_count(to), ret; | 876 | ssize_t len = iov_iter_count(to), ret; |
874 | 877 | ||
875 | ret = tap_do_read(q, to, file->f_flags & O_NONBLOCK); | 878 | ret = tap_do_read(q, to, file->f_flags & O_NONBLOCK, NULL); |
876 | ret = min_t(ssize_t, ret, len); | 879 | ret = min_t(ssize_t, ret, len); |
877 | if (ret > 0) | 880 | if (ret > 0) |
878 | iocb->ki_pos = ret; | 881 | iocb->ki_pos = ret; |
@@ -1155,7 +1158,8 @@ static int tap_recvmsg(struct socket *sock, struct msghdr *m, | |||
1155 | int ret; | 1158 | int ret; |
1156 | if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) | 1159 | if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) |
1157 | return -EINVAL; | 1160 | return -EINVAL; |
1158 | ret = tap_do_read(q, &m->msg_iter, flags & MSG_DONTWAIT); | 1161 | ret = tap_do_read(q, &m->msg_iter, flags & MSG_DONTWAIT, |
1162 | m->msg_control); | ||
1159 | if (ret > total_len) { | 1163 | if (ret > total_len) { |
1160 | m->msg_flags |= MSG_TRUNC; | 1164 | m->msg_flags |= MSG_TRUNC; |
1161 | ret = flags & MSG_TRUNC ? ret : total_len; | 1165 | ret = flags & MSG_TRUNC ? ret : total_len; |