lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Sun, 24 Apr 2022 10:40:41 +0800
From:   Xuan Zhuo <xuanzhuo@...ux.alibaba.com>
To:     linux-kernel@...r.kernel.org
Cc:     "Michael S. Tsirkin" <mst@...hat.com>,
        Jason Wang <jasowang@...hat.com>,
        virtualization@...ts.linux-foundation.org
Subject: [RFC PATCH 13/16] virtio_ring: packed: support copy from vring

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@...ux.alibaba.com>
---
 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

Powered by blists - more mailing lists