Skip to content

Commit

Permalink
vsock: handle buffer_size sockopts in the core
Browse files Browse the repository at this point in the history
virtio_transport and vmci_transport handle the buffer_size
sockopts in a very similar way.

In order to support multiple transports, this patch moves this
handling in the core to allow the user to change the options
also if the socket is not yet assigned to any transport.

This patch also adds the '.notify_buffer_size' callback in the
'struct virtio_transport' in order to inform the transport,
when the buffer_size is changed by the user. It is also useful
to limit the 'buffer_size' requested (e.g. virtio transports).

Acked-by: Dexuan Cui <[email protected]>
Reviewed-by: Stefan Hajnoczi <[email protected]>
Reviewed-by: Jorgen Hansen <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
stefano-garzarella authored and davem330 committed Nov 15, 2019
1 parent daabfbc commit b9f2b0f
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 227 deletions.
7 changes: 1 addition & 6 deletions drivers/vhost/vsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,13 +418,8 @@ static struct virtio_transport vhost_transport = {
.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,

.set_buffer_size = virtio_transport_set_buffer_size,
.set_min_buffer_size = virtio_transport_set_min_buffer_size,
.set_max_buffer_size = virtio_transport_set_max_buffer_size,
.get_buffer_size = virtio_transport_get_buffer_size,
.get_min_buffer_size = virtio_transport_get_min_buffer_size,
.get_max_buffer_size = virtio_transport_get_max_buffer_size,
},

.send_pkt = vhost_transport_send_pkt,
Expand Down
15 changes: 1 addition & 14 deletions include/linux/virtio_vsock.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
#include <net/sock.h>
#include <net/af_vsock.h>

#define VIRTIO_VSOCK_DEFAULT_MIN_BUF_SIZE 128
#define VIRTIO_VSOCK_DEFAULT_BUF_SIZE (1024 * 256)
#define VIRTIO_VSOCK_DEFAULT_MAX_BUF_SIZE (1024 * 256)
#define VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE (1024 * 4)
#define VIRTIO_VSOCK_MAX_BUF_SIZE 0xFFFFFFFFUL
#define VIRTIO_VSOCK_MAX_PKT_BUF_SIZE (1024 * 64)
Expand All @@ -25,11 +22,6 @@ enum {
struct virtio_vsock_sock {
struct vsock_sock *vsk;

/* Protected by lock_sock(sk_vsock(trans->vsk)) */
u32 buf_size;
u32 buf_size_min;
u32 buf_size_max;

spinlock_t tx_lock;
spinlock_t rx_lock;

Expand Down Expand Up @@ -92,12 +84,6 @@ s64 virtio_transport_stream_has_space(struct vsock_sock *vsk);

int virtio_transport_do_socket_init(struct vsock_sock *vsk,
struct vsock_sock *psk);
u64 virtio_transport_get_buffer_size(struct vsock_sock *vsk);
u64 virtio_transport_get_min_buffer_size(struct vsock_sock *vsk);
u64 virtio_transport_get_max_buffer_size(struct vsock_sock *vsk);
void virtio_transport_set_buffer_size(struct vsock_sock *vsk, u64 val);
void virtio_transport_set_min_buffer_size(struct vsock_sock *vsk, u64 val);
void virtio_transport_set_max_buffer_size(struct vsock_sock *vs, u64 val);
int
virtio_transport_notify_poll_in(struct vsock_sock *vsk,
size_t target,
Expand All @@ -124,6 +110,7 @@ int virtio_transport_notify_send_pre_enqueue(struct vsock_sock *vsk,
struct vsock_transport_send_notify_data *data);
int virtio_transport_notify_send_post_enqueue(struct vsock_sock *vsk,
ssize_t written, struct vsock_transport_send_notify_data *data);
void virtio_transport_notify_buffer_size(struct vsock_sock *vsk, u64 *val);

u64 virtio_transport_stream_rcvhiwat(struct vsock_sock *vsk);
bool virtio_transport_stream_is_active(struct vsock_sock *vsk);
Expand Down
15 changes: 7 additions & 8 deletions include/net/af_vsock.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ struct vsock_sock {
bool sent_request;
bool ignore_connecting_rst;

/* Protected by lock_sock(sk) */
u64 buffer_size;
u64 buffer_min_size;
u64 buffer_max_size;

/* Private to transport. */
void *trans;
};
Expand Down Expand Up @@ -140,18 +145,12 @@ struct vsock_transport {
struct vsock_transport_send_notify_data *);
int (*notify_send_post_enqueue)(struct vsock_sock *, ssize_t,
struct vsock_transport_send_notify_data *);
/* sk_lock held by the caller */
void (*notify_buffer_size)(struct vsock_sock *, u64 *);

/* Shutdown. */
int (*shutdown)(struct vsock_sock *, int);

/* Buffer sizes. */
void (*set_buffer_size)(struct vsock_sock *, u64);
void (*set_min_buffer_size)(struct vsock_sock *, u64);
void (*set_max_buffer_size)(struct vsock_sock *, u64);
u64 (*get_buffer_size)(struct vsock_sock *);
u64 (*get_min_buffer_size)(struct vsock_sock *);
u64 (*get_max_buffer_size)(struct vsock_sock *);

/* Addressing. */
u32 (*get_local_cid)(void);
};
Expand Down
43 changes: 35 additions & 8 deletions net/vmw_vsock/af_vsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ static struct proto vsock_proto = {
*/
#define VSOCK_DEFAULT_CONNECT_TIMEOUT (2 * HZ)

#define VSOCK_DEFAULT_BUFFER_SIZE (1024 * 256)
#define VSOCK_DEFAULT_BUFFER_MAX_SIZE (1024 * 256)
#define VSOCK_DEFAULT_BUFFER_MIN_SIZE 128

static const struct vsock_transport *transport_single;
static DEFINE_MUTEX(vsock_register_mutex);

Expand Down Expand Up @@ -613,10 +617,16 @@ struct sock *__vsock_create(struct net *net,
vsk->trusted = psk->trusted;
vsk->owner = get_cred(psk->owner);
vsk->connect_timeout = psk->connect_timeout;
vsk->buffer_size = psk->buffer_size;
vsk->buffer_min_size = psk->buffer_min_size;
vsk->buffer_max_size = psk->buffer_max_size;
} else {
vsk->trusted = capable(CAP_NET_ADMIN);
vsk->owner = get_current_cred();
vsk->connect_timeout = VSOCK_DEFAULT_CONNECT_TIMEOUT;
vsk->buffer_size = VSOCK_DEFAULT_BUFFER_SIZE;
vsk->buffer_min_size = VSOCK_DEFAULT_BUFFER_MIN_SIZE;
vsk->buffer_max_size = VSOCK_DEFAULT_BUFFER_MAX_SIZE;
}

if (vsk->transport->init(vsk, psk) < 0) {
Expand Down Expand Up @@ -1366,6 +1376,23 @@ static int vsock_listen(struct socket *sock, int backlog)
return err;
}

static void vsock_update_buffer_size(struct vsock_sock *vsk,
const struct vsock_transport *transport,
u64 val)
{
if (val > vsk->buffer_max_size)
val = vsk->buffer_max_size;

if (val < vsk->buffer_min_size)
val = vsk->buffer_min_size;

if (val != vsk->buffer_size &&
transport && transport->notify_buffer_size)
transport->notify_buffer_size(vsk, &val);

vsk->buffer_size = val;
}

static int vsock_stream_setsockopt(struct socket *sock,
int level,
int optname,
Expand Down Expand Up @@ -1403,17 +1430,19 @@ static int vsock_stream_setsockopt(struct socket *sock,
switch (optname) {
case SO_VM_SOCKETS_BUFFER_SIZE:
COPY_IN(val);
transport->set_buffer_size(vsk, val);
vsock_update_buffer_size(vsk, transport, val);
break;

case SO_VM_SOCKETS_BUFFER_MAX_SIZE:
COPY_IN(val);
transport->set_max_buffer_size(vsk, val);
vsk->buffer_max_size = val;
vsock_update_buffer_size(vsk, transport, vsk->buffer_size);
break;

case SO_VM_SOCKETS_BUFFER_MIN_SIZE:
COPY_IN(val);
transport->set_min_buffer_size(vsk, val);
vsk->buffer_min_size = val;
vsock_update_buffer_size(vsk, transport, vsk->buffer_size);
break;

case SO_VM_SOCKETS_CONNECT_TIMEOUT: {
Expand Down Expand Up @@ -1454,7 +1483,6 @@ static int vsock_stream_getsockopt(struct socket *sock,
int len;
struct sock *sk;
struct vsock_sock *vsk;
const struct vsock_transport *transport;
u64 val;

if (level != AF_VSOCK)
Expand All @@ -1478,21 +1506,20 @@ static int vsock_stream_getsockopt(struct socket *sock,
err = 0;
sk = sock->sk;
vsk = vsock_sk(sk);
transport = vsk->transport;

switch (optname) {
case SO_VM_SOCKETS_BUFFER_SIZE:
val = transport->get_buffer_size(vsk);
val = vsk->buffer_size;
COPY_OUT(val);
break;

case SO_VM_SOCKETS_BUFFER_MAX_SIZE:
val = transport->get_max_buffer_size(vsk);
val = vsk->buffer_max_size;
COPY_OUT(val);
break;

case SO_VM_SOCKETS_BUFFER_MIN_SIZE:
val = transport->get_min_buffer_size(vsk);
val = vsk->buffer_min_size;
COPY_OUT(val);
break;

Expand Down
36 changes: 0 additions & 36 deletions net/vmw_vsock/hyperv_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -845,36 +845,6 @@ int hvs_notify_send_post_enqueue(struct vsock_sock *vsk, ssize_t written,
return 0;
}

static void hvs_set_buffer_size(struct vsock_sock *vsk, u64 val)
{
/* Ignored. */
}

static void hvs_set_min_buffer_size(struct vsock_sock *vsk, u64 val)
{
/* Ignored. */
}

static void hvs_set_max_buffer_size(struct vsock_sock *vsk, u64 val)
{
/* Ignored. */
}

static u64 hvs_get_buffer_size(struct vsock_sock *vsk)
{
return -ENOPROTOOPT;
}

static u64 hvs_get_min_buffer_size(struct vsock_sock *vsk)
{
return -ENOPROTOOPT;
}

static u64 hvs_get_max_buffer_size(struct vsock_sock *vsk)
{
return -ENOPROTOOPT;
}

static struct vsock_transport hvs_transport = {
.get_local_cid = hvs_get_local_cid,

Expand Down Expand Up @@ -908,12 +878,6 @@ static struct vsock_transport hvs_transport = {
.notify_send_pre_enqueue = hvs_notify_send_pre_enqueue,
.notify_send_post_enqueue = hvs_notify_send_post_enqueue,

.set_buffer_size = hvs_set_buffer_size,
.set_min_buffer_size = hvs_set_min_buffer_size,
.set_max_buffer_size = hvs_set_max_buffer_size,
.get_buffer_size = hvs_get_buffer_size,
.get_min_buffer_size = hvs_get_min_buffer_size,
.get_max_buffer_size = hvs_get_max_buffer_size,
};

static int hvs_probe(struct hv_device *hdev,
Expand Down
8 changes: 1 addition & 7 deletions net/vmw_vsock/virtio_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,13 +494,7 @@ static struct virtio_transport virtio_transport = {
.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,

.set_buffer_size = virtio_transport_set_buffer_size,
.set_min_buffer_size = virtio_transport_set_min_buffer_size,
.set_max_buffer_size = virtio_transport_set_max_buffer_size,
.get_buffer_size = virtio_transport_get_buffer_size,
.get_min_buffer_size = virtio_transport_get_min_buffer_size,
.get_max_buffer_size = virtio_transport_get_max_buffer_size,
.notify_buffer_size = virtio_transport_notify_buffer_size,
},

.send_pkt = virtio_transport_send_pkt,
Expand Down
79 changes: 11 additions & 68 deletions net/vmw_vsock/virtio_transport_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,17 +456,13 @@ int virtio_transport_do_socket_init(struct vsock_sock *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;
if (vsk->buffer_size > VIRTIO_VSOCK_MAX_BUF_SIZE)
vsk->buffer_size = VIRTIO_VSOCK_MAX_BUF_SIZE;

vvs->buf_alloc = vsk->buffer_size;

spin_lock_init(&vvs->rx_lock);
spin_lock_init(&vvs->tx_lock);
Expand All @@ -476,71 +472,20 @@ int virtio_transport_do_socket_init(struct vsock_sock *vsk,
}
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;
}
EXPORT_SYMBOL_GPL(virtio_transport_get_buffer_size);

u64 virtio_transport_get_min_buffer_size(struct vsock_sock *vsk)
/* sk_lock held by the caller */
void virtio_transport_notify_buffer_size(struct vsock_sock *vsk, u64 *val)
{
struct virtio_vsock_sock *vvs = vsk->trans;

return vvs->buf_size_min;
}
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;
}
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 > 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;
vvs->buf_alloc = *val;

virtio_transport_send_credit_update(vsk, VIRTIO_VSOCK_TYPE_STREAM,
NULL);
}
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;
}
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;
}
EXPORT_SYMBOL_GPL(virtio_transport_set_max_buffer_size);
EXPORT_SYMBOL_GPL(virtio_transport_notify_buffer_size);

int
virtio_transport_notify_poll_in(struct vsock_sock *vsk,
Expand Down Expand Up @@ -632,9 +577,7 @@ 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;
return vsk->buffer_size;
}
EXPORT_SYMBOL_GPL(virtio_transport_stream_rcvhiwat);

Expand Down
Loading

0 comments on commit b9f2b0f

Please sign in to comment.