[RFC PATCH 13/16] virtio_ring: packed: support copy from vring

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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_packed(), but skips DMA. Use
the function virtqueue_update_packed() provided by the previous patch to
update the state of the vq.

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

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 1efb47b88b40..8ca9985ffb4b 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1654,6 +1654,82 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq,
 	return -EIO;
 }
 
+static u32 vring_copy_desc_packed(struct vring_virtqueue *vq,
+				  u32 idx,
+				  u16 curr,
+				  __le16 *head_flags,
+				  struct vring_virtqueue_packed *vring,
+				  u32 src)
+{
+	u16 old_flags = vring->desc_extra[src].flags;
+	u16 flags = vq->packed.avail_used_flags;
+	struct vring_packed_desc *desc;
+	struct vring_desc_extra *extra;
+
+	if (old_flags & VRING_DESC_F_NEXT)
+		flags |= VRING_DESC_F_NEXT;
+
+	if (old_flags & VRING_DESC_F_WRITE)
+		flags |= VRING_DESC_F_WRITE;
+
+	if (old_flags & VRING_DESC_F_INDIRECT)
+		flags |= VRING_DESC_F_INDIRECT;
+
+	desc = vq->packed.vring.desc + idx;
+	extra = vq->packed.desc_extra + curr;
+
+	if (head_flags)
+		*head_flags = cpu_to_le16(flags);
+	else
+		desc->flags = cpu_to_le16(flags);
+
+	desc->addr = cpu_to_le64(vring->desc_extra[src].addr);
+	desc->len  = cpu_to_le32(vring->desc_extra[src].len);
+	desc->id   = cpu_to_le16(vq->free_head);
+
+	extra->addr  = vring->desc_extra[src].addr;
+	extra->len   = vring->desc_extra[src].len;
+	extra->flags = vring->desc_extra[src].flags;
+
+	return vq->packed.desc_extra[curr].next;
+}
+
+static int vring_copy_to_vq_packed(struct vring_virtqueue *vq,
+				   struct vring_virtqueue_packed *vring,
+				   u32 old_id)
+{
+	struct vring_desc_state_packed *state;
+	__le16 head_flags;
+	u16 prev, curr;
+	u32 i, n;
+
+	state = &vring->desc_state[old_id];
+
+	if (state->num > vq->vq.num_free)
+		return -ENOSPC;
+
+	i = vq->packed.next_avail_idx;
+	curr = vq->free_head;
+
+	for (n = 0; n < state->num; n++) {
+		prev = curr;
+		curr = vring_copy_desc_packed(vq, i, curr,
+					      n ? NULL : &head_flags,
+					      vring, old_id);
+
+		old_id = vring->desc_extra[old_id].next;
+
+		i = next_idx(vq, i);
+	}
+
+	virtqueue_update_packed(vq, state->num, curr, prev, i, head_flags,
+				state->indir_desc, state->data);
+
+	state->data = NULL;
+
+	return state->num;
+}
+
 static bool virtqueue_kick_prepare_packed(struct virtqueue *_vq)
 {
 	struct vring_virtqueue *vq = to_vvq(_vq);
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linuxfoundation.org/mailman/listinfo/virtualization



[Index of Archives]     [KVM Development]     [Libvirt Development]     [Libvirt Users]     [CentOS Virtualization]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux