diff --git a/include/uapi/linux/hyperv.h b/include/uapi/linux/hyperv.h index d942996..eb3e44b 100644 --- a/include/uapi/linux/hyperv.h +++ b/include/uapi/linux/hyperv.h @@ -405,12 +405,11 @@ struct hv_kvp_ip_msg { * the first 3 fields. Refer to: * https://en.wikipedia.org/wiki/Globally_unique_identifier */ -#define guid_t uuid_le struct sockaddr_hv { __kernel_sa_family_t shv_family; /* Address family */ u16 reserved; /* Must be Zero */ - guid_t shv_vm_id; /* VM ID */ - guid_t shv_service_id; /* Service ID */ + uuid_le shv_vm_guid; /* VM ID */ + uuid_le shv_service_guid; /* Service ID */ }; #define SHV_VMID_GUEST NULL_UUID_LE diff --git a/net/hv_sock/Kconfig b/net/hv_sock/Kconfig index 1f41848..ff84875 100644 --- a/net/hv_sock/Kconfig +++ b/net/hv_sock/Kconfig @@ -3,8 +3,8 @@ config HYPERV_SOCK depends on HYPERV default m if HYPERV help - Hyper-V Sockets is somewhat like TCP over VMBus, allowing - communication between Linux guest and Hyper-V host without TCP/IP. + Hyper-V Sockets is a socket interface for high speed + communication between Linux guest and Hyper-V host over VMBus. To compile this driver as a module, choose M here: the module will be called hv_sock. diff --git a/net/hv_sock/af_hvsock.c b/net/hv_sock/af_hvsock.c index f339f38..d86b879 100644 --- a/net/hv_sock/af_hvsock.c +++ b/net/hv_sock/af_hvsock.c @@ -50,22 +50,22 @@ static struct proto hvsock_proto = { #define SS_LISTEN 255 +#define HVSOCK_CONNECT_TIMEOUT (30 * HZ) + +/* This is an artificial limit */ +#define HVSOCK_MAX_BACKLOG 128 + static LIST_HEAD(hvsock_bound_list); static LIST_HEAD(hvsock_connected_list); static DEFINE_MUTEX(hvsock_mutex); -static bool uuid_equals(uuid_le u1, uuid_le u2) -{ - return !uuid_le_cmp(u1, u2); -} - static struct sock *hvsock_find_bound_socket(const struct sockaddr_hv *addr) { struct hvsock_sock *hvsk; list_for_each_entry(hvsk, &hvsock_bound_list, bound_list) { - if (uuid_equals(addr->shv_service_id, - hvsk->local_addr.shv_service_id)) + if (!uuid_le_cmp(addr->shv_service_guid, + hvsk->local_addr.shv_service_guid)) return hvsock_to_sk(hvsk); } return NULL; @@ -147,7 +147,7 @@ static void hvsock_addr_init(struct sockaddr_hv *addr, uuid_le service_id) { memset(addr, 0, sizeof(*addr)); addr->shv_family = AF_HYPERV; - addr->shv_service_id = service_id; + addr->shv_service_guid = service_id; } static int hvsock_addr_validate(const struct sockaddr_hv *addr) @@ -166,7 +166,7 @@ static int hvsock_addr_validate(const struct sockaddr_hv *addr) static bool hvsock_addr_bound(const struct sockaddr_hv *addr) { - return !uuid_equals(addr->shv_service_id, SHV_SERVICE_ID_ANY); + return !!uuid_le_cmp(addr->shv_service_guid, SHV_SERVICE_ID_ANY); } static int hvsock_addr_cast(const struct sockaddr *addr, size_t len, @@ -185,13 +185,13 @@ static int __hvsock_do_bind(struct hvsock_sock *hvsk, struct sockaddr_hv hv_addr; int ret = 0; - hvsock_addr_init(&hv_addr, addr->shv_service_id); + hvsock_addr_init(&hv_addr, addr->shv_service_guid); mutex_lock(&hvsock_mutex); - if (uuid_equals(addr->shv_service_id, SHV_SERVICE_ID_ANY)) { + if (!uuid_le_cmp(addr->shv_service_guid, SHV_SERVICE_ID_ANY)) { do { - uuid_le_gen(&hv_addr.shv_service_id); + uuid_le_gen(&hv_addr.shv_service_guid); } while (hvsock_find_bound_socket(&hv_addr)); } else { if (hvsock_find_bound_socket(&hv_addr)) { @@ -200,7 +200,7 @@ static int __hvsock_do_bind(struct hvsock_sock *hvsk, } } - hvsock_addr_init(&hvsk->local_addr, hv_addr.shv_service_id); + hvsock_addr_init(&hvsk->local_addr, hv_addr.shv_service_guid); sock_hold(&hvsk->sk); list_add(&hvsk->bound_list, &hvsock_bound_list); @@ -366,7 +366,7 @@ static int hvsock_bind(struct socket *sock, struct sockaddr *addr, if (hvsock_addr_cast(addr, addr_len, &hv_addr) != 0) return -EINVAL; - if (!uuid_equals(hv_addr->shv_vm_id, NULL_UUID_LE)) + if (uuid_le_cmp(hv_addr->shv_vm_guid, NULL_UUID_LE)) return -EINVAL; lock_sock(sk); @@ -609,7 +609,6 @@ static unsigned int hvsock_poll(struct file *file, struct socket *sock, if (!(sk->sk_shutdown & RCV_SHUTDOWN) && can_read) mask |= POLLIN | POLLRDNORM; } else { - can_read = false; can_write = false; } @@ -654,10 +653,7 @@ static void hvsock_on_channel_cb(void *ctx) hvsk = sk_to_hvsock(sk); channel = hvsk->channel; - if (!channel) { - WARN_ONCE(1, "NULL channel! There is a programming bug.\n"); - return; - } + BUG_ON(!channel); get_ringbuffer_rw_status(channel, &can_read, &can_write); @@ -720,7 +716,7 @@ static int hvsock_open_connection(struct vmbus_channel *channel) if (conn_from_host) { if (sk->sk_ack_backlog >= sk->sk_max_ack_backlog) { - ret = -EMFILE; + ret = -ECONNREFUSED; goto out; } @@ -811,7 +807,7 @@ static int hvsock_connect_wait(struct socket *sock, long timeout; hvsk = sk_to_hvsock(sk); - timeout = 30 * HZ; + timeout = HVSOCK_CONNECT_TIMEOUT; prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); while (sk->sk_state != SS_CONNECTED && sk->sk_err == 0) { @@ -905,8 +901,8 @@ static int hvsock_connect(struct socket *sock, struct sockaddr *addr, sk->sk_state = SS_CONNECTING; ret = vmbus_send_tl_connect_request( - &hvsk->local_addr.shv_service_id, - &hvsk->remote_addr.shv_service_id); + &hvsk->local_addr.shv_service_guid, + &hvsk->remote_addr.shv_service_guid); if (ret < 0) goto out; @@ -964,15 +960,12 @@ static int hvsock_accept_wait(struct sock *listener, lock_sock(connected); hvconnected = sk_to_hvsock(connected); - if (ret) { - release_sock(connected); - sock_put(connected); - } else { + if (!ret) { newsock->state = SS_CONNECTED; sock_graft(connected, newsock); - release_sock(connected); - sock_put(connected); } + release_sock(connected); + sock_put(connected); } out_wait: @@ -1029,9 +1022,8 @@ static int hvsock_listen(struct socket *sock, int backlog) ret = -EINVAL; goto out; } - /* This is an artificial limit */ - if (backlog > 128) - backlog = 128; + if (backlog > HVSOCK_MAX_BACKLOG) + backlog = HVSOCK_MAX_BACKLOG; hvsk = sk_to_hvsock(sk); if (!hvsock_addr_bound(&hvsk->local_addr)) { @@ -1057,7 +1049,7 @@ static int hvsock_sendmsg_wait(struct sock *sk, struct msghdr *msg, DEFINE_WAIT(wait); bool can_write; long timeout; - int ret = 0; + int ret; timeout = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); @@ -1162,11 +1154,8 @@ static int hvsock_sendmsg(struct socket *sock, struct msghdr *msg, if (len == 0) return -EINVAL; - if (msg->msg_flags & ~MSG_DONTWAIT) { - pr_err("%s: unsupported flags=0x%x\n", __func__, - msg->msg_flags); + if (msg->msg_flags & ~MSG_DONTWAIT) return -EOPNOTSUPP; - } sk = sock->sk; hvsk = sk_to_hvsock(sk); @@ -1201,11 +1190,10 @@ static int hvsock_sendmsg(struct socket *sock, struct msghdr *msg, out: release_sock(sk); - /* ret is a bigger-than-0 total_written or a negative err code. */ - if (ret == 0) { - WARN(1, "unexpected return value of 0\n"); - ret = -EIO; - } + /* ret should be a bigger-than-0 total_written or a negative err + * code. + */ + BUG_ON(ret == 0); return ret; } @@ -1358,7 +1346,6 @@ static int hvsock_recvmsg(struct socket *sock, struct msghdr *msg, /* We ignore msg->addr_name/len. */ if (flags & ~MSG_DONTWAIT) { - pr_err("%s: unsupported flags=0x%x\n", __func__, flags); ret = -EOPNOTSUPP; goto out; } @@ -1478,8 +1465,7 @@ static int __init hvsock_init(void) { int ret; - /* Hyper-V Sockets requires at least VMBus 4.0 */ - if ((vmbus_proto_version >> 16) < 4) + if (vmbus_proto_version < VERSION_WIN10) return -ENODEV; ret = vmbus_driver_register(&hvsock_drv);