lkml.org 
[lkml]   [2022]   [Apr]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[RFC PATCH 05/16] virtio_ring: split: support copy from vring
Date
To support reusing old buffers during resize.

This patch implements copying a buffer from the detached vring to the vq
where the new vring is attached.

This process is similar to virtqueue_add_split(), but skips DMA. Use
the function virtqueue_update_split() provided by the previous patch to
update the state of the vq.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
drivers/virtio/virtio_ring.c | 60 ++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index aa85058978cb..167442cfdb2a 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -703,6 +703,66 @@ static inline int virtqueue_add_split(struct virtqueue *_vq,
return -ENOMEM;
}

+static u32 vring_copy_desc_split(struct vring_virtqueue *vq, u32 i,
+ struct vring_virtqueue_split *vring,
+ u32 src)
+{
+ struct vring_desc_extra *extra = vq->split.desc_extra;
+ struct vring_desc *desc = vq->split.vring.desc;
+ u16 next;
+
+ desc[i].flags = vring->vring.desc[src].flags;
+ desc[i].addr = vring->vring.desc[src].addr;
+ desc[i].len = vring->vring.desc[src].len;
+
+ next = extra[i].next;
+
+ desc[i].next = cpu_to_virtio16(vq->vq.vdev, next);
+
+ extra[i].addr = vring->desc_extra[src].addr;
+ extra[i].len = vring->desc_extra[src].len;
+ extra[i].flags = vring->desc_extra[src].flags;
+
+ return next;
+}
+
+static int vring_copy_to_vq_split(struct vring_virtqueue *vq,
+ struct vring_virtqueue_split *vring,
+ u32 old_index)
+{
+ __virtio16 nextflag = cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_NEXT);
+ struct vring_desc_state_split *state;
+ u32 i, num = 1, old_idx;
+
+ old_idx = old_index;
+ while (vring->vring.desc[old_idx].flags & nextflag) {
+ old_idx = vring->desc_extra[old_idx].next;
+ ++num;
+ }
+
+ if (num > vq->vq.num_free)
+ return -ENOSPC;
+
+ i = vq->free_head;
+
+ old_idx = old_index;
+ while (vring->vring.desc[old_idx].flags & nextflag) {
+ i = vring_copy_desc_split(vq, i, vring, old_idx);
+
+ old_idx = vring->desc_extra[old_idx].next;
+ }
+
+ i = vring_copy_desc_split(vq, i, vring, old_idx);
+
+ state = &vring->desc_state[old_index];
+
+ virtqueue_update_split(vq, num, i, state->indir_desc, state->data);
+
+ state->data = NULL;
+
+ return num;
+}
+
static bool virtqueue_kick_prepare_split(struct virtqueue *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
--
2.31.0
\
 
 \ /
  Last update: 2022-04-24 04:41    [W:0.073 / U:0.448 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site