Merge branch 'vhost-net-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
This commit is contained in:
commit
42560ca061
|
@ -243,7 +243,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
|
|||
int r, nlogs = 0;
|
||||
|
||||
while (datalen > 0) {
|
||||
if (unlikely(seg >= VHOST_NET_MAX_SG)) {
|
||||
if (unlikely(seg >= UIO_MAXIOV)) {
|
||||
r = -ENOBUFS;
|
||||
goto err;
|
||||
}
|
||||
|
|
|
@ -212,6 +212,45 @@ static int vhost_worker(void *data)
|
|||
}
|
||||
}
|
||||
|
||||
/* Helper to allocate iovec buffers for all vqs. */
|
||||
static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dev->nvqs; ++i) {
|
||||
dev->vqs[i].indirect = kmalloc(sizeof *dev->vqs[i].indirect *
|
||||
UIO_MAXIOV, GFP_KERNEL);
|
||||
dev->vqs[i].log = kmalloc(sizeof *dev->vqs[i].log * UIO_MAXIOV,
|
||||
GFP_KERNEL);
|
||||
dev->vqs[i].heads = kmalloc(sizeof *dev->vqs[i].heads *
|
||||
UIO_MAXIOV, GFP_KERNEL);
|
||||
|
||||
if (!dev->vqs[i].indirect || !dev->vqs[i].log ||
|
||||
!dev->vqs[i].heads)
|
||||
goto err_nomem;
|
||||
}
|
||||
return 0;
|
||||
err_nomem:
|
||||
for (; i >= 0; --i) {
|
||||
kfree(dev->vqs[i].indirect);
|
||||
kfree(dev->vqs[i].log);
|
||||
kfree(dev->vqs[i].heads);
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void vhost_dev_free_iovecs(struct vhost_dev *dev)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dev->nvqs; ++i) {
|
||||
kfree(dev->vqs[i].indirect);
|
||||
dev->vqs[i].indirect = NULL;
|
||||
kfree(dev->vqs[i].log);
|
||||
dev->vqs[i].log = NULL;
|
||||
kfree(dev->vqs[i].heads);
|
||||
dev->vqs[i].heads = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
long vhost_dev_init(struct vhost_dev *dev,
|
||||
struct vhost_virtqueue *vqs, int nvqs)
|
||||
{
|
||||
|
@ -229,6 +268,9 @@ long vhost_dev_init(struct vhost_dev *dev,
|
|||
dev->worker = NULL;
|
||||
|
||||
for (i = 0; i < dev->nvqs; ++i) {
|
||||
dev->vqs[i].log = NULL;
|
||||
dev->vqs[i].indirect = NULL;
|
||||
dev->vqs[i].heads = NULL;
|
||||
dev->vqs[i].dev = dev;
|
||||
mutex_init(&dev->vqs[i].mutex);
|
||||
vhost_vq_reset(dev, dev->vqs + i);
|
||||
|
@ -295,6 +337,10 @@ static long vhost_dev_set_owner(struct vhost_dev *dev)
|
|||
if (err)
|
||||
goto err_cgroup;
|
||||
|
||||
err = vhost_dev_alloc_iovecs(dev);
|
||||
if (err)
|
||||
goto err_cgroup;
|
||||
|
||||
return 0;
|
||||
err_cgroup:
|
||||
kthread_stop(worker);
|
||||
|
@ -345,6 +391,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
|
|||
fput(dev->vqs[i].call);
|
||||
vhost_vq_reset(dev, dev->vqs + i);
|
||||
}
|
||||
vhost_dev_free_iovecs(dev);
|
||||
if (dev->log_ctx)
|
||||
eventfd_ctx_put(dev->log_ctx);
|
||||
dev->log_ctx = NULL;
|
||||
|
@ -947,7 +994,7 @@ static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
|
|||
}
|
||||
|
||||
ret = translate_desc(dev, indirect->addr, indirect->len, vq->indirect,
|
||||
ARRAY_SIZE(vq->indirect));
|
||||
UIO_MAXIOV);
|
||||
if (unlikely(ret < 0)) {
|
||||
vq_err(vq, "Translation failure %d in indirect.\n", ret);
|
||||
return ret;
|
||||
|
|
|
@ -15,11 +15,6 @@
|
|||
|
||||
struct vhost_device;
|
||||
|
||||
enum {
|
||||
/* Enough place for all fragments, head, and virtio net header. */
|
||||
VHOST_NET_MAX_SG = MAX_SKB_FRAGS + 2,
|
||||
};
|
||||
|
||||
struct vhost_work;
|
||||
typedef void (*vhost_work_fn_t)(struct vhost_work *work);
|
||||
|
||||
|
@ -93,12 +88,15 @@ struct vhost_virtqueue {
|
|||
bool log_used;
|
||||
u64 log_addr;
|
||||
|
||||
struct iovec indirect[VHOST_NET_MAX_SG];
|
||||
struct iovec iov[VHOST_NET_MAX_SG];
|
||||
struct iovec hdr[VHOST_NET_MAX_SG];
|
||||
struct iovec iov[UIO_MAXIOV];
|
||||
/* hdr is used to store the virtio header.
|
||||
* Since each iovec has >= 1 byte length, we never need more than
|
||||
* header length entries to store the header. */
|
||||
struct iovec hdr[sizeof(struct virtio_net_hdr_mrg_rxbuf)];
|
||||
struct iovec *indirect;
|
||||
size_t vhost_hlen;
|
||||
size_t sock_hlen;
|
||||
struct vring_used_elem heads[VHOST_NET_MAX_SG];
|
||||
struct vring_used_elem *heads;
|
||||
/* We use a kind of RCU to access private pointer.
|
||||
* All readers access it from worker, which makes it possible to
|
||||
* flush the vhost_work instead of synchronize_rcu. Therefore readers do
|
||||
|
@ -109,7 +107,7 @@ struct vhost_virtqueue {
|
|||
void *private_data;
|
||||
/* Log write descriptors */
|
||||
void __user *log_base;
|
||||
struct vhost_log log[VHOST_NET_MAX_SG];
|
||||
struct vhost_log *log;
|
||||
};
|
||||
|
||||
struct vhost_dev {
|
||||
|
|
Loading…
Reference in New Issue