diff options
Diffstat (limited to 'drivers/net/tap.c')
| -rw-r--r-- | drivers/net/tap.c | 25 | 
1 files changed, 21 insertions, 4 deletions
| diff --git a/drivers/net/tap.c b/drivers/net/tap.c index 4d4173d25dd0..9af3239d6ad5 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -824,15 +824,17 @@ done:  static ssize_t tap_do_read(struct tap_queue *q,  			   struct iov_iter *to, -			   int noblock) +			   int noblock, struct sk_buff *skb)  {  	DEFINE_WAIT(wait); -	struct sk_buff *skb;  	ssize_t ret = 0;  	if (!iov_iter_count(to))  		return 0; +	if (skb) +		goto put; +  	while (1) {  		if (!noblock)  			prepare_to_wait(sk_sleep(&q->sk), &wait, @@ -856,6 +858,7 @@ static ssize_t tap_do_read(struct tap_queue *q,  	if (!noblock)  		finish_wait(sk_sleep(&q->sk), &wait); +put:  	if (skb) {  		ret = tap_put_user(q, skb, to);  		if (unlikely(ret < 0)) @@ -872,7 +875,7 @@ static ssize_t tap_read_iter(struct kiocb *iocb, struct iov_iter *to)  	struct tap_queue *q = file->private_data;  	ssize_t len = iov_iter_count(to), ret; -	ret = tap_do_read(q, to, file->f_flags & O_NONBLOCK); +	ret = tap_do_read(q, to, file->f_flags & O_NONBLOCK, NULL);  	ret = min_t(ssize_t, ret, len);  	if (ret > 0)  		iocb->ki_pos = ret; @@ -1155,7 +1158,8 @@ static int tap_recvmsg(struct socket *sock, struct msghdr *m,  	int ret;  	if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))  		return -EINVAL; -	ret = tap_do_read(q, &m->msg_iter, flags & MSG_DONTWAIT); +	ret = tap_do_read(q, &m->msg_iter, flags & MSG_DONTWAIT, +			  m->msg_control);  	if (ret > total_len) {  		m->msg_flags |= MSG_TRUNC;  		ret = flags & MSG_TRUNC ? ret : total_len; @@ -1193,6 +1197,19 @@ struct socket *tap_get_socket(struct file *file)  }  EXPORT_SYMBOL_GPL(tap_get_socket); +struct skb_array *tap_get_skb_array(struct file *file) +{ +	struct tap_queue *q; + +	if (file->f_op != &tap_fops) +		return ERR_PTR(-EINVAL); +	q = file->private_data; +	if (!q) +		return ERR_PTR(-EBADFD); +	return &q->skb_array; +} +EXPORT_SYMBOL_GPL(tap_get_skb_array); +  int tap_queue_resize(struct tap_dev *tap)  {  	struct net_device *dev = tap->dev; | 
