Skip to content

Commit 503e6ad

Browse files
author
Herton R. Krzesinski
committed
Merge: vsock: backport latest commits for RHEL-9-2
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/1869 ## Summary of Changes Backport of vsock fixes, features (support for SO_RCVLOWAT) and tests (SO_RCVLOWAT) included in Linux v6.2-rc3 for RHEL 9.2. > git backport-diff -u upstream-local/master -r main..HEAD Key: [----] : patches are identical [####] : number of functional differences between upstream/downstream patch [down] : patch is downstream-only The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively 001/17:[----] [--] 'vsock: Fix memory leak in vsock_connect()' 002/17:[----] [--] 'vsock: Set socket state back to SS_UNCONNECTED in vsock_connect_timeout()' 003/17:[----] [--] 'vsock: SO_RCVLOWAT transport set callback' 004/17:[----] [--] 'hv_sock: disable SO_RCVLOWAT support' 005/17:[----] [--] 'virtio/vsock: use 'target' in notify_poll_in callback' 006/17:[----] [--] 'vmci/vsock: use 'target' in notify_poll_in callback' 007/17:[----] [--] 'vsock: pass sock_rcvlowat to notify_poll_in as target' 008/17:[----] [--] 'vsock: add API call for data ready' 009/17:[----] [--] 'virtio/vsock: check SO_RCVLOWAT before wake up reader' 010/17:[----] [--] 'vmci/vsock: check SO_RCVLOWAT before wake up reader' 011/17:[----] [--] 'vsock_test: POLLIN + SO_RCVLOWAT test' 012/17:[----] [--] 'vsock/vmci: fix repeated words in comments' 013/17:[----] [--] 'vhost/vsock: Use kvmalloc/kvfree for larger packets.' 014/17:[----] [--] 'vsock: remove the unused 'wait' in vsock_connectible_recvmsg()' 015/17:[----] [--] 'vsock: fix possible infinite sleep in vsock_connectible_wait_data()' 016/17:[----] [--] 'net: vmw_vsock: vmci: Check memcpy_from_msg()' 017/17:[----] [--] 'vhost/vsock: Fix error handling in vhost_vsock_init()' ## Approved Bugzilla Ticket Bugzilla: https://bugzilla.redhat.com/2160028 Signed-off-by: Stefano Garzarella <sgarzare@redhat.com> Approved-by: Vitaly Kuznetsov <vkuznets@redhat.com> Approved-by: Mohamed Gamal Morsy <mgamal@redhat.com> Signed-off-by: Herton R. Krzesinski <herton@redhat.com>
2 parents eb7c7e8 + fa5e555 commit 503e6ad

File tree

9 files changed

+191
-26
lines changed

9 files changed

+191
-26
lines changed

drivers/vhost/vsock.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ vhost_vsock_alloc_pkt(struct vhost_virtqueue *vq,
393393
return NULL;
394394
}
395395

396-
pkt->buf = kmalloc(pkt->len, GFP_KERNEL);
396+
pkt->buf = kvmalloc(pkt->len, GFP_KERNEL);
397397
if (!pkt->buf) {
398398
kfree(pkt);
399399
return NULL;
@@ -964,7 +964,14 @@ static int __init vhost_vsock_init(void)
964964
VSOCK_TRANSPORT_F_H2G);
965965
if (ret < 0)
966966
return ret;
967-
return misc_register(&vhost_vsock_misc);
967+
968+
ret = misc_register(&vhost_vsock_misc);
969+
if (ret) {
970+
vsock_core_unregister(&vhost_transport.transport);
971+
return ret;
972+
}
973+
974+
return 0;
968975
};
969976

970977
static void __exit vhost_vsock_exit(void)

include/net/af_vsock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ struct vsock_sock {
7777
s64 vsock_stream_has_data(struct vsock_sock *vsk);
7878
s64 vsock_stream_has_space(struct vsock_sock *vsk);
7979
struct sock *vsock_create_connected(struct sock *parent);
80+
void vsock_data_ready(struct sock *sk);
8081

8182
/**** TRANSPORT ****/
8283

@@ -134,6 +135,7 @@ struct vsock_transport {
134135
u64 (*stream_rcvhiwat)(struct vsock_sock *);
135136
bool (*stream_is_active)(struct vsock_sock *);
136137
bool (*stream_allow)(u32 cid, u32 port);
138+
int (*set_rcvlowat)(struct vsock_sock *vsk, int val);
137139

138140
/* SEQ_PACKET. */
139141
ssize_t (*seqpacket_dequeue)(struct vsock_sock *vsk, struct msghdr *msg,

net/vmw_vsock/af_vsock.c

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,16 @@ s64 vsock_stream_has_space(struct vsock_sock *vsk)
882882
}
883883
EXPORT_SYMBOL_GPL(vsock_stream_has_space);
884884

885+
void vsock_data_ready(struct sock *sk)
886+
{
887+
struct vsock_sock *vsk = vsock_sk(sk);
888+
889+
if (vsock_stream_has_data(vsk) >= sk->sk_rcvlowat ||
890+
sock_flag(sk, SOCK_DONE))
891+
sk->sk_data_ready(sk);
892+
}
893+
EXPORT_SYMBOL_GPL(vsock_data_ready);
894+
885895
static int vsock_release(struct socket *sock)
886896
{
887897
__vsock_release(sock->sk, 0);
@@ -1066,8 +1076,9 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
10661076
if (transport && transport->stream_is_active(vsk) &&
10671077
!(sk->sk_shutdown & RCV_SHUTDOWN)) {
10681078
bool data_ready_now = false;
1079+
int target = sock_rcvlowat(sk, 0, INT_MAX);
10691080
int ret = transport->notify_poll_in(
1070-
vsk, 1, &data_ready_now);
1081+
vsk, target, &data_ready_now);
10711082
if (ret < 0) {
10721083
mask |= EPOLLERR;
10731084
} else {
@@ -1286,6 +1297,7 @@ static void vsock_connect_timeout(struct work_struct *work)
12861297
if (sk->sk_state == TCP_SYN_SENT &&
12871298
(sk->sk_shutdown != SHUTDOWN_MASK)) {
12881299
sk->sk_state = TCP_CLOSE;
1300+
sk->sk_socket->state = SS_UNCONNECTED;
12891301
sk->sk_err = ETIMEDOUT;
12901302
sk_error_report(sk);
12911303
vsock_transport_cancel_pkt(vsk);
@@ -1391,7 +1403,14 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr,
13911403
* timeout fires.
13921404
*/
13931405
sock_hold(sk);
1394-
schedule_delayed_work(&vsk->connect_work, timeout);
1406+
1407+
/* If the timeout function is already scheduled,
1408+
* reschedule it, then ungrab the socket refcount to
1409+
* keep it balanced.
1410+
*/
1411+
if (mod_delayed_work(system_wq, &vsk->connect_work,
1412+
timeout))
1413+
sock_put(sk);
13951414

13961415
/* Skip ahead to preserve error code set above. */
13971416
goto out_wait;
@@ -1886,8 +1905,11 @@ static int vsock_connectible_wait_data(struct sock *sk,
18861905
err = 0;
18871906
transport = vsk->transport;
18881907

1889-
while ((data = vsock_connectible_has_data(vsk)) == 0) {
1908+
while (1) {
18901909
prepare_to_wait(sk_sleep(sk), wait, TASK_INTERRUPTIBLE);
1910+
data = vsock_connectible_has_data(vsk);
1911+
if (data != 0)
1912+
break;
18911913

18921914
if (sk->sk_err != 0 ||
18931915
(sk->sk_shutdown & RCV_SHUTDOWN) ||
@@ -2073,8 +2095,6 @@ vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
20732095
const struct vsock_transport *transport;
20742096
int err;
20752097

2076-
DEFINE_WAIT(wait);
2077-
20782098
sk = sock->sk;
20792099
vsk = vsock_sk(sk);
20802100
err = 0;
@@ -2129,6 +2149,25 @@ vsock_connectible_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
21292149
return err;
21302150
}
21312151

2152+
static int vsock_set_rcvlowat(struct sock *sk, int val)
2153+
{
2154+
const struct vsock_transport *transport;
2155+
struct vsock_sock *vsk;
2156+
2157+
vsk = vsock_sk(sk);
2158+
2159+
if (val > vsk->buffer_size)
2160+
return -EINVAL;
2161+
2162+
transport = vsk->transport;
2163+
2164+
if (transport && transport->set_rcvlowat)
2165+
return transport->set_rcvlowat(vsk, val);
2166+
2167+
WRITE_ONCE(sk->sk_rcvlowat, val ? : 1);
2168+
return 0;
2169+
}
2170+
21322171
static const struct proto_ops vsock_stream_ops = {
21332172
.family = PF_VSOCK,
21342173
.owner = THIS_MODULE,
@@ -2148,6 +2187,7 @@ static const struct proto_ops vsock_stream_ops = {
21482187
.recvmsg = vsock_connectible_recvmsg,
21492188
.mmap = sock_no_mmap,
21502189
.sendpage = sock_no_sendpage,
2190+
.set_rcvlowat = vsock_set_rcvlowat,
21512191
};
21522192

21532193
static const struct proto_ops vsock_seqpacket_ops = {

net/vmw_vsock/hyperv_transport.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,12 @@ int hvs_notify_send_post_enqueue(struct vsock_sock *vsk, ssize_t written,
809809
return 0;
810810
}
811811

812+
static
813+
int hvs_set_rcvlowat(struct vsock_sock *vsk, int val)
814+
{
815+
return -EOPNOTSUPP;
816+
}
817+
812818
static struct vsock_transport hvs_transport = {
813819
.module = THIS_MODULE,
814820

@@ -844,6 +850,7 @@ static struct vsock_transport hvs_transport = {
844850
.notify_send_pre_enqueue = hvs_notify_send_pre_enqueue,
845851
.notify_send_post_enqueue = hvs_notify_send_post_enqueue,
846852

853+
.set_rcvlowat = hvs_set_rcvlowat
847854
};
848855

849856
static bool hvs_check_transport(struct vsock_sock *vsk)

net/vmw_vsock/virtio_transport_common.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -634,10 +634,7 @@ virtio_transport_notify_poll_in(struct vsock_sock *vsk,
634634
size_t target,
635635
bool *data_ready_now)
636636
{
637-
if (vsock_stream_has_data(vsk))
638-
*data_ready_now = true;
639-
else
640-
*data_ready_now = false;
637+
*data_ready_now = vsock_stream_has_data(vsk) >= target;
641638

642639
return 0;
643640
}
@@ -1084,7 +1081,7 @@ virtio_transport_recv_connected(struct sock *sk,
10841081
switch (le16_to_cpu(pkt->hdr.op)) {
10851082
case VIRTIO_VSOCK_OP_RW:
10861083
virtio_transport_recv_enqueue(vsk, pkt);
1087-
sk->sk_data_ready(sk);
1084+
vsock_data_ready(sk);
10881085
return err;
10891086
case VIRTIO_VSOCK_OP_CREDIT_REQUEST:
10901087
virtio_transport_send_credit_update(vsk);
@@ -1342,7 +1339,7 @@ EXPORT_SYMBOL_GPL(virtio_transport_recv_pkt);
13421339

13431340
void virtio_transport_free_pkt(struct virtio_vsock_pkt *pkt)
13441341
{
1345-
kfree(pkt->buf);
1342+
kvfree(pkt->buf);
13461343
kfree(pkt);
13471344
}
13481345
EXPORT_SYMBOL_GPL(virtio_transport_free_pkt);

net/vmw_vsock/vmci_transport.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -951,7 +951,7 @@ static int vmci_transport_recv_listen(struct sock *sk,
951951
* for ourself or any previous connection requests that we received.
952952
* If it's the latter, we try to find a socket in our list of pending
953953
* connections and, if we do, call the appropriate handler for the
954-
* state that that socket is in. Otherwise we try to service the
954+
* state that socket is in. Otherwise we try to service the
955955
* connection request.
956956
*/
957957
pending = vmci_transport_get_pending(sk, pkt);
@@ -1711,7 +1711,11 @@ static int vmci_transport_dgram_enqueue(
17111711
if (!dg)
17121712
return -ENOMEM;
17131713

1714-
memcpy_from_msg(VMCI_DG_PAYLOAD(dg), msg, len);
1714+
err = memcpy_from_msg(VMCI_DG_PAYLOAD(dg), msg, len);
1715+
if (err) {
1716+
kfree(dg);
1717+
return err;
1718+
}
17151719

17161720
dg->dst = vmci_make_handle(remote_addr->svm_cid,
17171721
remote_addr->svm_port);

net/vmw_vsock/vmci_transport_notify.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ vmci_transport_handle_wrote(struct sock *sk,
307307
struct vsock_sock *vsk = vsock_sk(sk);
308308
PKT_FIELD(vsk, sent_waiting_read) = false;
309309
#endif
310-
sk->sk_data_ready(sk);
310+
vsock_data_ready(sk);
311311
}
312312

313313
static void vmci_transport_notify_pkt_socket_init(struct sock *sk)
@@ -340,12 +340,12 @@ vmci_transport_notify_pkt_poll_in(struct sock *sk,
340340
{
341341
struct vsock_sock *vsk = vsock_sk(sk);
342342

343-
if (vsock_stream_has_data(vsk)) {
343+
if (vsock_stream_has_data(vsk) >= target) {
344344
*data_ready_now = true;
345345
} else {
346-
/* We can't read right now because there is nothing in the
347-
* queue. Ask for notifications when there is something to
348-
* read.
346+
/* We can't read right now because there is not enough data
347+
* in the queue. Ask for notifications when there is something
348+
* to read.
349349
*/
350350
if (sk->sk_state == TCP_ESTABLISHED) {
351351
if (!send_waiting_read(sk, 1))

net/vmw_vsock/vmci_transport_notify_qstate.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ vmci_transport_handle_wrote(struct sock *sk,
8484
bool bottom_half,
8585
struct sockaddr_vm *dst, struct sockaddr_vm *src)
8686
{
87-
sk->sk_data_ready(sk);
87+
vsock_data_ready(sk);
8888
}
8989

9090
static void vsock_block_update_write_window(struct sock *sk)
@@ -161,12 +161,12 @@ vmci_transport_notify_pkt_poll_in(struct sock *sk,
161161
{
162162
struct vsock_sock *vsk = vsock_sk(sk);
163163

164-
if (vsock_stream_has_data(vsk)) {
164+
if (vsock_stream_has_data(vsk) >= target) {
165165
*data_ready_now = true;
166166
} else {
167-
/* We can't read right now because there is nothing in the
168-
* queue. Ask for notifications when there is something to
169-
* read.
167+
/* We can't read right now because there is not enough data
168+
* in the queue. Ask for notifications when there is something
169+
* to read.
170170
*/
171171
if (sk->sk_state == TCP_ESTABLISHED)
172172
vsock_block_update_write_window(sk);
@@ -282,7 +282,7 @@ vmci_transport_notify_pkt_recv_post_dequeue(
282282
/* See the comment in
283283
* vmci_transport_notify_pkt_send_post_enqueue().
284284
*/
285-
sk->sk_data_ready(sk);
285+
vsock_data_ready(sk);
286286
}
287287

288288
return err;

0 commit comments

Comments
 (0)