diff mbox series

[v13,16/42] virtio_ring: split: introduce virtqueue_resize_split()

Message ID 20220726072225.19884-17-xuanzhuo@linux.alibaba.com (mailing list archive)
State New, archived
Headers show
Series virtio pci support VIRTIO_F_RING_RESET | expand

Commit Message

Xuan Zhuo July 26, 2022, 7:21 a.m. UTC
virtio ring split supports resize.

Only after the new vring is successfully allocated based on the new num,
we will release the old vring. In any case, an error is returned,
indicating that the vring still points to the old vring.

In the case of an error, re-initialize(virtqueue_reinit_split()) the
virtqueue to ensure that the vring can be used.

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

Comments

Jason Wang July 27, 2022, 3:12 a.m. UTC | #1
在 2022/7/26 15:21, Xuan Zhuo 写道:
> virtio ring split supports resize.
>
> Only after the new vring is successfully allocated based on the new num,
> we will release the old vring. In any case, an error is returned,
> indicating that the vring still points to the old vring.
>
> In the case of an error, re-initialize(virtqueue_reinit_split()) the
> virtqueue to ensure that the vring can be used.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> Acked-by: Jason Wang <jasowang@redhat.com>
> ---
>   drivers/virtio/virtio_ring.c | 34 ++++++++++++++++++++++++++++++++++
>   1 file changed, 34 insertions(+)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index b6fda91c8059..58355e1ac7d7 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -220,6 +220,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
>   					       void (*callback)(struct virtqueue *),
>   					       const char *name);
>   static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
> +static void vring_free(struct virtqueue *_vq);
>   
>   /*
>    * Helpers.
> @@ -1117,6 +1118,39 @@ static struct virtqueue *vring_create_virtqueue_split(
>   	return vq;
>   }
>   
> +static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
> +{
> +	struct vring_virtqueue_split vring_split = {};
> +	struct vring_virtqueue *vq = to_vvq(_vq);
> +	struct virtio_device *vdev = _vq->vdev;
> +	int err;
> +
> +	err = vring_alloc_queue_split(&vring_split, vdev, num,
> +				      vq->split.vring_align,
> +				      vq->split.may_reduce_num);
> +	if (err)
> +		goto err;


I think we don't need to do anything here?


> +
> +	err = vring_alloc_state_extra_split(&vring_split);
> +	if (err) {
> +		vring_free_split(&vring_split, vdev);
> +		goto err;


I suggest to move vring_free_split() into a dedicated error label.

Thanks


> +	}
> +
> +	vring_free(&vq->vq);
> +
> +	virtqueue_vring_init_split(&vring_split, vq);
> +
> +	virtqueue_init(vq, vring_split.vring.num);
> +	virtqueue_vring_attach_split(vq, &vring_split);
> +
> +	return 0;
> +
> +err:
> +	virtqueue_reinit_split(vq);
> +	return -ENOMEM;
> +}
> +
>   
>   /*
>    * Packed ring specific functions - *_packed().
Xuan Zhuo July 27, 2022, 7:36 a.m. UTC | #2
On Wed, 27 Jul 2022 11:12:19 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/7/26 15:21, Xuan Zhuo 写道:
> > virtio ring split supports resize.
> >
> > Only after the new vring is successfully allocated based on the new num,
> > we will release the old vring. In any case, an error is returned,
> > indicating that the vring still points to the old vring.
> >
> > In the case of an error, re-initialize(virtqueue_reinit_split()) the
> > virtqueue to ensure that the vring can be used.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > Acked-by: Jason Wang <jasowang@redhat.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 34 ++++++++++++++++++++++++++++++++++
> >   1 file changed, 34 insertions(+)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index b6fda91c8059..58355e1ac7d7 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -220,6 +220,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
> >   					       void (*callback)(struct virtqueue *),
> >   					       const char *name);
> >   static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
> > +static void vring_free(struct virtqueue *_vq);
> >
> >   /*
> >    * Helpers.
> > @@ -1117,6 +1118,39 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   	return vq;
> >   }
> >
> > +static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
> > +{
> > +	struct vring_virtqueue_split vring_split = {};
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +	struct virtio_device *vdev = _vq->vdev;
> > +	int err;
> > +
> > +	err = vring_alloc_queue_split(&vring_split, vdev, num,
> > +				      vq->split.vring_align,
> > +				      vq->split.may_reduce_num);
> > +	if (err)
> > +		goto err;
>
>
> I think we don't need to do anything here?

Am I missing something?

>
>
> > +
> > +	err = vring_alloc_state_extra_split(&vring_split);
> > +	if (err) {
> > +		vring_free_split(&vring_split, vdev);
> > +		goto err;
>
>
> I suggest to move vring_free_split() into a dedicated error label.

Will change.

Thanks.


>
> Thanks
>
>
> > +	}
> > +
> > +	vring_free(&vq->vq);
> > +
> > +	virtqueue_vring_init_split(&vring_split, vq);
> > +
> > +	virtqueue_init(vq, vring_split.vring.num);
> > +	virtqueue_vring_attach_split(vq, &vring_split);
> > +
> > +	return 0;
> > +
> > +err:
> > +	virtqueue_reinit_split(vq);
> > +	return -ENOMEM;
> > +}
> > +
> >
> >   /*
> >    * Packed ring specific functions - *_packed().
>
Jason Wang July 28, 2022, 2:38 a.m. UTC | #3
On Wed, Jul 27, 2022 at 3:44 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
>
> On Wed, 27 Jul 2022 11:12:19 +0800, Jason Wang <jasowang@redhat.com> wrote:
> >
> > 在 2022/7/26 15:21, Xuan Zhuo 写道:
> > > virtio ring split supports resize.
> > >
> > > Only after the new vring is successfully allocated based on the new num,
> > > we will release the old vring. In any case, an error is returned,
> > > indicating that the vring still points to the old vring.
> > >
> > > In the case of an error, re-initialize(virtqueue_reinit_split()) the
> > > virtqueue to ensure that the vring can be used.
> > >
> > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > Acked-by: Jason Wang <jasowang@redhat.com>
> > > ---
> > >   drivers/virtio/virtio_ring.c | 34 ++++++++++++++++++++++++++++++++++
> > >   1 file changed, 34 insertions(+)
> > >
> > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > index b6fda91c8059..58355e1ac7d7 100644
> > > --- a/drivers/virtio/virtio_ring.c
> > > +++ b/drivers/virtio/virtio_ring.c
> > > @@ -220,6 +220,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > >                                            void (*callback)(struct virtqueue *),
> > >                                            const char *name);
> > >   static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
> > > +static void vring_free(struct virtqueue *_vq);
> > >
> > >   /*
> > >    * Helpers.
> > > @@ -1117,6 +1118,39 @@ static struct virtqueue *vring_create_virtqueue_split(
> > >     return vq;
> > >   }
> > >
> > > +static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
> > > +{
> > > +   struct vring_virtqueue_split vring_split = {};
> > > +   struct vring_virtqueue *vq = to_vvq(_vq);
> > > +   struct virtio_device *vdev = _vq->vdev;
> > > +   int err;
> > > +
> > > +   err = vring_alloc_queue_split(&vring_split, vdev, num,
> > > +                                 vq->split.vring_align,
> > > +                                 vq->split.may_reduce_num);
> > > +   if (err)
> > > +           goto err;
> >
> >
> > I think we don't need to do anything here?
>
> Am I missing something?

I meant it looks to me most of the virtqueue_reinit() is unnecessary.
We probably only need to reinit avail/used idx there.

Thanks

>
> >
> >
> > > +
> > > +   err = vring_alloc_state_extra_split(&vring_split);
> > > +   if (err) {
> > > +           vring_free_split(&vring_split, vdev);
> > > +           goto err;
> >
> >
> > I suggest to move vring_free_split() into a dedicated error label.
>
> Will change.
>
> Thanks.
>
>
> >
> > Thanks
> >
> >
> > > +   }
> > > +
> > > +   vring_free(&vq->vq);
> > > +
> > > +   virtqueue_vring_init_split(&vring_split, vq);
> > > +
> > > +   virtqueue_init(vq, vring_split.vring.num);
> > > +   virtqueue_vring_attach_split(vq, &vring_split);
> > > +
> > > +   return 0;
> > > +
> > > +err:
> > > +   virtqueue_reinit_split(vq);
> > > +   return -ENOMEM;
> > > +}
> > > +
> > >
> > >   /*
> > >    * Packed ring specific functions - *_packed().
> >
>
Xuan Zhuo July 28, 2022, 7:09 a.m. UTC | #4
On Thu, 28 Jul 2022 10:38:51 +0800, Jason Wang <jasowang@redhat.com> wrote:
> On Wed, Jul 27, 2022 at 3:44 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> >
> > On Wed, 27 Jul 2022 11:12:19 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > >
> > > 在 2022/7/26 15:21, Xuan Zhuo 写道:
> > > > virtio ring split supports resize.
> > > >
> > > > Only after the new vring is successfully allocated based on the new num,
> > > > we will release the old vring. In any case, an error is returned,
> > > > indicating that the vring still points to the old vring.
> > > >
> > > > In the case of an error, re-initialize(virtqueue_reinit_split()) the
> > > > virtqueue to ensure that the vring can be used.
> > > >
> > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > Acked-by: Jason Wang <jasowang@redhat.com>
> > > > ---
> > > >   drivers/virtio/virtio_ring.c | 34 ++++++++++++++++++++++++++++++++++
> > > >   1 file changed, 34 insertions(+)
> > > >
> > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > index b6fda91c8059..58355e1ac7d7 100644
> > > > --- a/drivers/virtio/virtio_ring.c
> > > > +++ b/drivers/virtio/virtio_ring.c
> > > > @@ -220,6 +220,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > > >                                            void (*callback)(struct virtqueue *),
> > > >                                            const char *name);
> > > >   static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
> > > > +static void vring_free(struct virtqueue *_vq);
> > > >
> > > >   /*
> > > >    * Helpers.
> > > > @@ -1117,6 +1118,39 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > >     return vq;
> > > >   }
> > > >
> > > > +static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
> > > > +{
> > > > +   struct vring_virtqueue_split vring_split = {};
> > > > +   struct vring_virtqueue *vq = to_vvq(_vq);
> > > > +   struct virtio_device *vdev = _vq->vdev;
> > > > +   int err;
> > > > +
> > > > +   err = vring_alloc_queue_split(&vring_split, vdev, num,
> > > > +                                 vq->split.vring_align,
> > > > +                                 vq->split.may_reduce_num);
> > > > +   if (err)
> > > > +           goto err;
> > >
> > >
> > > I think we don't need to do anything here?
> >
> > Am I missing something?
>
> I meant it looks to me most of the virtqueue_reinit() is unnecessary.
> We probably only need to reinit avail/used idx there.


In this function, we can indeed remove some code.

>	static void virtqueue_reinit_split(struct vring_virtqueue *vq)
>	{
>		int size, i;
>
>		memset(vq->split.vring.desc, 0, vq->split.queue_size_in_bytes);
>
>		size = sizeof(struct vring_desc_state_split) * vq->split.vring.num;
>		memset(vq->split.desc_state, 0, size);
>
>		size = sizeof(struct vring_desc_extra) * vq->split.vring.num;
>		memset(vq->split.desc_extra, 0, size);

These memsets can be removed, and theoretically it will not cause any
exceptions.

>
>
>
>		for (i = 0; i < vq->split.vring.num - 1; i++)
>			vq->split.desc_extra[i].next = i + 1;

This can also be removed, but we need to record free_head that will been update
inside virtqueue_init().

>
>		virtqueue_init(vq, vq->split.vring.num);

There are some operations in this, which can also be skipped, such as setting
use_dma_api. But I think calling this function directly will be more convenient
for maintenance.


>		virtqueue_vring_init_split(&vq->split, vq);

virtqueue_vring_init_split() is necessary.

>	}

Another method, we can take out all the variables to be reinitialized
separately, and repackage them into a new function. I don’t think it’s worth
it, because this path will only be reached if the memory allocation fails, which
is a rare occurrence. In this case, doing so will increase the cost of
maintenance. If you think so also, I will remove the above memset in the next
version.

Thanks.


>
> Thanks
>
> >
> > >
> > >
> > > > +
> > > > +   err = vring_alloc_state_extra_split(&vring_split);
> > > > +   if (err) {
> > > > +           vring_free_split(&vring_split, vdev);
> > > > +           goto err;
> > >
> > >
> > > I suggest to move vring_free_split() into a dedicated error label.
> >
> > Will change.
> >
> > Thanks.
> >
> >
> > >
> > > Thanks
> > >
> > >
> > > > +   }
> > > > +
> > > > +   vring_free(&vq->vq);
> > > > +
> > > > +   virtqueue_vring_init_split(&vring_split, vq);
> > > > +
> > > > +   virtqueue_init(vq, vring_split.vring.num);
> > > > +   virtqueue_vring_attach_split(vq, &vring_split);
> > > > +
> > > > +   return 0;
> > > > +
> > > > +err:
> > > > +   virtqueue_reinit_split(vq);
> > > > +   return -ENOMEM;
> > > > +}
> > > > +
> > > >
> > > >   /*
> > > >    * Packed ring specific functions - *_packed().
> > >
> >
>
Jason Wang July 28, 2022, 7:42 a.m. UTC | #5
On Thu, Jul 28, 2022 at 3:24 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
>
> On Thu, 28 Jul 2022 10:38:51 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > On Wed, Jul 27, 2022 at 3:44 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > >
> > > On Wed, 27 Jul 2022 11:12:19 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > >
> > > > 在 2022/7/26 15:21, Xuan Zhuo 写道:
> > > > > virtio ring split supports resize.
> > > > >
> > > > > Only after the new vring is successfully allocated based on the new num,
> > > > > we will release the old vring. In any case, an error is returned,
> > > > > indicating that the vring still points to the old vring.
> > > > >
> > > > > In the case of an error, re-initialize(virtqueue_reinit_split()) the
> > > > > virtqueue to ensure that the vring can be used.
> > > > >
> > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > Acked-by: Jason Wang <jasowang@redhat.com>
> > > > > ---
> > > > >   drivers/virtio/virtio_ring.c | 34 ++++++++++++++++++++++++++++++++++
> > > > >   1 file changed, 34 insertions(+)
> > > > >
> > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > index b6fda91c8059..58355e1ac7d7 100644
> > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > @@ -220,6 +220,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > > > >                                            void (*callback)(struct virtqueue *),
> > > > >                                            const char *name);
> > > > >   static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
> > > > > +static void vring_free(struct virtqueue *_vq);
> > > > >
> > > > >   /*
> > > > >    * Helpers.
> > > > > @@ -1117,6 +1118,39 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > >     return vq;
> > > > >   }
> > > > >
> > > > > +static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
> > > > > +{
> > > > > +   struct vring_virtqueue_split vring_split = {};
> > > > > +   struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > +   struct virtio_device *vdev = _vq->vdev;
> > > > > +   int err;
> > > > > +
> > > > > +   err = vring_alloc_queue_split(&vring_split, vdev, num,
> > > > > +                                 vq->split.vring_align,
> > > > > +                                 vq->split.may_reduce_num);
> > > > > +   if (err)
> > > > > +           goto err;
> > > >
> > > >
> > > > I think we don't need to do anything here?
> > >
> > > Am I missing something?
> >
> > I meant it looks to me most of the virtqueue_reinit() is unnecessary.
> > We probably only need to reinit avail/used idx there.
>
>
> In this function, we can indeed remove some code.
>
> >       static void virtqueue_reinit_split(struct vring_virtqueue *vq)
> >       {
> >               int size, i;
> >
> >               memset(vq->split.vring.desc, 0, vq->split.queue_size_in_bytes);
> >
> >               size = sizeof(struct vring_desc_state_split) * vq->split.vring.num;
> >               memset(vq->split.desc_state, 0, size);
> >
> >               size = sizeof(struct vring_desc_extra) * vq->split.vring.num;
> >               memset(vq->split.desc_extra, 0, size);
>
> These memsets can be removed, and theoretically it will not cause any
> exceptions.

Yes, otherwise we have bugs in detach_buf().

>
> >
> >
> >
> >               for (i = 0; i < vq->split.vring.num - 1; i++)
> >                       vq->split.desc_extra[i].next = i + 1;
>
> This can also be removed, but we need to record free_head that will been update
> inside virtqueue_init().

We can simply keep free_head unchanged? Otherwise it's a bug somewhere I guess.


>
> >
> >               virtqueue_init(vq, vq->split.vring.num);
>
> There are some operations in this, which can also be skipped, such as setting
> use_dma_api. But I think calling this function directly will be more convenient
> for maintenance.

I don't see anything that is necessary here.

>
>
> >               virtqueue_vring_init_split(&vq->split, vq);
>
> virtqueue_vring_init_split() is necessary.

Right.

>
> >       }
>
> Another method, we can take out all the variables to be reinitialized
> separately, and repackage them into a new function. I don’t think it’s worth
> it, because this path will only be reached if the memory allocation fails, which
> is a rare occurrence. In this case, doing so will increase the cost of
> maintenance. If you think so also, I will remove the above memset in the next
> version.

I agree.

Thanks

>
> Thanks.
>
>
> >
> > Thanks
> >
> > >
> > > >
> > > >
> > > > > +
> > > > > +   err = vring_alloc_state_extra_split(&vring_split);
> > > > > +   if (err) {
> > > > > +           vring_free_split(&vring_split, vdev);
> > > > > +           goto err;
> > > >
> > > >
> > > > I suggest to move vring_free_split() into a dedicated error label.
> > >
> > > Will change.
> > >
> > > Thanks.
> > >
> > >
> > > >
> > > > Thanks
> > > >
> > > >
> > > > > +   }
> > > > > +
> > > > > +   vring_free(&vq->vq);
> > > > > +
> > > > > +   virtqueue_vring_init_split(&vring_split, vq);
> > > > > +
> > > > > +   virtqueue_init(vq, vring_split.vring.num);
> > > > > +   virtqueue_vring_attach_split(vq, &vring_split);
> > > > > +
> > > > > +   return 0;
> > > > > +
> > > > > +err:
> > > > > +   virtqueue_reinit_split(vq);
> > > > > +   return -ENOMEM;
> > > > > +}
> > > > > +
> > > > >
> > > > >   /*
> > > > >    * Packed ring specific functions - *_packed().
> > > >
> > >
> >
>
Xuan Zhuo July 28, 2022, 8:09 a.m. UTC | #6
On Thu, 28 Jul 2022 15:42:50 +0800, Jason Wang <jasowang@redhat.com> wrote:
> On Thu, Jul 28, 2022 at 3:24 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> >
> > On Thu, 28 Jul 2022 10:38:51 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > On Wed, Jul 27, 2022 at 3:44 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > > >
> > > > On Wed, 27 Jul 2022 11:12:19 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > >
> > > > > 在 2022/7/26 15:21, Xuan Zhuo 写道:
> > > > > > virtio ring split supports resize.
> > > > > >
> > > > > > Only after the new vring is successfully allocated based on the new num,
> > > > > > we will release the old vring. In any case, an error is returned,
> > > > > > indicating that the vring still points to the old vring.
> > > > > >
> > > > > > In the case of an error, re-initialize(virtqueue_reinit_split()) the
> > > > > > virtqueue to ensure that the vring can be used.
> > > > > >
> > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > Acked-by: Jason Wang <jasowang@redhat.com>
> > > > > > ---
> > > > > >   drivers/virtio/virtio_ring.c | 34 ++++++++++++++++++++++++++++++++++
> > > > > >   1 file changed, 34 insertions(+)
> > > > > >
> > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > index b6fda91c8059..58355e1ac7d7 100644
> > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > @@ -220,6 +220,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > > > > >                                            void (*callback)(struct virtqueue *),
> > > > > >                                            const char *name);
> > > > > >   static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
> > > > > > +static void vring_free(struct virtqueue *_vq);
> > > > > >
> > > > > >   /*
> > > > > >    * Helpers.
> > > > > > @@ -1117,6 +1118,39 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > >     return vq;
> > > > > >   }
> > > > > >
> > > > > > +static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
> > > > > > +{
> > > > > > +   struct vring_virtqueue_split vring_split = {};
> > > > > > +   struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > +   struct virtio_device *vdev = _vq->vdev;
> > > > > > +   int err;
> > > > > > +
> > > > > > +   err = vring_alloc_queue_split(&vring_split, vdev, num,
> > > > > > +                                 vq->split.vring_align,
> > > > > > +                                 vq->split.may_reduce_num);
> > > > > > +   if (err)
> > > > > > +           goto err;
> > > > >
> > > > >
> > > > > I think we don't need to do anything here?
> > > >
> > > > Am I missing something?
> > >
> > > I meant it looks to me most of the virtqueue_reinit() is unnecessary.
> > > We probably only need to reinit avail/used idx there.
> >
> >
> > In this function, we can indeed remove some code.
> >
> > >       static void virtqueue_reinit_split(struct vring_virtqueue *vq)
> > >       {
> > >               int size, i;
> > >
> > >               memset(vq->split.vring.desc, 0, vq->split.queue_size_in_bytes);
> > >
> > >               size = sizeof(struct vring_desc_state_split) * vq->split.vring.num;
> > >               memset(vq->split.desc_state, 0, size);
> > >
> > >               size = sizeof(struct vring_desc_extra) * vq->split.vring.num;
> > >               memset(vq->split.desc_extra, 0, size);
> >
> > These memsets can be removed, and theoretically it will not cause any
> > exceptions.
>
> Yes, otherwise we have bugs in detach_buf().
>
> >
> > >
> > >
> > >
> > >               for (i = 0; i < vq->split.vring.num - 1; i++)
> > >                       vq->split.desc_extra[i].next = i + 1;
> >
> > This can also be removed, but we need to record free_head that will been update
> > inside virtqueue_init().
>
> We can simply keep free_head unchanged? Otherwise it's a bug somewhere I guess.
>
>
> >
> > >
> > >               virtqueue_init(vq, vq->split.vring.num);
> >
> > There are some operations in this, which can also be skipped, such as setting
> > use_dma_api. But I think calling this function directly will be more convenient
> > for maintenance.
>
> I don't see anything that is necessary here.

These three are currently inside virtqueue_init()

vq->last_used_idx = 0;
vq->event_triggered = false;
vq->num_added = 0;

Thanks.


>
> >
> >
> > >               virtqueue_vring_init_split(&vq->split, vq);
> >
> > virtqueue_vring_init_split() is necessary.
>
> Right.
>
> >
> > >       }
> >
> > Another method, we can take out all the variables to be reinitialized
> > separately, and repackage them into a new function. I don’t think it’s worth
> > it, because this path will only be reached if the memory allocation fails, which
> > is a rare occurrence. In this case, doing so will increase the cost of
> > maintenance. If you think so also, I will remove the above memset in the next
> > version.
>
> I agree.
>
> Thanks
>
> >
> > Thanks.
> >
> >
> > >
> > > Thanks
> > >
> > > >
> > > > >
> > > > >
> > > > > > +
> > > > > > +   err = vring_alloc_state_extra_split(&vring_split);
> > > > > > +   if (err) {
> > > > > > +           vring_free_split(&vring_split, vdev);
> > > > > > +           goto err;
> > > > >
> > > > >
> > > > > I suggest to move vring_free_split() into a dedicated error label.
> > > >
> > > > Will change.
> > > >
> > > > Thanks.
> > > >
> > > >
> > > > >
> > > > > Thanks
> > > > >
> > > > >
> > > > > > +   }
> > > > > > +
> > > > > > +   vring_free(&vq->vq);
> > > > > > +
> > > > > > +   virtqueue_vring_init_split(&vring_split, vq);
> > > > > > +
> > > > > > +   virtqueue_init(vq, vring_split.vring.num);
> > > > > > +   virtqueue_vring_attach_split(vq, &vring_split);
> > > > > > +
> > > > > > +   return 0;
> > > > > > +
> > > > > > +err:
> > > > > > +   virtqueue_reinit_split(vq);
> > > > > > +   return -ENOMEM;
> > > > > > +}
> > > > > > +
> > > > > >
> > > > > >   /*
> > > > > >    * Packed ring specific functions - *_packed().
> > > > >
> > > >
> > >
> >
>
Jason Wang July 28, 2022, 9:04 a.m. UTC | #7
On Thu, Jul 28, 2022 at 4:18 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
>
> On Thu, 28 Jul 2022 15:42:50 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > On Thu, Jul 28, 2022 at 3:24 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > >
> > > On Thu, 28 Jul 2022 10:38:51 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > On Wed, Jul 27, 2022 at 3:44 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > > > >
> > > > > On Wed, 27 Jul 2022 11:12:19 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > > >
> > > > > > 在 2022/7/26 15:21, Xuan Zhuo 写道:
> > > > > > > virtio ring split supports resize.
> > > > > > >
> > > > > > > Only after the new vring is successfully allocated based on the new num,
> > > > > > > we will release the old vring. In any case, an error is returned,
> > > > > > > indicating that the vring still points to the old vring.
> > > > > > >
> > > > > > > In the case of an error, re-initialize(virtqueue_reinit_split()) the
> > > > > > > virtqueue to ensure that the vring can be used.
> > > > > > >
> > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > Acked-by: Jason Wang <jasowang@redhat.com>
> > > > > > > ---
> > > > > > >   drivers/virtio/virtio_ring.c | 34 ++++++++++++++++++++++++++++++++++
> > > > > > >   1 file changed, 34 insertions(+)
> > > > > > >
> > > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > > index b6fda91c8059..58355e1ac7d7 100644
> > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > @@ -220,6 +220,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > > > > > >                                            void (*callback)(struct virtqueue *),
> > > > > > >                                            const char *name);
> > > > > > >   static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
> > > > > > > +static void vring_free(struct virtqueue *_vq);
> > > > > > >
> > > > > > >   /*
> > > > > > >    * Helpers.
> > > > > > > @@ -1117,6 +1118,39 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > >     return vq;
> > > > > > >   }
> > > > > > >
> > > > > > > +static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
> > > > > > > +{
> > > > > > > +   struct vring_virtqueue_split vring_split = {};
> > > > > > > +   struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > +   struct virtio_device *vdev = _vq->vdev;
> > > > > > > +   int err;
> > > > > > > +
> > > > > > > +   err = vring_alloc_queue_split(&vring_split, vdev, num,
> > > > > > > +                                 vq->split.vring_align,
> > > > > > > +                                 vq->split.may_reduce_num);
> > > > > > > +   if (err)
> > > > > > > +           goto err;
> > > > > >
> > > > > >
> > > > > > I think we don't need to do anything here?
> > > > >
> > > > > Am I missing something?
> > > >
> > > > I meant it looks to me most of the virtqueue_reinit() is unnecessary.
> > > > We probably only need to reinit avail/used idx there.
> > >
> > >
> > > In this function, we can indeed remove some code.
> > >
> > > >       static void virtqueue_reinit_split(struct vring_virtqueue *vq)
> > > >       {
> > > >               int size, i;
> > > >
> > > >               memset(vq->split.vring.desc, 0, vq->split.queue_size_in_bytes);
> > > >
> > > >               size = sizeof(struct vring_desc_state_split) * vq->split.vring.num;
> > > >               memset(vq->split.desc_state, 0, size);
> > > >
> > > >               size = sizeof(struct vring_desc_extra) * vq->split.vring.num;
> > > >               memset(vq->split.desc_extra, 0, size);
> > >
> > > These memsets can be removed, and theoretically it will not cause any
> > > exceptions.
> >
> > Yes, otherwise we have bugs in detach_buf().
> >
> > >
> > > >
> > > >
> > > >
> > > >               for (i = 0; i < vq->split.vring.num - 1; i++)
> > > >                       vq->split.desc_extra[i].next = i + 1;
> > >
> > > This can also be removed, but we need to record free_head that will been update
> > > inside virtqueue_init().
> >
> > We can simply keep free_head unchanged? Otherwise it's a bug somewhere I guess.
> >
> >
> > >
> > > >
> > > >               virtqueue_init(vq, vq->split.vring.num);
> > >
> > > There are some operations in this, which can also be skipped, such as setting
> > > use_dma_api. But I think calling this function directly will be more convenient
> > > for maintenance.
> >
> > I don't see anything that is necessary here.
>
> These three are currently inside virtqueue_init()
>
> vq->last_used_idx = 0;
> vq->event_triggered = false;
> vq->num_added = 0;

Right. Let's keep it there.

(Though it's kind of strange that the last_used_idx is not initialized
at the same place with avail_idx/flags_shadow, we can optimize it on
top).

Thanks

>
> Thanks.
>
>
> >
> > >
> > >
> > > >               virtqueue_vring_init_split(&vq->split, vq);
> > >
> > > virtqueue_vring_init_split() is necessary.
> >
> > Right.
> >
> > >
> > > >       }
> > >
> > > Another method, we can take out all the variables to be reinitialized
> > > separately, and repackage them into a new function. I don’t think it’s worth
> > > it, because this path will only be reached if the memory allocation fails, which
> > > is a rare occurrence. In this case, doing so will increase the cost of
> > > maintenance. If you think so also, I will remove the above memset in the next
> > > version.
> >
> > I agree.
> >
> > Thanks
> >
> > >
> > > Thanks.
> > >
> > >
> > > >
> > > > Thanks
> > > >
> > > > >
> > > > > >
> > > > > >
> > > > > > > +
> > > > > > > +   err = vring_alloc_state_extra_split(&vring_split);
> > > > > > > +   if (err) {
> > > > > > > +           vring_free_split(&vring_split, vdev);
> > > > > > > +           goto err;
> > > > > >
> > > > > >
> > > > > > I suggest to move vring_free_split() into a dedicated error label.
> > > > >
> > > > > Will change.
> > > > >
> > > > > Thanks.
> > > > >
> > > > >
> > > > > >
> > > > > > Thanks
> > > > > >
> > > > > >
> > > > > > > +   }
> > > > > > > +
> > > > > > > +   vring_free(&vq->vq);
> > > > > > > +
> > > > > > > +   virtqueue_vring_init_split(&vring_split, vq);
> > > > > > > +
> > > > > > > +   virtqueue_init(vq, vring_split.vring.num);
> > > > > > > +   virtqueue_vring_attach_split(vq, &vring_split);
> > > > > > > +
> > > > > > > +   return 0;
> > > > > > > +
> > > > > > > +err:
> > > > > > > +   virtqueue_reinit_split(vq);
> > > > > > > +   return -ENOMEM;
> > > > > > > +}
> > > > > > > +
> > > > > > >
> > > > > > >   /*
> > > > > > >    * Packed ring specific functions - *_packed().
> > > > > >
> > > > >
> > > >
> > >
> >
>
Xuan Zhuo July 28, 2022, 9:42 a.m. UTC | #8
On Thu, 28 Jul 2022 17:04:36 +0800, Jason Wang <jasowang@redhat.com> wrote:
> On Thu, Jul 28, 2022 at 4:18 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> >
> > On Thu, 28 Jul 2022 15:42:50 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > On Thu, Jul 28, 2022 at 3:24 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > > >
> > > > On Thu, 28 Jul 2022 10:38:51 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > > On Wed, Jul 27, 2022 at 3:44 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > > > > >
> > > > > > On Wed, 27 Jul 2022 11:12:19 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > > > >
> > > > > > > 在 2022/7/26 15:21, Xuan Zhuo 写道:
> > > > > > > > virtio ring split supports resize.
> > > > > > > >
> > > > > > > > Only after the new vring is successfully allocated based on the new num,
> > > > > > > > we will release the old vring. In any case, an error is returned,
> > > > > > > > indicating that the vring still points to the old vring.
> > > > > > > >
> > > > > > > > In the case of an error, re-initialize(virtqueue_reinit_split()) the
> > > > > > > > virtqueue to ensure that the vring can be used.
> > > > > > > >
> > > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > > Acked-by: Jason Wang <jasowang@redhat.com>
> > > > > > > > ---
> > > > > > > >   drivers/virtio/virtio_ring.c | 34 ++++++++++++++++++++++++++++++++++
> > > > > > > >   1 file changed, 34 insertions(+)
> > > > > > > >
> > > > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > > > index b6fda91c8059..58355e1ac7d7 100644
> > > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > > @@ -220,6 +220,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > > > > > > >                                            void (*callback)(struct virtqueue *),
> > > > > > > >                                            const char *name);
> > > > > > > >   static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
> > > > > > > > +static void vring_free(struct virtqueue *_vq);
> > > > > > > >
> > > > > > > >   /*
> > > > > > > >    * Helpers.
> > > > > > > > @@ -1117,6 +1118,39 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > > >     return vq;
> > > > > > > >   }
> > > > > > > >
> > > > > > > > +static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
> > > > > > > > +{
> > > > > > > > +   struct vring_virtqueue_split vring_split = {};
> > > > > > > > +   struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > > +   struct virtio_device *vdev = _vq->vdev;
> > > > > > > > +   int err;
> > > > > > > > +
> > > > > > > > +   err = vring_alloc_queue_split(&vring_split, vdev, num,
> > > > > > > > +                                 vq->split.vring_align,
> > > > > > > > +                                 vq->split.may_reduce_num);
> > > > > > > > +   if (err)
> > > > > > > > +           goto err;
> > > > > > >
> > > > > > >
> > > > > > > I think we don't need to do anything here?
> > > > > >
> > > > > > Am I missing something?
> > > > >
> > > > > I meant it looks to me most of the virtqueue_reinit() is unnecessary.
> > > > > We probably only need to reinit avail/used idx there.
> > > >
> > > >
> > > > In this function, we can indeed remove some code.
> > > >
> > > > >       static void virtqueue_reinit_split(struct vring_virtqueue *vq)
> > > > >       {
> > > > >               int size, i;
> > > > >
> > > > >               memset(vq->split.vring.desc, 0, vq->split.queue_size_in_bytes);
> > > > >
> > > > >               size = sizeof(struct vring_desc_state_split) * vq->split.vring.num;
> > > > >               memset(vq->split.desc_state, 0, size);
> > > > >
> > > > >               size = sizeof(struct vring_desc_extra) * vq->split.vring.num;
> > > > >               memset(vq->split.desc_extra, 0, size);
> > > >
> > > > These memsets can be removed, and theoretically it will not cause any
> > > > exceptions.
> > >
> > > Yes, otherwise we have bugs in detach_buf().
> > >
> > > >
> > > > >
> > > > >
> > > > >
> > > > >               for (i = 0; i < vq->split.vring.num - 1; i++)
> > > > >                       vq->split.desc_extra[i].next = i + 1;
> > > >
> > > > This can also be removed, but we need to record free_head that will been update
> > > > inside virtqueue_init().
> > >
> > > We can simply keep free_head unchanged? Otherwise it's a bug somewhere I guess.
> > >
> > >
> > > >
> > > > >
> > > > >               virtqueue_init(vq, vq->split.vring.num);
> > > >
> > > > There are some operations in this, which can also be skipped, such as setting
> > > > use_dma_api. But I think calling this function directly will be more convenient
> > > > for maintenance.
> > >
> > > I don't see anything that is necessary here.
> >
> > These three are currently inside virtqueue_init()
> >
> > vq->last_used_idx = 0;
> > vq->event_triggered = false;
> > vq->num_added = 0;
>
> Right. Let's keep it there.
>
> (Though it's kind of strange that the last_used_idx is not initialized
> at the same place with avail_idx/flags_shadow, we can optimize it on
> top).

I put free_head = 0 in the attach function, it is only necessary to set
free_head = 0 when a new state/extra is attached.

In this way, when we call virtqueue_init(), we don't have to worry about
free_head being modified.

Rethinking this problem, I think virtqueue_init() can be rewritten and some
variables that will not change are removed from it. (use_dma_api, event,
weak_barriers)

+static void virtqueue_init(struct vring_virtqueue *vq, u32 num)
+{
+       vq->vq.num_free = num;
+
+       if (vq->packed_ring)
+               vq->last_used_idx = 0 | (1 << VRING_PACKED_EVENT_F_WRAP_CTR);
+       else
+               vq->last_used_idx = 0;
+
+       vq->event_triggered = false;
+       vq->num_added = 0;
+
+#ifdef DEBUG
+       vq->in_use = false;
+       vq->last_add_time_valid = false;
+#endif
+}
+

Thanks.


>
> Thanks
>
> >
> > Thanks.
> >
> >
> > >
> > > >
> > > >
> > > > >               virtqueue_vring_init_split(&vq->split, vq);
> > > >
> > > > virtqueue_vring_init_split() is necessary.
> > >
> > > Right.
> > >
> > > >
> > > > >       }
> > > >
> > > > Another method, we can take out all the variables to be reinitialized
> > > > separately, and repackage them into a new function. I don’t think it’s worth
> > > > it, because this path will only be reached if the memory allocation fails, which
> > > > is a rare occurrence. In this case, doing so will increase the cost of
> > > > maintenance. If you think so also, I will remove the above memset in the next
> > > > version.
> > >
> > > I agree.
> > >
> > > Thanks
> > >
> > > >
> > > > Thanks.
> > > >
> > > >
> > > > >
> > > > > Thanks
> > > > >
> > > > > >
> > > > > > >
> > > > > > >
> > > > > > > > +
> > > > > > > > +   err = vring_alloc_state_extra_split(&vring_split);
> > > > > > > > +   if (err) {
> > > > > > > > +           vring_free_split(&vring_split, vdev);
> > > > > > > > +           goto err;
> > > > > > >
> > > > > > >
> > > > > > > I suggest to move vring_free_split() into a dedicated error label.
> > > > > >
> > > > > > Will change.
> > > > > >
> > > > > > Thanks.
> > > > > >
> > > > > >
> > > > > > >
> > > > > > > Thanks
> > > > > > >
> > > > > > >
> > > > > > > > +   }
> > > > > > > > +
> > > > > > > > +   vring_free(&vq->vq);
> > > > > > > > +
> > > > > > > > +   virtqueue_vring_init_split(&vring_split, vq);
> > > > > > > > +
> > > > > > > > +   virtqueue_init(vq, vring_split.vring.num);
> > > > > > > > +   virtqueue_vring_attach_split(vq, &vring_split);
> > > > > > > > +
> > > > > > > > +   return 0;
> > > > > > > > +
> > > > > > > > +err:
> > > > > > > > +   virtqueue_reinit_split(vq);
> > > > > > > > +   return -ENOMEM;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > >
> > > > > > > >   /*
> > > > > > > >    * Packed ring specific functions - *_packed().
> > > > > > >
> > > > > >
> > > > >
> > > >
> > >
> >
>
Jason Wang Aug. 1, 2022, 4:49 a.m. UTC | #9
On Thu, Jul 28, 2022 at 7:27 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
>
> On Thu, 28 Jul 2022 17:04:36 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > On Thu, Jul 28, 2022 at 4:18 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > >
> > > On Thu, 28 Jul 2022 15:42:50 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > On Thu, Jul 28, 2022 at 3:24 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > > > >
> > > > > On Thu, 28 Jul 2022 10:38:51 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > > > On Wed, Jul 27, 2022 at 3:44 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > > > > > >
> > > > > > > On Wed, 27 Jul 2022 11:12:19 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > > > > >
> > > > > > > > 在 2022/7/26 15:21, Xuan Zhuo 写道:
> > > > > > > > > virtio ring split supports resize.
> > > > > > > > >
> > > > > > > > > Only after the new vring is successfully allocated based on the new num,
> > > > > > > > > we will release the old vring. In any case, an error is returned,
> > > > > > > > > indicating that the vring still points to the old vring.
> > > > > > > > >
> > > > > > > > > In the case of an error, re-initialize(virtqueue_reinit_split()) the
> > > > > > > > > virtqueue to ensure that the vring can be used.
> > > > > > > > >
> > > > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > > > Acked-by: Jason Wang <jasowang@redhat.com>
> > > > > > > > > ---
> > > > > > > > >   drivers/virtio/virtio_ring.c | 34 ++++++++++++++++++++++++++++++++++
> > > > > > > > >   1 file changed, 34 insertions(+)
> > > > > > > > >
> > > > > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > > > > index b6fda91c8059..58355e1ac7d7 100644
> > > > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > > > @@ -220,6 +220,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > > > > > > > >                                            void (*callback)(struct virtqueue *),
> > > > > > > > >                                            const char *name);
> > > > > > > > >   static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
> > > > > > > > > +static void vring_free(struct virtqueue *_vq);
> > > > > > > > >
> > > > > > > > >   /*
> > > > > > > > >    * Helpers.
> > > > > > > > > @@ -1117,6 +1118,39 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > > > >     return vq;
> > > > > > > > >   }
> > > > > > > > >
> > > > > > > > > +static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
> > > > > > > > > +{
> > > > > > > > > +   struct vring_virtqueue_split vring_split = {};
> > > > > > > > > +   struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > > > +   struct virtio_device *vdev = _vq->vdev;
> > > > > > > > > +   int err;
> > > > > > > > > +
> > > > > > > > > +   err = vring_alloc_queue_split(&vring_split, vdev, num,
> > > > > > > > > +                                 vq->split.vring_align,
> > > > > > > > > +                                 vq->split.may_reduce_num);
> > > > > > > > > +   if (err)
> > > > > > > > > +           goto err;
> > > > > > > >
> > > > > > > >
> > > > > > > > I think we don't need to do anything here?
> > > > > > >
> > > > > > > Am I missing something?
> > > > > >
> > > > > > I meant it looks to me most of the virtqueue_reinit() is unnecessary.
> > > > > > We probably only need to reinit avail/used idx there.
> > > > >
> > > > >
> > > > > In this function, we can indeed remove some code.
> > > > >
> > > > > >       static void virtqueue_reinit_split(struct vring_virtqueue *vq)
> > > > > >       {
> > > > > >               int size, i;
> > > > > >
> > > > > >               memset(vq->split.vring.desc, 0, vq->split.queue_size_in_bytes);
> > > > > >
> > > > > >               size = sizeof(struct vring_desc_state_split) * vq->split.vring.num;
> > > > > >               memset(vq->split.desc_state, 0, size);
> > > > > >
> > > > > >               size = sizeof(struct vring_desc_extra) * vq->split.vring.num;
> > > > > >               memset(vq->split.desc_extra, 0, size);
> > > > >
> > > > > These memsets can be removed, and theoretically it will not cause any
> > > > > exceptions.
> > > >
> > > > Yes, otherwise we have bugs in detach_buf().
> > > >
> > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >               for (i = 0; i < vq->split.vring.num - 1; i++)
> > > > > >                       vq->split.desc_extra[i].next = i + 1;
> > > > >
> > > > > This can also be removed, but we need to record free_head that will been update
> > > > > inside virtqueue_init().
> > > >
> > > > We can simply keep free_head unchanged? Otherwise it's a bug somewhere I guess.
> > > >
> > > >
> > > > >
> > > > > >
> > > > > >               virtqueue_init(vq, vq->split.vring.num);
> > > > >
> > > > > There are some operations in this, which can also be skipped, such as setting
> > > > > use_dma_api. But I think calling this function directly will be more convenient
> > > > > for maintenance.
> > > >
> > > > I don't see anything that is necessary here.
> > >
> > > These three are currently inside virtqueue_init()
> > >
> > > vq->last_used_idx = 0;
> > > vq->event_triggered = false;
> > > vq->num_added = 0;
> >
> > Right. Let's keep it there.
> >
> > (Though it's kind of strange that the last_used_idx is not initialized
> > at the same place with avail_idx/flags_shadow, we can optimize it on
> > top).
>
> I put free_head = 0 in the attach function, it is only necessary to set
> free_head = 0 when a new state/extra is attached.

Ok, so I meant I tend to keep it to make this series converge soon :)

We can do optimization on top anyhow.

Thanks

>
> In this way, when we call virtqueue_init(), we don't have to worry about
> free_head being modified.
>
> Rethinking this problem, I think virtqueue_init() can be rewritten and some
> variables that will not change are removed from it. (use_dma_api, event,
> weak_barriers)
>
> +static void virtqueue_init(struct vring_virtqueue *vq, u32 num)
> +{
> +       vq->vq.num_free = num;
> +
> +       if (vq->packed_ring)
> +               vq->last_used_idx = 0 | (1 << VRING_PACKED_EVENT_F_WRAP_CTR);
> +       else
> +               vq->last_used_idx = 0;
> +
> +       vq->event_triggered = false;
> +       vq->num_added = 0;
> +
> +#ifdef DEBUG
> +       vq->in_use = false;
> +       vq->last_add_time_valid = false;
> +#endif
> +}
> +
>
> Thanks.
>
>
> >
> > Thanks
> >
> > >
> > > Thanks.
> > >
> > >
> > > >
> > > > >
> > > > >
> > > > > >               virtqueue_vring_init_split(&vq->split, vq);
> > > > >
> > > > > virtqueue_vring_init_split() is necessary.
> > > >
> > > > Right.
> > > >
> > > > >
> > > > > >       }
> > > > >
> > > > > Another method, we can take out all the variables to be reinitialized
> > > > > separately, and repackage them into a new function. I don’t think it’s worth
> > > > > it, because this path will only be reached if the memory allocation fails, which
> > > > > is a rare occurrence. In this case, doing so will increase the cost of
> > > > > maintenance. If you think so also, I will remove the above memset in the next
> > > > > version.
> > > >
> > > > I agree.
> > > >
> > > > Thanks
> > > >
> > > > >
> > > > > Thanks.
> > > > >
> > > > >
> > > > > >
> > > > > > Thanks
> > > > > >
> > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > > > +
> > > > > > > > > +   err = vring_alloc_state_extra_split(&vring_split);
> > > > > > > > > +   if (err) {
> > > > > > > > > +           vring_free_split(&vring_split, vdev);
> > > > > > > > > +           goto err;
> > > > > > > >
> > > > > > > >
> > > > > > > > I suggest to move vring_free_split() into a dedicated error label.
> > > > > > >
> > > > > > > Will change.
> > > > > > >
> > > > > > > Thanks.
> > > > > > >
> > > > > > >
> > > > > > > >
> > > > > > > > Thanks
> > > > > > > >
> > > > > > > >
> > > > > > > > > +   }
> > > > > > > > > +
> > > > > > > > > +   vring_free(&vq->vq);
> > > > > > > > > +
> > > > > > > > > +   virtqueue_vring_init_split(&vring_split, vq);
> > > > > > > > > +
> > > > > > > > > +   virtqueue_init(vq, vring_split.vring.num);
> > > > > > > > > +   virtqueue_vring_attach_split(vq, &vring_split);
> > > > > > > > > +
> > > > > > > > > +   return 0;
> > > > > > > > > +
> > > > > > > > > +err:
> > > > > > > > > +   virtqueue_reinit_split(vq);
> > > > > > > > > +   return -ENOMEM;
> > > > > > > > > +}
> > > > > > > > > +
> > > > > > > > >
> > > > > > > > >   /*
> > > > > > > > >    * Packed ring specific functions - *_packed().
> > > > > > > >
> > > > > > >
> > > > > >
> > > > >
> > > >
> > >
> >
>
Xuan Zhuo Aug. 1, 2022, 6:11 a.m. UTC | #10
On Mon, 1 Aug 2022 12:49:12 +0800, Jason Wang <jasowang@redhat.com> wrote:
> On Thu, Jul 28, 2022 at 7:27 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> >
> > On Thu, 28 Jul 2022 17:04:36 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > On Thu, Jul 28, 2022 at 4:18 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > > >
> > > > On Thu, 28 Jul 2022 15:42:50 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > > On Thu, Jul 28, 2022 at 3:24 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > > > > >
> > > > > > On Thu, 28 Jul 2022 10:38:51 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > > > > On Wed, Jul 27, 2022 at 3:44 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > > > > > > >
> > > > > > > > On Wed, 27 Jul 2022 11:12:19 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > > > > > >
> > > > > > > > > 在 2022/7/26 15:21, Xuan Zhuo 写道:
> > > > > > > > > > virtio ring split supports resize.
> > > > > > > > > >
> > > > > > > > > > Only after the new vring is successfully allocated based on the new num,
> > > > > > > > > > we will release the old vring. In any case, an error is returned,
> > > > > > > > > > indicating that the vring still points to the old vring.
> > > > > > > > > >
> > > > > > > > > > In the case of an error, re-initialize(virtqueue_reinit_split()) the
> > > > > > > > > > virtqueue to ensure that the vring can be used.
> > > > > > > > > >
> > > > > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > > > > Acked-by: Jason Wang <jasowang@redhat.com>
> > > > > > > > > > ---
> > > > > > > > > >   drivers/virtio/virtio_ring.c | 34 ++++++++++++++++++++++++++++++++++
> > > > > > > > > >   1 file changed, 34 insertions(+)
> > > > > > > > > >
> > > > > > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > > > > > index b6fda91c8059..58355e1ac7d7 100644
> > > > > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > > > > @@ -220,6 +220,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > > > > > > > > >                                            void (*callback)(struct virtqueue *),
> > > > > > > > > >                                            const char *name);
> > > > > > > > > >   static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
> > > > > > > > > > +static void vring_free(struct virtqueue *_vq);
> > > > > > > > > >
> > > > > > > > > >   /*
> > > > > > > > > >    * Helpers.
> > > > > > > > > > @@ -1117,6 +1118,39 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > > > > >     return vq;
> > > > > > > > > >   }
> > > > > > > > > >
> > > > > > > > > > +static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
> > > > > > > > > > +{
> > > > > > > > > > +   struct vring_virtqueue_split vring_split = {};
> > > > > > > > > > +   struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > > > > +   struct virtio_device *vdev = _vq->vdev;
> > > > > > > > > > +   int err;
> > > > > > > > > > +
> > > > > > > > > > +   err = vring_alloc_queue_split(&vring_split, vdev, num,
> > > > > > > > > > +                                 vq->split.vring_align,
> > > > > > > > > > +                                 vq->split.may_reduce_num);
> > > > > > > > > > +   if (err)
> > > > > > > > > > +           goto err;
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > I think we don't need to do anything here?
> > > > > > > >
> > > > > > > > Am I missing something?
> > > > > > >
> > > > > > > I meant it looks to me most of the virtqueue_reinit() is unnecessary.
> > > > > > > We probably only need to reinit avail/used idx there.
> > > > > >
> > > > > >
> > > > > > In this function, we can indeed remove some code.
> > > > > >
> > > > > > >       static void virtqueue_reinit_split(struct vring_virtqueue *vq)
> > > > > > >       {
> > > > > > >               int size, i;
> > > > > > >
> > > > > > >               memset(vq->split.vring.desc, 0, vq->split.queue_size_in_bytes);
> > > > > > >
> > > > > > >               size = sizeof(struct vring_desc_state_split) * vq->split.vring.num;
> > > > > > >               memset(vq->split.desc_state, 0, size);
> > > > > > >
> > > > > > >               size = sizeof(struct vring_desc_extra) * vq->split.vring.num;
> > > > > > >               memset(vq->split.desc_extra, 0, size);
> > > > > >
> > > > > > These memsets can be removed, and theoretically it will not cause any
> > > > > > exceptions.
> > > > >
> > > > > Yes, otherwise we have bugs in detach_buf().
> > > > >
> > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >               for (i = 0; i < vq->split.vring.num - 1; i++)
> > > > > > >                       vq->split.desc_extra[i].next = i + 1;
> > > > > >
> > > > > > This can also be removed, but we need to record free_head that will been update
> > > > > > inside virtqueue_init().
> > > > >
> > > > > We can simply keep free_head unchanged? Otherwise it's a bug somewhere I guess.
> > > > >
> > > > >
> > > > > >
> > > > > > >
> > > > > > >               virtqueue_init(vq, vq->split.vring.num);
> > > > > >
> > > > > > There are some operations in this, which can also be skipped, such as setting
> > > > > > use_dma_api. But I think calling this function directly will be more convenient
> > > > > > for maintenance.
> > > > >
> > > > > I don't see anything that is necessary here.
> > > >
> > > > These three are currently inside virtqueue_init()
> > > >
> > > > vq->last_used_idx = 0;
> > > > vq->event_triggered = false;
> > > > vq->num_added = 0;
> > >
> > > Right. Let's keep it there.
> > >
> > > (Though it's kind of strange that the last_used_idx is not initialized
> > > at the same place with avail_idx/flags_shadow, we can optimize it on
> > > top).
> >
> > I put free_head = 0 in the attach function, it is only necessary to set
> > free_head = 0 when a new state/extra is attached.
>
> Ok, so I meant I tend to keep it to make this series converge soon :)


Ok, other than this, and what we discussed, no more fixes will be added.

Thanks.


>
> We can do optimization on top anyhow.
>
> Thanks
>
> >
> > In this way, when we call virtqueue_init(), we don't have to worry about
> > free_head being modified.
> >
> > Rethinking this problem, I think virtqueue_init() can be rewritten and some
> > variables that will not change are removed from it. (use_dma_api, event,
> > weak_barriers)
> >
> > +static void virtqueue_init(struct vring_virtqueue *vq, u32 num)
> > +{
> > +       vq->vq.num_free = num;
> > +
> > +       if (vq->packed_ring)
> > +               vq->last_used_idx = 0 | (1 << VRING_PACKED_EVENT_F_WRAP_CTR);
> > +       else
> > +               vq->last_used_idx = 0;
> > +
> > +       vq->event_triggered = false;
> > +       vq->num_added = 0;
> > +
> > +#ifdef DEBUG
> > +       vq->in_use = false;
> > +       vq->last_add_time_valid = false;
> > +#endif
> > +}
> > +
> >
> > Thanks.
> >
> >
> > >
> > > Thanks
> > >
> > > >
> > > > Thanks.
> > > >
> > > >
> > > > >
> > > > > >
> > > > > >
> > > > > > >               virtqueue_vring_init_split(&vq->split, vq);
> > > > > >
> > > > > > virtqueue_vring_init_split() is necessary.
> > > > >
> > > > > Right.
> > > > >
> > > > > >
> > > > > > >       }
> > > > > >
> > > > > > Another method, we can take out all the variables to be reinitialized
> > > > > > separately, and repackage them into a new function. I don’t think it’s worth
> > > > > > it, because this path will only be reached if the memory allocation fails, which
> > > > > > is a rare occurrence. In this case, doing so will increase the cost of
> > > > > > maintenance. If you think so also, I will remove the above memset in the next
> > > > > > version.
> > > > >
> > > > > I agree.
> > > > >
> > > > > Thanks
> > > > >
> > > > > >
> > > > > > Thanks.
> > > > > >
> > > > > >
> > > > > > >
> > > > > > > Thanks
> > > > > > >
> > > > > > > >
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > +
> > > > > > > > > > +   err = vring_alloc_state_extra_split(&vring_split);
> > > > > > > > > > +   if (err) {
> > > > > > > > > > +           vring_free_split(&vring_split, vdev);
> > > > > > > > > > +           goto err;
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > I suggest to move vring_free_split() into a dedicated error label.
> > > > > > > >
> > > > > > > > Will change.
> > > > > > > >
> > > > > > > > Thanks.
> > > > > > > >
> > > > > > > >
> > > > > > > > >
> > > > > > > > > Thanks
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > +   }
> > > > > > > > > > +
> > > > > > > > > > +   vring_free(&vq->vq);
> > > > > > > > > > +
> > > > > > > > > > +   virtqueue_vring_init_split(&vring_split, vq);
> > > > > > > > > > +
> > > > > > > > > > +   virtqueue_init(vq, vring_split.vring.num);
> > > > > > > > > > +   virtqueue_vring_attach_split(vq, &vring_split);
> > > > > > > > > > +
> > > > > > > > > > +   return 0;
> > > > > > > > > > +
> > > > > > > > > > +err:
> > > > > > > > > > +   virtqueue_reinit_split(vq);
> > > > > > > > > > +   return -ENOMEM;
> > > > > > > > > > +}
> > > > > > > > > > +
> > > > > > > > > >
> > > > > > > > > >   /*
> > > > > > > > > >    * Packed ring specific functions - *_packed().
> > > > > > > > >
> > > > > > > >
> > > > > > >
> > > > > >
> > > > >
> > > >
> > >
> >
>
Jason Wang Aug. 1, 2022, 6:27 a.m. UTC | #11
On Mon, Aug 1, 2022 at 2:13 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
>
> On Mon, 1 Aug 2022 12:49:12 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > On Thu, Jul 28, 2022 at 7:27 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > >
> > > On Thu, 28 Jul 2022 17:04:36 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > On Thu, Jul 28, 2022 at 4:18 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > > > >
> > > > > On Thu, 28 Jul 2022 15:42:50 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > > > On Thu, Jul 28, 2022 at 3:24 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > > > > > >
> > > > > > > On Thu, 28 Jul 2022 10:38:51 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > > > > > On Wed, Jul 27, 2022 at 3:44 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote:
> > > > > > > > >
> > > > > > > > > On Wed, 27 Jul 2022 11:12:19 +0800, Jason Wang <jasowang@redhat.com> wrote:
> > > > > > > > > >
> > > > > > > > > > 在 2022/7/26 15:21, Xuan Zhuo 写道:
> > > > > > > > > > > virtio ring split supports resize.
> > > > > > > > > > >
> > > > > > > > > > > Only after the new vring is successfully allocated based on the new num,
> > > > > > > > > > > we will release the old vring. In any case, an error is returned,
> > > > > > > > > > > indicating that the vring still points to the old vring.
> > > > > > > > > > >
> > > > > > > > > > > In the case of an error, re-initialize(virtqueue_reinit_split()) the
> > > > > > > > > > > virtqueue to ensure that the vring can be used.
> > > > > > > > > > >
> > > > > > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > > > > > Acked-by: Jason Wang <jasowang@redhat.com>
> > > > > > > > > > > ---
> > > > > > > > > > >   drivers/virtio/virtio_ring.c | 34 ++++++++++++++++++++++++++++++++++
> > > > > > > > > > >   1 file changed, 34 insertions(+)
> > > > > > > > > > >
> > > > > > > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > > > > > > index b6fda91c8059..58355e1ac7d7 100644
> > > > > > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > > > > > @@ -220,6 +220,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > > > > > > > > > >                                            void (*callback)(struct virtqueue *),
> > > > > > > > > > >                                            const char *name);
> > > > > > > > > > >   static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
> > > > > > > > > > > +static void vring_free(struct virtqueue *_vq);
> > > > > > > > > > >
> > > > > > > > > > >   /*
> > > > > > > > > > >    * Helpers.
> > > > > > > > > > > @@ -1117,6 +1118,39 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > > > > > >     return vq;
> > > > > > > > > > >   }
> > > > > > > > > > >
> > > > > > > > > > > +static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
> > > > > > > > > > > +{
> > > > > > > > > > > +   struct vring_virtqueue_split vring_split = {};
> > > > > > > > > > > +   struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > > > > > +   struct virtio_device *vdev = _vq->vdev;
> > > > > > > > > > > +   int err;
> > > > > > > > > > > +
> > > > > > > > > > > +   err = vring_alloc_queue_split(&vring_split, vdev, num,
> > > > > > > > > > > +                                 vq->split.vring_align,
> > > > > > > > > > > +                                 vq->split.may_reduce_num);
> > > > > > > > > > > +   if (err)
> > > > > > > > > > > +           goto err;
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > I think we don't need to do anything here?
> > > > > > > > >
> > > > > > > > > Am I missing something?
> > > > > > > >
> > > > > > > > I meant it looks to me most of the virtqueue_reinit() is unnecessary.
> > > > > > > > We probably only need to reinit avail/used idx there.
> > > > > > >
> > > > > > >
> > > > > > > In this function, we can indeed remove some code.
> > > > > > >
> > > > > > > >       static void virtqueue_reinit_split(struct vring_virtqueue *vq)
> > > > > > > >       {
> > > > > > > >               int size, i;
> > > > > > > >
> > > > > > > >               memset(vq->split.vring.desc, 0, vq->split.queue_size_in_bytes);
> > > > > > > >
> > > > > > > >               size = sizeof(struct vring_desc_state_split) * vq->split.vring.num;
> > > > > > > >               memset(vq->split.desc_state, 0, size);
> > > > > > > >
> > > > > > > >               size = sizeof(struct vring_desc_extra) * vq->split.vring.num;
> > > > > > > >               memset(vq->split.desc_extra, 0, size);
> > > > > > >
> > > > > > > These memsets can be removed, and theoretically it will not cause any
> > > > > > > exceptions.
> > > > > >
> > > > > > Yes, otherwise we have bugs in detach_buf().
> > > > > >
> > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > >               for (i = 0; i < vq->split.vring.num - 1; i++)
> > > > > > > >                       vq->split.desc_extra[i].next = i + 1;
> > > > > > >
> > > > > > > This can also be removed, but we need to record free_head that will been update
> > > > > > > inside virtqueue_init().
> > > > > >
> > > > > > We can simply keep free_head unchanged? Otherwise it's a bug somewhere I guess.
> > > > > >
> > > > > >
> > > > > > >
> > > > > > > >
> > > > > > > >               virtqueue_init(vq, vq->split.vring.num);
> > > > > > >
> > > > > > > There are some operations in this, which can also be skipped, such as setting
> > > > > > > use_dma_api. But I think calling this function directly will be more convenient
> > > > > > > for maintenance.
> > > > > >
> > > > > > I don't see anything that is necessary here.
> > > > >
> > > > > These three are currently inside virtqueue_init()
> > > > >
> > > > > vq->last_used_idx = 0;
> > > > > vq->event_triggered = false;
> > > > > vq->num_added = 0;
> > > >
> > > > Right. Let's keep it there.
> > > >
> > > > (Though it's kind of strange that the last_used_idx is not initialized
> > > > at the same place with avail_idx/flags_shadow, we can optimize it on
> > > > top).
> > >
> > > I put free_head = 0 in the attach function, it is only necessary to set
> > > free_head = 0 when a new state/extra is attached.
> >
> > Ok, so I meant I tend to keep it to make this series converge soon :)
>
>
> Ok, other than this, and what we discussed, no more fixes will be added.
>
> Thanks.

Ack

Thanks

>
>
> >
> > We can do optimization on top anyhow.
> >
> > Thanks
> >
> > >
> > > In this way, when we call virtqueue_init(), we don't have to worry about
> > > free_head being modified.
> > >
> > > Rethinking this problem, I think virtqueue_init() can be rewritten and some
> > > variables that will not change are removed from it. (use_dma_api, event,
> > > weak_barriers)
> > >
> > > +static void virtqueue_init(struct vring_virtqueue *vq, u32 num)
> > > +{
> > > +       vq->vq.num_free = num;
> > > +
> > > +       if (vq->packed_ring)
> > > +               vq->last_used_idx = 0 | (1 << VRING_PACKED_EVENT_F_WRAP_CTR);
> > > +       else
> > > +               vq->last_used_idx = 0;
> > > +
> > > +       vq->event_triggered = false;
> > > +       vq->num_added = 0;
> > > +
> > > +#ifdef DEBUG
> > > +       vq->in_use = false;
> > > +       vq->last_add_time_valid = false;
> > > +#endif
> > > +}
> > > +
> > >
> > > Thanks.
> > >
> > >
> > > >
> > > > Thanks
> > > >
> > > > >
> > > > > Thanks.
> > > > >
> > > > >
> > > > > >
> > > > > > >
> > > > > > >
> > > > > > > >               virtqueue_vring_init_split(&vq->split, vq);
> > > > > > >
> > > > > > > virtqueue_vring_init_split() is necessary.
> > > > > >
> > > > > > Right.
> > > > > >
> > > > > > >
> > > > > > > >       }
> > > > > > >
> > > > > > > Another method, we can take out all the variables to be reinitialized
> > > > > > > separately, and repackage them into a new function. I don’t think it’s worth
> > > > > > > it, because this path will only be reached if the memory allocation fails, which
> > > > > > > is a rare occurrence. In this case, doing so will increase the cost of
> > > > > > > maintenance. If you think so also, I will remove the above memset in the next
> > > > > > > version.
> > > > > >
> > > > > > I agree.
> > > > > >
> > > > > > Thanks
> > > > > >
> > > > > > >
> > > > > > > Thanks.
> > > > > > >
> > > > > > >
> > > > > > > >
> > > > > > > > Thanks
> > > > > > > >
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > +
> > > > > > > > > > > +   err = vring_alloc_state_extra_split(&vring_split);
> > > > > > > > > > > +   if (err) {
> > > > > > > > > > > +           vring_free_split(&vring_split, vdev);
> > > > > > > > > > > +           goto err;
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > I suggest to move vring_free_split() into a dedicated error label.
> > > > > > > > >
> > > > > > > > > Will change.
> > > > > > > > >
> > > > > > > > > Thanks.
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > Thanks
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > +   }
> > > > > > > > > > > +
> > > > > > > > > > > +   vring_free(&vq->vq);
> > > > > > > > > > > +
> > > > > > > > > > > +   virtqueue_vring_init_split(&vring_split, vq);
> > > > > > > > > > > +
> > > > > > > > > > > +   virtqueue_init(vq, vring_split.vring.num);
> > > > > > > > > > > +   virtqueue_vring_attach_split(vq, &vring_split);
> > > > > > > > > > > +
> > > > > > > > > > > +   return 0;
> > > > > > > > > > > +
> > > > > > > > > > > +err:
> > > > > > > > > > > +   virtqueue_reinit_split(vq);
> > > > > > > > > > > +   return -ENOMEM;
> > > > > > > > > > > +}
> > > > > > > > > > > +
> > > > > > > > > > >
> > > > > > > > > > >   /*
> > > > > > > > > > >    * Packed ring specific functions - *_packed().
> > > > > > > > > >
> > > > > > > > >
> > > > > > > >
> > > > > > >
> > > > > >
> > > > >
> > > >
> > >
> >
>
diff mbox series

Patch

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index b6fda91c8059..58355e1ac7d7 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -220,6 +220,7 @@  static struct virtqueue *__vring_new_virtqueue(unsigned int index,
 					       void (*callback)(struct virtqueue *),
 					       const char *name);
 static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
+static void vring_free(struct virtqueue *_vq);
 
 /*
  * Helpers.
@@ -1117,6 +1118,39 @@  static struct virtqueue *vring_create_virtqueue_split(
 	return vq;
 }
 
+static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
+{
+	struct vring_virtqueue_split vring_split = {};
+	struct vring_virtqueue *vq = to_vvq(_vq);
+	struct virtio_device *vdev = _vq->vdev;
+	int err;
+
+	err = vring_alloc_queue_split(&vring_split, vdev, num,
+				      vq->split.vring_align,
+				      vq->split.may_reduce_num);
+	if (err)
+		goto err;
+
+	err = vring_alloc_state_extra_split(&vring_split);
+	if (err) {
+		vring_free_split(&vring_split, vdev);
+		goto err;
+	}
+
+	vring_free(&vq->vq);
+
+	virtqueue_vring_init_split(&vring_split, vq);
+
+	virtqueue_init(vq, vring_split.vring.num);
+	virtqueue_vring_attach_split(vq, &vring_split);
+
+	return 0;
+
+err:
+	virtqueue_reinit_split(vq);
+	return -ENOMEM;
+}
+
 
 /*
  * Packed ring specific functions - *_packed().