android_kernel_samsung_sm8650/net/vmw_vsock/vsock_loopback.c
Greg Kroah-Hartman 55d4929d66 Revert "virtio/vsock: replace virtio_vsock_pkt with sk_buff"
This reverts commit baddcc2c71 which is
commit 71dc9ec9ac7d3eee785cdc986c3daeb821381e20 upstream.

It needs to be reverted, as the function virtio_transport_free_pkt() is
in the stable Android ABI, and this function is removed in the 6.1.63
kernel as part of a series of fixes and optimizations of the virtio
networking connection.  To preserve the ABI (and thereby keeping the
slower interface), revert the commit for now.

If this needs to come back in the future, if performance for this
interface needs to be resolved, it can be done so in an ABI-safe way.

Bug: 161946584
Change-Id: Id589087dead45cb846fd9a735a0daece04b8e252
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
2023-11-29 13:06:15 +00:00

193 lines
5.7 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/* loopback transport for vsock using virtio_transport_common APIs
*
* Copyright (C) 2013-2019 Red Hat, Inc.
* Authors: Asias He <asias@redhat.com>
* Stefan Hajnoczi <stefanha@redhat.com>
* Stefano Garzarella <sgarzare@redhat.com>
*
*/
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/virtio_vsock.h>
struct vsock_loopback {
struct workqueue_struct *workqueue;
spinlock_t pkt_list_lock; /* protects pkt_list */
struct list_head pkt_list;
struct work_struct pkt_work;
};
static struct vsock_loopback the_vsock_loopback;
static u32 vsock_loopback_get_local_cid(void)
{
return VMADDR_CID_LOCAL;
}
static int vsock_loopback_send_pkt(struct virtio_vsock_pkt *pkt)
{
struct vsock_loopback *vsock = &the_vsock_loopback;
int len = pkt->len;
spin_lock_bh(&vsock->pkt_list_lock);
list_add_tail(&pkt->list, &vsock->pkt_list);
spin_unlock_bh(&vsock->pkt_list_lock);
queue_work(vsock->workqueue, &vsock->pkt_work);
return len;
}
static int vsock_loopback_cancel_pkt(struct vsock_sock *vsk)
{
struct vsock_loopback *vsock = &the_vsock_loopback;
struct virtio_vsock_pkt *pkt, *n;
LIST_HEAD(freeme);
spin_lock_bh(&vsock->pkt_list_lock);
list_for_each_entry_safe(pkt, n, &vsock->pkt_list, list) {
if (pkt->vsk != vsk)
continue;
list_move(&pkt->list, &freeme);
}
spin_unlock_bh(&vsock->pkt_list_lock);
list_for_each_entry_safe(pkt, n, &freeme, list) {
list_del(&pkt->list);
virtio_transport_free_pkt(pkt);
}
return 0;
}
static bool vsock_loopback_seqpacket_allow(u32 remote_cid);
static struct virtio_transport loopback_transport = {
.transport = {
.module = THIS_MODULE,
.get_local_cid = vsock_loopback_get_local_cid,
.init = virtio_transport_do_socket_init,
.destruct = virtio_transport_destruct,
.release = virtio_transport_release,
.connect = virtio_transport_connect,
.shutdown = virtio_transport_shutdown,
.cancel_pkt = vsock_loopback_cancel_pkt,
.dgram_bind = virtio_transport_dgram_bind,
.dgram_dequeue = virtio_transport_dgram_dequeue,
.dgram_enqueue = virtio_transport_dgram_enqueue,
.dgram_allow = virtio_transport_dgram_allow,
.stream_dequeue = virtio_transport_stream_dequeue,
.stream_enqueue = virtio_transport_stream_enqueue,
.stream_has_data = virtio_transport_stream_has_data,
.stream_has_space = virtio_transport_stream_has_space,
.stream_rcvhiwat = virtio_transport_stream_rcvhiwat,
.stream_is_active = virtio_transport_stream_is_active,
.stream_allow = virtio_transport_stream_allow,
.seqpacket_dequeue = virtio_transport_seqpacket_dequeue,
.seqpacket_enqueue = virtio_transport_seqpacket_enqueue,
.seqpacket_allow = vsock_loopback_seqpacket_allow,
.seqpacket_has_data = virtio_transport_seqpacket_has_data,
.notify_poll_in = virtio_transport_notify_poll_in,
.notify_poll_out = virtio_transport_notify_poll_out,
.notify_recv_init = virtio_transport_notify_recv_init,
.notify_recv_pre_block = virtio_transport_notify_recv_pre_block,
.notify_recv_pre_dequeue = virtio_transport_notify_recv_pre_dequeue,
.notify_recv_post_dequeue = virtio_transport_notify_recv_post_dequeue,
.notify_send_init = virtio_transport_notify_send_init,
.notify_send_pre_block = virtio_transport_notify_send_pre_block,
.notify_send_pre_enqueue = virtio_transport_notify_send_pre_enqueue,
.notify_send_post_enqueue = virtio_transport_notify_send_post_enqueue,
.notify_buffer_size = virtio_transport_notify_buffer_size,
},
.send_pkt = vsock_loopback_send_pkt,
};
static bool vsock_loopback_seqpacket_allow(u32 remote_cid)
{
return true;
}
static void vsock_loopback_work(struct work_struct *work)
{
struct vsock_loopback *vsock =
container_of(work, struct vsock_loopback, pkt_work);
LIST_HEAD(pkts);
spin_lock_bh(&vsock->pkt_list_lock);
list_splice_init(&vsock->pkt_list, &pkts);
spin_unlock_bh(&vsock->pkt_list_lock);
while (!list_empty(&pkts)) {
struct virtio_vsock_pkt *pkt;
pkt = list_first_entry(&pkts, struct virtio_vsock_pkt, list);
list_del_init(&pkt->list);
virtio_transport_deliver_tap_pkt(pkt);
virtio_transport_recv_pkt(&loopback_transport, pkt);
}
}
static int __init vsock_loopback_init(void)
{
struct vsock_loopback *vsock = &the_vsock_loopback;
int ret;
vsock->workqueue = alloc_workqueue("vsock-loopback", 0, 0);
if (!vsock->workqueue)
return -ENOMEM;
spin_lock_init(&vsock->pkt_list_lock);
INIT_LIST_HEAD(&vsock->pkt_list);
INIT_WORK(&vsock->pkt_work, vsock_loopback_work);
ret = vsock_core_register(&loopback_transport.transport,
VSOCK_TRANSPORT_F_LOCAL);
if (ret)
goto out_wq;
return 0;
out_wq:
destroy_workqueue(vsock->workqueue);
return ret;
}
static void __exit vsock_loopback_exit(void)
{
struct vsock_loopback *vsock = &the_vsock_loopback;
struct virtio_vsock_pkt *pkt;
vsock_core_unregister(&loopback_transport.transport);
flush_work(&vsock->pkt_work);
spin_lock_bh(&vsock->pkt_list_lock);
while (!list_empty(&vsock->pkt_list)) {
pkt = list_first_entry(&vsock->pkt_list,
struct virtio_vsock_pkt, list);
list_del(&pkt->list);
virtio_transport_free_pkt(pkt);
}
spin_unlock_bh(&vsock->pkt_list_lock);
destroy_workqueue(vsock->workqueue);
}
module_init(vsock_loopback_init);
module_exit(vsock_loopback_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Stefano Garzarella <sgarzare@redhat.com>");
MODULE_DESCRIPTION("loopback transport for vsock");
MODULE_ALIAS_NETPROTO(PF_VSOCK);