diff options
Diffstat (limited to 'drivers/net/macvtap.c')
| -rw-r--r-- | drivers/net/macvtap.c | 46 | 
1 files changed, 35 insertions, 11 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index abba3cc81f1..a8a94e2f6dd 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -37,6 +37,8 @@  struct macvtap_queue {  	struct sock sk;  	struct socket sock; +	struct socket_wq wq; +	int vnet_hdr_sz;  	struct macvlan_dev *vlan;  	struct file *file;  	unsigned int flags; @@ -181,7 +183,7 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)  		return -ENOLINK;  	skb_queue_tail(&q->sk.sk_receive_queue, skb); -	wake_up_interruptible_poll(q->sk.sk_sleep, POLLIN | POLLRDNORM | POLLRDBAND); +	wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND);  	return 0;  } @@ -242,12 +244,15 @@ static struct rtnl_link_ops macvtap_link_ops __read_mostly = {  static void macvtap_sock_write_space(struct sock *sk)  { +	wait_queue_head_t *wqueue; +  	if (!sock_writeable(sk) ||  	    !test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags))  		return; -	if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) -		wake_up_interruptible_poll(sk->sk_sleep, POLLOUT | POLLWRNORM | POLLWRBAND); +	wqueue = sk_sleep(sk); +	if (wqueue && waitqueue_active(wqueue)) +		wake_up_interruptible_poll(wqueue, POLLOUT | POLLWRNORM | POLLWRBAND);  }  static int macvtap_open(struct inode *inode, struct file *file) @@ -272,7 +277,8 @@ static int macvtap_open(struct inode *inode, struct file *file)  	if (!q)  		goto out; -	init_waitqueue_head(&q->sock.wait); +	q->sock.wq = &q->wq; +	init_waitqueue_head(&q->wq.wait);  	q->sock.type = SOCK_RAW;  	q->sock.state = SS_CONNECTED;  	q->sock.file = file; @@ -280,6 +286,7 @@ static int macvtap_open(struct inode *inode, struct file *file)  	sock_init_data(&q->sock, &q->sk);  	q->sk.sk_write_space = macvtap_sock_write_space;  	q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; +	q->vnet_hdr_sz = sizeof(struct virtio_net_hdr);  	err = macvtap_set_queue(dev, file, q);  	if (err) @@ -308,7 +315,7 @@ static unsigned int macvtap_poll(struct file *file, poll_table * wait)  		goto out;  	mask = 0; -	poll_wait(file, &q->sock.wait, wait); +	poll_wait(file, &q->wq.wait, wait);  	if (!skb_queue_empty(&q->sk.sk_receive_queue))  		mask |= POLLIN | POLLRDNORM; @@ -440,14 +447,14 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,  	int vnet_hdr_len = 0;  	if (q->flags & IFF_VNET_HDR) { -		vnet_hdr_len = sizeof(vnet_hdr); +		vnet_hdr_len = q->vnet_hdr_sz;  		err = -EINVAL;  		if ((len -= vnet_hdr_len) < 0)  			goto err;  		err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, -					   vnet_hdr_len); +					   sizeof(vnet_hdr));  		if (err < 0)  			goto err;  		if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && @@ -529,7 +536,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,  	if (q->flags & IFF_VNET_HDR) {  		struct virtio_net_hdr vnet_hdr; -		vnet_hdr_len = sizeof (vnet_hdr); +		vnet_hdr_len = q->vnet_hdr_sz;  		if ((len -= vnet_hdr_len) < 0)  			return -EINVAL; @@ -537,7 +544,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,  		if (ret)  			return ret; -		if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, vnet_hdr_len)) +		if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr)))  			return -EFAULT;  	} @@ -562,7 +569,7 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb,  	struct sk_buff *skb;  	ssize_t ret = 0; -	add_wait_queue(q->sk.sk_sleep, &wait); +	add_wait_queue(sk_sleep(&q->sk), &wait);  	while (len) {  		current->state = TASK_INTERRUPTIBLE; @@ -587,7 +594,7 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb,  	}  	current->state = TASK_RUNNING; -	remove_wait_queue(q->sk.sk_sleep, &wait); +	remove_wait_queue(sk_sleep(&q->sk), &wait);  	return ret;  } @@ -622,6 +629,8 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,  	struct ifreq __user *ifr = argp;  	unsigned int __user *up = argp;  	unsigned int u; +	int __user *sp = argp; +	int s;  	int ret;  	switch (cmd) { @@ -667,6 +676,21 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,  		q->sk.sk_sndbuf = u;  		return 0; +	case TUNGETVNETHDRSZ: +		s = q->vnet_hdr_sz; +		if (put_user(s, sp)) +			return -EFAULT; +		return 0; + +	case TUNSETVNETHDRSZ: +		if (get_user(s, sp)) +			return -EFAULT; +		if (s < (int)sizeof(struct virtio_net_hdr)) +			return -EINVAL; + +		q->vnet_hdr_sz = s; +		return 0; +  	case TUNSETOFFLOAD:  		/* let the user check for future flags */  		if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |  |