SCSI fixes on 20260125

only one core change, the rest are drivers. The core change reorders
 some state operations in the error handler to try to prevent missed
 wake ups of the error handler (which can halt error processing and
 effectively freeze the entire system).
 
 Signed-off-by: James E.J. Bottomley <James.Bottomley@HansenPartnership.com>
 -----BEGIN PGP SIGNATURE-----
 
 iLgEABMIAGAWIQTnYEDbdso9F2cI+arnQslM7pishQUCaXZkyRsUgAAAAAAEAA5t
 YW51MiwyLjUrMS4xMSwyLDImHGphbWVzLmJvdHRvbWxleUBoYW5zZW5wYXJ0bmVy
 c2hpcC5jb20ACgkQ50LJTO6YrIWQoAD9GhKN9FMdjxlLtb7cuy3GJq41QnOaTJ7K
 ze12EznP6RgA/RODy+aKgL9+NQXOLBycfDjUzzYDzA5BTUtR2dg4Zt5E
 =eS8f
 -----END PGP SIGNATURE-----

Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI fixes from James Bottomley:
 "Only one core change, the rest are drivers.

  The core change reorders some state operations in the error handler to
  try to prevent missed wake ups of the error handler (which can halt
  error processing and effectively freeze the entire system)"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: qla2xxx: Sanitize payload size to prevent member overflow
  scsi: target: iscsi: Fix use-after-free in iscsit_dec_session_usage_count()
  scsi: target: iscsi: Fix use-after-free in iscsit_dec_conn_usage_count()
  scsi: core: Wake up the error handler when final completions race against each other
  scsi: storvsc: Process unsupported MODE_SENSE_10
  scsi: xen: scsiback: Fix potential memory leak in scsiback_remove()
This commit is contained in:
Linus Torvalds 2026-01-25 12:06:15 -08:00
commit 0237777974
6 changed files with 36 additions and 4 deletions

View file

@ -878,6 +878,9 @@ qla27xx_copy_multiple_pkt(struct scsi_qla_host *vha, void **pkt,
payload_size = sizeof(purex->els_frame_payload);
}
if (total_bytes > sizeof(item->iocb.iocb))
total_bytes = sizeof(item->iocb.iocb);
pending_bytes = total_bytes;
no_bytes = (pending_bytes > payload_size) ? payload_size :
pending_bytes;
@ -1163,6 +1166,10 @@ qla27xx_copy_fpin_pkt(struct scsi_qla_host *vha, void **pkt,
total_bytes = (le16_to_cpu(purex->frame_size) & 0x0FFF)
- PURX_ELS_HEADER_SIZE;
if (total_bytes > sizeof(item->iocb.iocb))
total_bytes = sizeof(item->iocb.iocb);
pending_bytes = total_bytes;
entry_count = entry_count_remaining = purex->entry_count;
no_bytes = (pending_bytes > sizeof(purex->els_frame_payload)) ?

View file

@ -282,11 +282,20 @@ static void scsi_eh_inc_host_failed(struct rcu_head *head)
{
struct scsi_cmnd *scmd = container_of(head, typeof(*scmd), rcu);
struct Scsi_Host *shost = scmd->device->host;
unsigned int busy = scsi_host_busy(shost);
unsigned int busy;
unsigned long flags;
spin_lock_irqsave(shost->host_lock, flags);
shost->host_failed++;
spin_unlock_irqrestore(shost->host_lock, flags);
/*
* The counting of busy requests needs to occur after adding to
* host_failed or after the lock acquire for adding to host_failed
* to prevent a race with host unbusy and missing an eh wakeup.
*/
busy = scsi_host_busy(shost);
spin_lock_irqsave(shost->host_lock, flags);
scsi_eh_wakeup(shost, busy);
spin_unlock_irqrestore(shost->host_lock, flags);
}

View file

@ -376,6 +376,14 @@ static void scsi_dec_host_busy(struct Scsi_Host *shost, struct scsi_cmnd *cmd)
rcu_read_lock();
__clear_bit(SCMD_STATE_INFLIGHT, &cmd->state);
if (unlikely(scsi_host_in_recovery(shost))) {
/*
* Ensure the clear of SCMD_STATE_INFLIGHT is visible to
* other CPUs before counting busy requests. Otherwise,
* reordering can cause CPUs to race and miss an eh wakeup
* when no CPU sees all busy requests as done or timed out.
*/
smp_mb();
unsigned int busy = scsi_host_busy(shost);
spin_lock_irqsave(shost->host_lock, flags);

View file

@ -1144,7 +1144,7 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device,
* The current SCSI handling on the host side does
* not correctly handle:
* INQUIRY command with page code parameter set to 0x80
* MODE_SENSE command with cmd[2] == 0x1c
* MODE_SENSE and MODE_SENSE_10 command with cmd[2] == 0x1c
* MAINTENANCE_IN is not supported by HyperV FC passthrough
*
* Setup srb and scsi status so this won't be fatal.
@ -1154,6 +1154,7 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device,
if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) ||
(stor_pkt->vm_srb.cdb[0] == MODE_SENSE) ||
(stor_pkt->vm_srb.cdb[0] == MODE_SENSE_10) ||
(stor_pkt->vm_srb.cdb[0] == MAINTENANCE_IN &&
hv_dev_is_fc(device))) {
vstor_packet->vm_srb.scsi_status = 0;

View file

@ -741,8 +741,11 @@ void iscsit_dec_session_usage_count(struct iscsit_session *sess)
spin_lock_bh(&sess->session_usage_lock);
sess->session_usage_count--;
if (!sess->session_usage_count && sess->session_waiting_on_uc)
if (!sess->session_usage_count && sess->session_waiting_on_uc) {
spin_unlock_bh(&sess->session_usage_lock);
complete(&sess->session_waiting_on_uc_comp);
return;
}
spin_unlock_bh(&sess->session_usage_lock);
}
@ -810,8 +813,11 @@ void iscsit_dec_conn_usage_count(struct iscsit_conn *conn)
spin_lock_bh(&conn->conn_usage_lock);
conn->conn_usage_count--;
if (!conn->conn_usage_count && conn->conn_waiting_on_uc)
if (!conn->conn_usage_count && conn->conn_waiting_on_uc) {
spin_unlock_bh(&conn->conn_usage_lock);
complete(&conn->conn_waiting_on_uc_comp);
return;
}
spin_unlock_bh(&conn->conn_usage_lock);
}

View file

@ -1262,6 +1262,7 @@ static void scsiback_remove(struct xenbus_device *dev)
gnttab_page_cache_shrink(&info->free_pages, 0);
dev_set_drvdata(&dev->dev, NULL);
kfree(info);
}
static int scsiback_probe(struct xenbus_device *dev,