To handle freeing buf from the detached vring, do a split for detach_buf_split(). The split function detach_buf_from_vring_split() is used to release buf from vring, and the vq passed in is read-only. All modifications are for vring. In this way, detach_buf_from_vring_split() becomes a general function, which can be used for detach_buf_split() and also for handling detached vrings. Signed-off-by: Xuan Zhuo <xuanzhuo@xxxxxxxxxxxxxxxxx> --- drivers/virtio/virtio_ring.c | 54 +++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 6fd45c9a3517..aa85058978cb 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -734,54 +734,68 @@ static bool virtqueue_kick_prepare_split(struct virtqueue *_vq) return needs_kick; } -static void detach_buf_split(struct vring_virtqueue *vq, unsigned int head, - void **ctx) +static int detach_buf_from_vring_split(struct vring_virtqueue_split *vring, + struct vring_virtqueue const *vq, + unsigned int head, + unsigned int free_head, + void **ctx) { - unsigned int i, j; + unsigned int i, j, num = 0; __virtio16 nextflag = cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_NEXT); /* Clear data ptr. */ - vq->split.desc_state[head].data = NULL; + vring->desc_state[head].data = NULL; /* Put back on free list: unmap first-level descriptors and find end */ i = head; - while (vq->split.vring.desc[i].flags & nextflag) { - vring_unmap_one_split(vq, &vq->split.desc_extra[i]); - i = vq->split.desc_extra[i].next; - vq->vq.num_free++; + while (vring->vring.desc[i].flags & nextflag) { + vring_unmap_one_split(vq, &vring->desc_extra[i]); + i = vring->desc_extra[i].next; + ++num; } - vring_unmap_one_split(vq, &vq->split.desc_extra[i]); - vq->split.desc_extra[i].next = vq->free_head; - vq->free_head = head; + vring_unmap_one_split(vq, &vring->desc_extra[i]); + vring->desc_extra[i].next = free_head; - /* Plus final descriptor */ - vq->vq.num_free++; + ++num; if (vq->indirect) { struct vring_desc *indir_desc = - vq->split.desc_state[head].indir_desc; + vring->desc_state[head].indir_desc; u32 len; /* Free the indirect table, if any, now that it's unmapped. */ if (!indir_desc) - return; + return num; - len = vq->split.desc_extra[head].len; + len = vring->desc_extra[head].len; - BUG_ON(!(vq->split.desc_extra[head].flags & - VRING_DESC_F_INDIRECT)); + BUG_ON(!(vring->desc_extra[head].flags & VRING_DESC_F_INDIRECT)); BUG_ON(len == 0 || len % sizeof(struct vring_desc)); for (j = 0; j < len / sizeof(struct vring_desc); j++) vring_unmap_one_split_indirect(vq, &indir_desc[j]); kfree(indir_desc); - vq->split.desc_state[head].indir_desc = NULL; + vring->desc_state[head].indir_desc = NULL; } else if (ctx) { - *ctx = vq->split.desc_state[head].indir_desc; + *ctx = vring->desc_state[head].indir_desc; } + + return num; +} + +static void detach_buf_split(struct vring_virtqueue *vq, unsigned int head, + void **ctx) +{ + int num; + + num = detach_buf_from_vring_split(&vq->split, vq, head, vq->free_head, + ctx); + + vq->vq.num_free += num; + vq->free_head = head; } static inline bool more_used_split(const struct vring_virtqueue *vq) -- 2.31.0 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/virtualization