Re: [PATCH v2 3/8] vhost-scsi: Add better resource allocation failure handling

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

 




On 12/3/24 11:15 AM, Mike Christie wrote:
> If we can't allocate mem to map in data for a request or can't find
> a tag for a command, we currently drop the command. This leads to the
> error handler running to clean it up. Instead of dropping the command
> this has us return an error telling the initiator that it queued more
> commands than we can handle. The initiator will then reduce how many
> commands it will send us and retry later.
> 
> Signed-off-by: Mike Christie <michael.christie@xxxxxxxxxx>
> ---
>  drivers/vhost/scsi.c | 28 +++++++++++++++++++++++++---
>  1 file changed, 25 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
> index 99e008219e6c..ad7c778632f9 100644
> --- a/drivers/vhost/scsi.c
> +++ b/drivers/vhost/scsi.c
> @@ -629,7 +629,7 @@ vhost_scsi_get_cmd(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg,
>  
>  	tag = sbitmap_get(&svq->scsi_tags);
>  	if (tag < 0) {
> -		pr_err("Unable to obtain tag for vhost_scsi_cmd\n");
> +		pr_warn_once("Guest sent too many cmds. Returning TASK_SET_FULL.\n");
>  		return ERR_PTR(-ENOMEM);
>  	}
>  
> @@ -928,6 +928,24 @@ static void vhost_scsi_target_queue_cmd(struct vhost_scsi_cmd *cmd)
>  	target_submit(se_cmd);
>  }
>  
> +static void
> +vhost_scsi_send_status(struct vhost_scsi *vs, struct vhost_virtqueue *vq,
> +		       int head, unsigned int out, u8 status)
> +{
> +	struct virtio_scsi_cmd_resp __user *resp;
> +	struct virtio_scsi_cmd_resp rsp;
> +	int ret;
> +
> +	memset(&rsp, 0, sizeof(rsp));
> +	rsp.status = status;
> +	resp = vq->iov[out].iov_base;
> +	ret = __copy_to_user(resp, &rsp, sizeof(rsp));
> +	if (!ret)
> +		vhost_add_used_and_signal(&vs->dev, vq, head, 0);
> +	else
> +		pr_err("Faulted on virtio_scsi_cmd_resp\n");
> +}
> +

When I re-base my patchset on top of the most recent change ...

https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git/log/?h=linux-next

... I notice this is the same issue as what the patch is going to fix:

[PATCH 9/9] vhost-scsi: Fix vhost_scsi_send_bad_target()

https://lore.kernel.org/all/20250207184212.20831-10-dongli.zhang@xxxxxxxxxx/

We cannot assume the response takes only one iovec.

We may need something like (not tested):

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 9a4cbdc607fa..dd9614464732 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -994,18 +994,25 @@ static void vhost_scsi_target_queue_cmd(struct
vhost_scsi_nexus *nexus,

 static void
 vhost_scsi_send_status(struct vhost_scsi *vs, struct vhost_virtqueue *vq,
-                      int head, unsigned int out, u8 status)
+                      struct vhost_scsi_ctx *vc, u8 status)
 {
-       struct virtio_scsi_cmd_resp __user *resp;
-       struct virtio_scsi_cmd_resp rsp;
+       struct virtio_scsi_cmd_resp resp;
+       struct iov_iter iov_iter;
+       size_t resp_size;
        int ret;

-       memset(&rsp, 0, sizeof(rsp));
-       rsp.status = status;
-       resp = vq->iov[out].iov_base;
-       ret = __copy_to_user(resp, &rsp, sizeof(rsp));
-       if (!ret)
-               vhost_add_used_and_signal(&vs->dev, vq, head, 0);
+       resp_size = sizeof(struct virtio_scsi_cmd_resp);
+
+       memset(&resp, 0, sizeof(resp));
+       resp.status = status;
+
+       iov_iter_init(&iov_iter, ITER_DEST, &vq->iov[vc->out], vc->in,
+                     resp_size);
+
+       ret = copy_to_iter(&resp, resp_size, &iov_iter);
+
+       if (likely(ret == resp_size))
+               vhost_add_used_and_signal(&vs->dev, vq, vc->head, 0);
        else
                pr_err("Faulted on virtio_scsi_cmd_resp\n");
 }
@@ -1392,7 +1399,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct
vhost_virtqueue *vq)
                else if (ret == -EIO)
                        vhost_scsi_send_bad_target(vs, vq, vc.head, vc.out);
                else if (ret == -ENOMEM)
-                       vhost_scsi_send_status(vs, vq, vc.head, vc.out,
+                       vhost_scsi_send_status(vs, vq, &vc,
                                               SAM_STAT_TASK_SET_FULL);
        } while (likely(!vhost_exceeds_weight(vq, ++c, 0)));
 out:


I will add it when to re-base my patchset.

Thank you very much!

Dongli Zhang




[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