cregit-Linux how code gets into the kernel

Release 4.8 net/vmw_vsock/virtio_transport_common.c

Directory: net/vmw_vsock
/*
 * common code for virtio vsock
 *
 * Copyright (C) 2013-2015 Red Hat, Inc.
 * Author: Asias He <asias@redhat.com>
 *         Stefan Hajnoczi <stefanha@redhat.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.
 */
#include <linux/spinlock.h>
#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/list.h>
#include <linux/virtio.h>
#include <linux/virtio_ids.h>
#include <linux/virtio_config.h>
#include <linux/virtio_vsock.h>

#include <net/sock.h>
#include <net/af_vsock.h>


#define CREATE_TRACE_POINTS
#include <trace/events/vsock_virtio_transport_common.h>

/* How long to wait for graceful shutdown of a connection */

#define VSOCK_CLOSE_TIMEOUT (8 * HZ)


static const struct virtio_transport *virtio_transport_get_ops(void) { const struct vsock_transport *t = vsock_core_get_transport(); return container_of(t, struct virtio_transport, transport); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he31100.00%1100.00%
Total31100.00%1100.00%


struct virtio_vsock_pkt * virtio_transport_alloc_pkt(struct virtio_vsock_pkt_info *info, size_t len, u32 src_cid, u32 src_port, u32 dst_cid, u32 dst_port) { struct virtio_vsock_pkt *pkt; int err; pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); if (!pkt) return NULL; pkt->hdr.type = cpu_to_le16(info->type); pkt->hdr.op = cpu_to_le16(info->op); pkt->hdr.src_cid = cpu_to_le64(src_cid); pkt->hdr.dst_cid = cpu_to_le64(dst_cid); pkt->hdr.src_port = cpu_to_le32(src_port); pkt->hdr.dst_port = cpu_to_le32(dst_port); pkt->hdr.flags = cpu_to_le32(info->flags); pkt->len = len; pkt->hdr.len = cpu_to_le32(len); pkt->reply = info->reply; if (info->msg && len > 0) { pkt->buf = kmalloc(len, GFP_KERNEL); if (!pkt->buf) goto out_pkt; err = memcpy_from_msg(pkt->buf, info->msg, len); if (err) goto out; } trace_virtio_transport_alloc_pkt(src_cid, src_port, dst_cid, dst_port, len, info->type, info->op, info->flags); return pkt; out: kfree(pkt->buf); out_pkt: kfree(pkt); return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he266100.00%1100.00%
Total266100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_alloc_pkt);
static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, struct virtio_vsock_pkt_info *info) { u32 src_cid, src_port, dst_cid, dst_port; struct virtio_vsock_sock *vvs; struct virtio_vsock_pkt *pkt; u32 pkt_len = info->pkt_len; src_cid = vm_sockets_get_local_cid(); src_port = vsk->local_addr.svm_port; if (!info->remote_cid) { dst_cid = vsk->remote_addr.svm_cid; dst_port = vsk->remote_addr.svm_port; } else { dst_cid = info->remote_cid; dst_port = info->remote_port; } vvs = vsk->trans; /* we can send less than pkt_len bytes */ if (pkt_len > VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE) pkt_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE; /* virtio_transport_get_credit might return less than pkt_len credit */ pkt_len = virtio_transport_get_credit(vvs, pkt_len); /* Do not send zero length OP_RW pkt */ if (pkt_len == 0 && info->op == VIRTIO_VSOCK_OP_RW) return pkt_len; pkt = virtio_transport_alloc_pkt(info, pkt_len, src_cid, src_port, dst_cid, dst_port); if (!pkt) { virtio_transport_put_credit(vvs, pkt_len); return -ENOMEM; } virtio_transport_inc_tx_pkt(vvs, pkt); return virtio_transport_get_ops()->send_pkt(pkt); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he189100.00%1100.00%
Total189100.00%1100.00%


static void virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs, struct virtio_vsock_pkt *pkt) { vvs->rx_bytes += pkt->len; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he24100.00%1100.00%
Total24100.00%1100.00%


static void virtio_transport_dec_rx_pkt(struct virtio_vsock_sock *vvs, struct virtio_vsock_pkt *pkt) { vvs->rx_bytes -= pkt->len; vvs->fwd_cnt += pkt->len; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he32100.00%1100.00%
Total32100.00%1100.00%


void virtio_transport_inc_tx_pkt(struct virtio_vsock_sock *vvs, struct virtio_vsock_pkt *pkt) { spin_lock_bh(&vvs->tx_lock); pkt->hdr.fwd_cnt = cpu_to_le32(vvs->fwd_cnt); pkt->hdr.buf_alloc = cpu_to_le32(vvs->buf_alloc); spin_unlock_bh(&vvs->tx_lock); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he57100.00%1100.00%
Total57100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_inc_tx_pkt);
u32 virtio_transport_get_credit(struct virtio_vsock_sock *vvs, u32 credit) { u32 ret; spin_lock_bh(&vvs->tx_lock); ret = vvs->peer_buf_alloc - (vvs->tx_cnt - vvs->peer_fwd_cnt); if (ret > credit) ret = credit; vvs->tx_cnt += ret; spin_unlock_bh(&vvs->tx_lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he67100.00%1100.00%
Total67100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_get_credit);
void virtio_transport_put_credit(struct virtio_vsock_sock *vvs, u32 credit) { spin_lock_bh(&vvs->tx_lock); vvs->tx_cnt -= credit; spin_unlock_bh(&vvs->tx_lock); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he35100.00%1100.00%
Total35100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_put_credit);
static int virtio_transport_send_credit_update(struct vsock_sock *vsk, int type, struct virtio_vsock_hdr *hdr) { struct virtio_vsock_pkt_info info = { .op = VIRTIO_VSOCK_OP_CREDIT_UPDATE, .type = type, }; return virtio_transport_send_pkt_info(vsk, &info); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he44100.00%1100.00%
Total44100.00%1100.00%


static ssize_t virtio_transport_stream_do_dequeue(struct vsock_sock *vsk, struct msghdr *msg, size_t len) { struct virtio_vsock_sock *vvs = vsk->trans; struct virtio_vsock_pkt *pkt; size_t bytes, total = 0; int err = -EFAULT; spin_lock_bh(&vvs->rx_lock); while (total < len && !list_empty(&vvs->rx_queue)) { pkt = list_first_entry(&vvs->rx_queue, struct virtio_vsock_pkt, list); bytes = len - total; if (bytes > pkt->len - pkt->off) bytes = pkt->len - pkt->off; /* sk_lock is held by caller so no one else can dequeue. * Unlock rx_lock since memcpy_to_msg() may sleep. */ spin_unlock_bh(&vvs->rx_lock); err = memcpy_to_msg(msg, pkt->buf + pkt->off, bytes); if (err) goto out; spin_lock_bh(&vvs->rx_lock); total += bytes; pkt->off += bytes; if (pkt->off == pkt->len) { virtio_transport_dec_rx_pkt(vvs, pkt); list_del(&pkt->list); virtio_transport_free_pkt(pkt); } } spin_unlock_bh(&vvs->rx_lock); /* Send a credit pkt to peer */ virtio_transport_send_credit_update(vsk, VIRTIO_VSOCK_TYPE_STREAM, NULL); return total; out: if (total) err = total; return err; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he231100.00%1100.00%
Total231100.00%1100.00%


ssize_t virtio_transport_stream_dequeue(struct vsock_sock *vsk, struct msghdr *msg, size_t len, int flags) { if (flags & MSG_PEEK) return -EOPNOTSUPP; return virtio_transport_stream_do_dequeue(vsk, msg, len); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he41100.00%1100.00%
Total41100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_stream_dequeue);
int virtio_transport_dgram_dequeue(struct vsock_sock *vsk, struct msghdr *msg, size_t len, int flags) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he25100.00%1100.00%
Total25100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_dgram_dequeue);
s64 virtio_transport_stream_has_data(struct vsock_sock *vsk) { struct virtio_vsock_sock *vvs = vsk->trans; s64 bytes; spin_lock_bh(&vvs->rx_lock); bytes = vvs->rx_bytes; spin_unlock_bh(&vvs->rx_lock); return bytes; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he47100.00%1100.00%
Total47100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_stream_has_data);
static s64 virtio_transport_has_space(struct vsock_sock *vsk) { struct virtio_vsock_sock *vvs = vsk->trans; s64 bytes; bytes = vvs->peer_buf_alloc - (vvs->tx_cnt - vvs->peer_fwd_cnt); if (bytes < 0) bytes = 0; return bytes; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he52100.00%1100.00%
Total52100.00%1100.00%


s64 virtio_transport_stream_has_space(struct vsock_sock *vsk) { struct virtio_vsock_sock *vvs = vsk->trans; s64 bytes; spin_lock_bh(&vvs->tx_lock); bytes = virtio_transport_has_space(vsk); spin_unlock_bh(&vvs->tx_lock); return bytes; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he48100.00%1100.00%
Total48100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_stream_has_space);
int virtio_transport_do_socket_init(struct vsock_sock *vsk, struct vsock_sock *psk) { struct virtio_vsock_sock *vvs; vvs = kzalloc(sizeof(*vvs), GFP_KERNEL); if (!vvs) return -ENOMEM; vsk->trans = vvs; vvs->vsk = vsk; if (psk) { struct virtio_vsock_sock *ptrans = psk->trans; vvs->buf_size = ptrans->buf_size; vvs->buf_size_min = ptrans->buf_size_min; vvs->buf_size_max = ptrans->buf_size_max; vvs->peer_buf_alloc = ptrans->peer_buf_alloc; } else { vvs->buf_size = VIRTIO_VSOCK_DEFAULT_BUF_SIZE; vvs->buf_size_min = VIRTIO_VSOCK_DEFAULT_MIN_BUF_SIZE; vvs->buf_size_max = VIRTIO_VSOCK_DEFAULT_MAX_BUF_SIZE; } vvs->buf_alloc = vvs->buf_size; spin_lock_init(&vvs->rx_lock); spin_lock_init(&vvs->tx_lock); INIT_LIST_HEAD(&vvs->rx_queue); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he157100.00%1100.00%
Total157100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_do_socket_init);
u64 virtio_transport_get_buffer_size(struct vsock_sock *vsk) { struct virtio_vsock_sock *vvs = vsk->trans; return vvs->buf_size; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he24100.00%1100.00%
Total24100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_get_buffer_size);
u64 virtio_transport_get_min_buffer_size(struct vsock_sock *vsk) { struct virtio_vsock_sock *vvs = vsk->trans; return vvs->buf_size_min; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he24100.00%1100.00%
Total24100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_get_min_buffer_size);
u64 virtio_transport_get_max_buffer_size(struct vsock_sock *vsk) { struct virtio_vsock_sock *vvs = vsk->trans; return vvs->buf_size_max; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he24100.00%1100.00%
Total24100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_get_max_buffer_size);
void virtio_transport_set_buffer_size(struct vsock_sock *vsk, u64 val) { struct virtio_vsock_sock *vvs = vsk->trans; if (val > VIRTIO_VSOCK_MAX_BUF_SIZE) val = VIRTIO_VSOCK_MAX_BUF_SIZE; if (val < vvs->buf_size_min) vvs->buf_size_min = val; if (val > vvs->buf_size_max) vvs->buf_size_max = val; vvs->buf_size = val; vvs->buf_alloc = val; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he72100.00%1100.00%
Total72100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_set_buffer_size);
void virtio_transport_set_min_buffer_size(struct vsock_sock *vsk, u64 val) { struct virtio_vsock_sock *vvs = vsk->trans; if (val > VIRTIO_VSOCK_MAX_BUF_SIZE) val = VIRTIO_VSOCK_MAX_BUF_SIZE; if (val > vvs->buf_size) vvs->buf_size = val; vvs->buf_size_min = val; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he52100.00%1100.00%
Total52100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_set_min_buffer_size);
void virtio_transport_set_max_buffer_size(struct vsock_sock *vsk, u64 val) { struct virtio_vsock_sock *vvs = vsk->trans; if (val > VIRTIO_VSOCK_MAX_BUF_SIZE) val = VIRTIO_VSOCK_MAX_BUF_SIZE; if (val < vvs->buf_size) vvs->buf_size = val; vvs->buf_size_max = val; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he52100.00%1100.00%
Total52100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_set_max_buffer_size);
int virtio_transport_notify_poll_in(struct vsock_sock *vsk, size_t target, bool *data_ready_now) { if (vsock_stream_has_data(vsk)) *data_ready_now = true; else *data_ready_now = false; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he38100.00%1100.00%
Total38100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_notify_poll_in);
int virtio_transport_notify_poll_out(struct vsock_sock *vsk, size_t target, bool *space_avail_now) { s64 free_space; free_space = vsock_stream_has_space(vsk); if (free_space > 0) *space_avail_now = true; else if (free_space == 0) *space_avail_now = false; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he53100.00%1100.00%
Total53100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_notify_poll_out);
int virtio_transport_notify_recv_init(struct vsock_sock *vsk, size_t target, struct vsock_transport_recv_notify_data *data) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he21100.00%1100.00%
Total21100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_notify_recv_init);
int virtio_transport_notify_recv_pre_block(struct vsock_sock *vsk, size_t target, struct vsock_transport_recv_notify_data *data) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he21100.00%1100.00%
Total21100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_notify_recv_pre_block);
int virtio_transport_notify_recv_pre_dequeue(struct vsock_sock *vsk, size_t target, struct vsock_transport_recv_notify_data *data) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he21100.00%1100.00%
Total21100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_notify_recv_pre_dequeue);
int virtio_transport_notify_recv_post_dequeue(struct vsock_sock *vsk, size_t target, ssize_t copied, bool data_read, struct vsock_transport_recv_notify_data *data) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he27100.00%1100.00%
Total27100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_notify_recv_post_dequeue);
int virtio_transport_notify_send_init(struct vsock_sock *vsk, struct vsock_transport_send_notify_data *data) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he18100.00%1100.00%
Total18100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_notify_send_init);
int virtio_transport_notify_send_pre_block(struct vsock_sock *vsk, struct vsock_transport_send_notify_data *data) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he18100.00%1100.00%
Total18100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_notify_send_pre_block);
int virtio_transport_notify_send_pre_enqueue(struct vsock_sock *vsk, struct vsock_transport_send_notify_data *data) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he18100.00%1100.00%
Total18100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_notify_send_pre_enqueue);
int virtio_transport_notify_send_post_enqueue(struct vsock_sock *vsk, ssize_t written, struct vsock_transport_send_notify_data *data) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he21100.00%1100.00%
Total21100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_notify_send_post_enqueue);
u64 virtio_transport_stream_rcvhiwat(struct vsock_sock *vsk) { struct virtio_vsock_sock *vvs = vsk->trans; return vvs->buf_size; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he24100.00%1100.00%
Total24100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_stream_rcvhiwat);
bool virtio_transport_stream_is_active(struct vsock_sock *vsk) { return true; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he13100.00%1100.00%
Total13100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_stream_is_active);
bool virtio_transport_stream_allow(u32 cid, u32 port) { return true; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he14100.00%1100.00%
Total14100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_stream_allow);
int virtio_transport_dgram_bind(struct vsock_sock *vsk, struct sockaddr_vm *addr) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he19100.00%1100.00%
Total19100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_dgram_bind);
bool virtio_transport_dgram_allow(u32 cid, u32 port) { return false; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he14100.00%1100.00%
Total14100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_dgram_allow);
int virtio_transport_connect(struct vsock_sock *vsk) { struct virtio_vsock_pkt_info info = { .op = VIRTIO_VSOCK_OP_REQUEST, .type = VIRTIO_VSOCK_TYPE_STREAM, }; return virtio_transport_send_pkt_info(vsk, &info); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he35100.00%1100.00%
Total35100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_connect);
int virtio_transport_shutdown(struct vsock_sock *vsk, int mode) { struct virtio_vsock_pkt_info info = { .op = VIRTIO_VSOCK_OP_SHUTDOWN, .type = VIRTIO_VSOCK_TYPE_STREAM, .flags = (mode & RCV_SHUTDOWN ? VIRTIO_VSOCK_SHUTDOWN_RCV : 0) | (mode & SEND_SHUTDOWN ? VIRTIO_VSOCK_SHUTDOWN_SEND : 0), }; return virtio_transport_send_pkt_info(vsk, &info); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he61100.00%1100.00%
Total61100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_shutdown);
int virtio_transport_dgram_enqueue(struct vsock_sock *vsk, struct sockaddr_vm *remote_addr, struct msghdr *msg, size_t dgram_len) { return -EOPNOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he27100.00%1100.00%
Total27100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_dgram_enqueue);
ssize_t virtio_transport_stream_enqueue(struct vsock_sock *vsk, struct msghdr *msg, size_t len) { struct virtio_vsock_pkt_info info = { .op = VIRTIO_VSOCK_OP_RW, .type = VIRTIO_VSOCK_TYPE_STREAM, .msg = msg, .pkt_len = len, }; return virtio_transport_send_pkt_info(vsk, &info); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he53100.00%1100.00%
Total53100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_stream_enqueue);
void virtio_transport_destruct(struct vsock_sock *vsk) { struct virtio_vsock_sock *vvs = vsk->trans; kfree(vvs); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he24100.00%1100.00%
Total24100.00%1100.00%

EXPORT_SYMBOL_GPL(virtio_transport_destruct);
static int virtio_transport_reset(struct vsock_sock *vsk, struct virtio_vsock_pkt *pkt) { struct virtio_vsock_pkt_info info = { .op = VIRTIO_VSOCK_OP_RST, .type = VIRTIO_VSOCK_TYPE_STREAM, .reply = !!pkt, }; /* Send RST only if the original pkt is not a RST pkt */ if (pkt && le16_to_cpu(pkt->hdr.op) == VIRTIO_VSOCK_OP_RST) return 0; return virtio_transport_send_pkt_info(vsk, &info); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he67100.00%1100.00%
Total67100.00%1100.00%

/* Normally packets are associated with a socket. There may be no socket if an * attempt was made to connect to a socket that does not exist. */
static int virtio_transport_reset_no_sock(struct virtio_vsock_pkt *pkt) { struct virtio_vsock_pkt_info info = { .op = VIRTIO_VSOCK_OP_RST, .type = le16_to_cpu(pkt->hdr.type), .reply = true, }; /* Send RST only if the original pkt is not a RST pkt */ if (le16_to_cpu(pkt->hdr.op) == VIRTIO_VSOCK_OP_RST) return 0; pkt = virtio_transport_alloc_pkt(&info, 0, le32_to_cpu(pkt->hdr.dst_cid), le32_to_cpu(pkt->hdr.dst_port), le32_to_cpu(pkt->hdr.src_cid), le32_to_cpu(pkt->hdr.src_port)); if (!pkt) return -ENOMEM; return virtio_transport_get_ops()->send_pkt(pkt); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he120100.00%1100.00%
Total120100.00%1100.00%


static void virtio_transport_wait_close(struct sock *sk, long timeout) { if (timeout) { DEFINE_WAIT(wait); do { prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); if (sk_wait_event(sk, &timeout, sock_flag(sk, SOCK_DONE))) break; } while (!signal_pending(current) && timeout); finish_wait(sk_sleep(sk), &wait); } }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he81100.00%1100.00%
Total81100.00%1100.00%


static void virtio_transport_do_close(struct vsock_sock *vsk, bool cancel_timeout) { struct sock *sk = sk_vsock(vsk); sock_set_flag(sk, SOCK_DONE); vsk->peer_shutdown = SHUTDOWN_MASK; if (vsock_stream_has_data(vsk) <= 0) sk->sk_state = SS_DISCONNECTING; sk->sk_state_change(sk); if (vsk->close_work_scheduled && (!cancel_timeout || cancel_delayed_work(&vsk->close_work))) { vsk->close_work_scheduled = false; vsock_remove_sock(vsk); /* Release refcnt obtained when we scheduled the timeout */ sock_put(sk); } }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he97100.00%1100.00%
Total97100.00%1100.00%


static void virtio_transport_close_timeout(struct work_struct *work) { struct vsock_sock *vsk = container_of(work, struct vsock_sock, close_work.work); struct sock *sk = sk_vsock(vsk); sock_hold(sk); lock_sock(sk); if (!sock_flag(sk, SOCK_DONE)) { (void)virtio_transport_reset(vsk, NULL); virtio_transport_do_close(vsk, false); } vsk->close_work_scheduled = false; release_sock(sk); sock_put(sk); }

Contributors

PersonTokensPropCommitsCommitProp
asias heasias he93100.00%1100.00%
Total93100.00%1100.00%

/* User context, vsk->sk is locked */
static bool virtio_transport_close(struct vsock_sock *vsk) { struct sock *sk = &vsk->sk; if (!(sk->sk_state == SS_CONNECTED || sk->sk_state == SS_DISCONNECTING)) return true; /* Already received SHUTDOWN from peer, reply with RST */ if ((vsk->peer_shutdown & SHUTDOWN_MASK) == SHUTDOWN_MASK) { (void)virtio_transport_reset(vsk, NULL); return true; } if ((sk->sk_shutdown & SHUTDOWN_MASK) != SHUTDOWN_MASK) (void)virtio_transport_shutdown(vsk, SHUTDOWN_MASK); if (sock_flag(sk, SOCK_LINGER) && !(current->flags & PF_EXITING)) virtio_transport_wait_close(sk, sk->sk_lingertime); if (sock_flag(sk, SOCK_DONE)) { return true; } sock_hold(sk); INIT_DELAYED_WORK(&vsk->close_work, virtio_transport_close_timeout)