forked from mirrors/linux
		
	vsock: add support for SIOCOUTQ ioctl
Add support for ioctl(s) in AF_VSOCK. The only ioctl available is SIOCOUTQ/TIOCOUTQ, which returns the number of unsent bytes in the socket. This information is transport-specific and is delegated to them using a callback. Suggested-by: Daan De Meyer <daan.j.demeyer@gmail.com> Signed-off-by: Luigi Leonardi <luigi.leonardi@outlook.com> Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									5fe164fb0e
								
							
						
					
					
						commit
						744500d81f
					
				
					 2 changed files with 58 additions and 3 deletions
				
			
		|  | @ -169,6 +169,9 @@ struct vsock_transport { | ||||||
| 	void (*notify_buffer_size)(struct vsock_sock *, u64 *); | 	void (*notify_buffer_size)(struct vsock_sock *, u64 *); | ||||||
| 	int (*notify_set_rcvlowat)(struct vsock_sock *vsk, int val); | 	int (*notify_set_rcvlowat)(struct vsock_sock *vsk, int val); | ||||||
| 
 | 
 | ||||||
|  | 	/* SIOCOUTQ ioctl */ | ||||||
|  | 	ssize_t (*unsent_bytes)(struct vsock_sock *vsk); | ||||||
|  | 
 | ||||||
| 	/* Shutdown. */ | 	/* Shutdown. */ | ||||||
| 	int (*shutdown)(struct vsock_sock *, int); | 	int (*shutdown)(struct vsock_sock *, int); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -112,6 +112,7 @@ | ||||||
| #include <net/sock.h> | #include <net/sock.h> | ||||||
| #include <net/af_vsock.h> | #include <net/af_vsock.h> | ||||||
| #include <uapi/linux/vm_sockets.h> | #include <uapi/linux/vm_sockets.h> | ||||||
|  | #include <uapi/asm-generic/ioctls.h> | ||||||
| 
 | 
 | ||||||
| static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr); | static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr); | ||||||
| static void vsock_sk_destruct(struct sock *sk); | static void vsock_sk_destruct(struct sock *sk); | ||||||
|  | @ -1292,6 +1293,57 @@ int vsock_dgram_recvmsg(struct socket *sock, struct msghdr *msg, | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(vsock_dgram_recvmsg); | EXPORT_SYMBOL_GPL(vsock_dgram_recvmsg); | ||||||
| 
 | 
 | ||||||
|  | static int vsock_do_ioctl(struct socket *sock, unsigned int cmd, | ||||||
|  | 			  int __user *arg) | ||||||
|  | { | ||||||
|  | 	struct sock *sk = sock->sk; | ||||||
|  | 	struct vsock_sock *vsk; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	vsk = vsock_sk(sk); | ||||||
|  | 
 | ||||||
|  | 	switch (cmd) { | ||||||
|  | 	case SIOCOUTQ: { | ||||||
|  | 		ssize_t n_bytes; | ||||||
|  | 
 | ||||||
|  | 		if (!vsk->transport || !vsk->transport->unsent_bytes) { | ||||||
|  | 			ret = -EOPNOTSUPP; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (sock_type_connectible(sk->sk_type) && sk->sk_state == TCP_LISTEN) { | ||||||
|  | 			ret = -EINVAL; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		n_bytes = vsk->transport->unsent_bytes(vsk); | ||||||
|  | 		if (n_bytes < 0) { | ||||||
|  | 			ret = n_bytes; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		ret = put_user(n_bytes, arg); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	default: | ||||||
|  | 		ret = -ENOIOCTLCMD; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int vsock_ioctl(struct socket *sock, unsigned int cmd, | ||||||
|  | 		       unsigned long arg) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	lock_sock(sock->sk); | ||||||
|  | 	ret = vsock_do_ioctl(sock, cmd, (int __user *)arg); | ||||||
|  | 	release_sock(sock->sk); | ||||||
|  | 
 | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static const struct proto_ops vsock_dgram_ops = { | static const struct proto_ops vsock_dgram_ops = { | ||||||
| 	.family = PF_VSOCK, | 	.family = PF_VSOCK, | ||||||
| 	.owner = THIS_MODULE, | 	.owner = THIS_MODULE, | ||||||
|  | @ -1302,7 +1354,7 @@ static const struct proto_ops vsock_dgram_ops = { | ||||||
| 	.accept = sock_no_accept, | 	.accept = sock_no_accept, | ||||||
| 	.getname = vsock_getname, | 	.getname = vsock_getname, | ||||||
| 	.poll = vsock_poll, | 	.poll = vsock_poll, | ||||||
| 	.ioctl = sock_no_ioctl, | 	.ioctl = vsock_ioctl, | ||||||
| 	.listen = sock_no_listen, | 	.listen = sock_no_listen, | ||||||
| 	.shutdown = vsock_shutdown, | 	.shutdown = vsock_shutdown, | ||||||
| 	.sendmsg = vsock_dgram_sendmsg, | 	.sendmsg = vsock_dgram_sendmsg, | ||||||
|  | @ -2286,7 +2338,7 @@ static const struct proto_ops vsock_stream_ops = { | ||||||
| 	.accept = vsock_accept, | 	.accept = vsock_accept, | ||||||
| 	.getname = vsock_getname, | 	.getname = vsock_getname, | ||||||
| 	.poll = vsock_poll, | 	.poll = vsock_poll, | ||||||
| 	.ioctl = sock_no_ioctl, | 	.ioctl = vsock_ioctl, | ||||||
| 	.listen = vsock_listen, | 	.listen = vsock_listen, | ||||||
| 	.shutdown = vsock_shutdown, | 	.shutdown = vsock_shutdown, | ||||||
| 	.setsockopt = vsock_connectible_setsockopt, | 	.setsockopt = vsock_connectible_setsockopt, | ||||||
|  | @ -2308,7 +2360,7 @@ static const struct proto_ops vsock_seqpacket_ops = { | ||||||
| 	.accept = vsock_accept, | 	.accept = vsock_accept, | ||||||
| 	.getname = vsock_getname, | 	.getname = vsock_getname, | ||||||
| 	.poll = vsock_poll, | 	.poll = vsock_poll, | ||||||
| 	.ioctl = sock_no_ioctl, | 	.ioctl = vsock_ioctl, | ||||||
| 	.listen = vsock_listen, | 	.listen = vsock_listen, | ||||||
| 	.shutdown = vsock_shutdown, | 	.shutdown = vsock_shutdown, | ||||||
| 	.setsockopt = vsock_connectible_setsockopt, | 	.setsockopt = vsock_connectible_setsockopt, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Luigi Leonardi
						Luigi Leonardi