On Thu, Jul 23, 2026 at 11:44 PM Jia Jia <[email protected]> wrote:
>
> vhost_scsi_setup_vq_cmds() runs from VHOST_SCSI_SET_ENDPOINT and allocates
> each command's protection scatterlist array (prot_sgl) according to the
> acknowledged VIRTIO_SCSI_F_T10_PI bit.  The command pools are not rebuilt
> when VHOST_SET_FEATURES changes that bit later.
>
> Although virtio feature bits must not change after feature negotiation,
> vhost_scsi_set_features() currently accepts such a request after the
> endpoint is active and updates acked_features.  Enabling T10-PI after
> endpoint setup therefore leaves prot_sgl NULL while the I/O path follows
> the new feature bit.
>
> For a 129-page protection payload, vhost_scsi_mapal() passes the missing
> first chunk to sg_alloc_table_chained():
>
>   sg_alloc_table_chained(table, 129, first_chunk=NULL,
>                          nents_first_chunk=inline_sg_cnt)
>
> sg_pool_index() then hits:
>
>   BUG_ON(nents > SG_CHUNK_SIZE);   /* 129 > 128 */
>
> The kernel reported the following call trace and register state:
>
>   Call Trace:
>    <TASK>
>    ? __sg_alloc_table+0x1d8/0x250
>    ? __pfx_vhost_run_work_list+0x10/0x10 [vhost]
>    sg_alloc_table_chained+0x59/0xf0
>    ? __pfx_sg_pool_alloc+0x10/0x10
>    ? vhost_scsi_calc_sgls.constprop.0+0x43/0x60 [vhost_scsi]
>    vhost_scsi_handle_vq+0xf02/0x1700 [vhost_scsi]
>    ? __pfx_vhost_scsi_handle_vq+0x10/0x10 [vhost_scsi]
>    vhost_scsi_handle_kick+0x37/0x50 [vhost_scsi]
>    vhost_run_work_list+0x8e/0xd0 [vhost]
>    vhost_task_fn+0xe1/0x210
>    ret_from_fork+0x348/0x540
>    </TASK>
>
>   RIP: 0010:0x4
>   CR2 = 0x4
>   RSP: 0018:ffffc90000dbf940 EFLAGS: 00010202
>   RAX: ffffffff82396810 RBX: ffff88811dc28b80 RCX: 0000000000000000
>   RDX: 0000000000000000 RSI: 0000000000000820 RDI: 0000000000000081
>
> VHOST_F_LOG_ALL is a vhost-specific runtime feature and remains the only
> exception.
>
> Reject changes to any feature other than VHOST_F_LOG_ALL while the
> endpoint is active.  This preserves the existing runtime log toggle while
> preventing feature-dependent command resources and data-path state from
> becoming inconsistent.  Userspace must clear the endpoint before changing
> any other negotiated feature and set the endpoint up again afterward.
>
> Fixes: bf2d650391be ("vhost-scsi: Allocate T10 PI structs only when enabled")
> Signed-off-by: Jia Jia <[email protected]>
> ---
> Changes in v2:
> - Reject changes to every feature except VHOST_F_LOG_ALL after endpoint
>   setup, following review feedback.
> - Keep the existing runtime VHOST_F_LOG_ALL cleanup path.
>  drivers/vhost/scsi.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
> index 9a1253b9d8c5..000000000000 100644
> --- a/drivers/vhost/scsi.c
> +++ b/drivers/vhost/scsi.c
> @@ -2219,6 +2219,7 @@ static int vhost_scsi_set_features(struct vhost_scsi 
> *vs, u64 features)
>  {
>         struct vhost_virtqueue *vq;
>         bool is_log, was_log;
> +       u64 old_features;
>         int i;
>
>         if (features & ~VHOST_SCSI_FEATURES)
> @@ -2234,6 +2235,14 @@ static int vhost_scsi_set_features(struct vhost_scsi 
> *vs, u64 features)
>         if (!vs->dev.nvqs)
>                 goto out;
>
> +       old_features = vs->vqs[0].vq.acked_features;
> +       if (vs->vs_tpg &&
> +           ((features ^ old_features) &
> +            ~(1ULL << VHOST_F_LOG_ALL))) {
> +               mutex_unlock(&vs->dev.mutex);
> +               return -EBUSY;
> +       }
> +

Reviewed-by: Stefan Hajnoczi <[email protected]>

Reply via email to