mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 15:03:53 +02:00
scsi: core: Enforce unlimited max_segment_size when virt_boundary_mask is set
The virt_boundary_mask limit requires an unlimited max_segment_size for bio splitting to not corrupt data. Historically, the block layer tried to validate this, although the check was half-hearted until the addition of the atomic queue limits API. The full blown check then triggered issues with stacked devices incorrectly inheriting limits such as the virt boundary and got disabled in commitb561ea56a2
("block: allow device to have both virt_boundary_mask and max segment size") instead of fixing the issue properly. Ensure that the SCSI mid layer doesn't set the default low max_segment_size limit for this case, and check for invalid max_segment_size values in the host template, similar to the original block layer check given that SCSI devices can't be stacked. This fixes reported data corruption on storvsc, although as far as I can tell storvsc always failed to properly set the max_segment_size limit as the SCSI APIs historically applied that when setting up the host, while storvsc only set the virt_boundary_mask when configuring the scsi_device. Fixes:81988a0e6b
("storvsc: get rid of bounce buffer") Fixes:b561ea56a2
("block: allow device to have both virt_boundary_mask and max segment size") Reported-by: Ming Lei <ming.lei@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Link: https://lore.kernel.org/r/20250624125233.219635-3-hch@lst.de Reviewed-by: John Garry <john.g.garry@oracle.com> Reviewed-by: Ming Lei <ming.lei@redhat.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
844c6a160e
commit
4937e604ca
|
@ -473,10 +473,17 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv
|
|||
else
|
||||
shost->max_sectors = SCSI_DEFAULT_MAX_SECTORS;
|
||||
|
||||
if (sht->max_segment_size)
|
||||
shost->max_segment_size = sht->max_segment_size;
|
||||
else
|
||||
shost->max_segment_size = BLK_MAX_SEGMENT_SIZE;
|
||||
shost->virt_boundary_mask = sht->virt_boundary_mask;
|
||||
if (shost->virt_boundary_mask) {
|
||||
WARN_ON_ONCE(sht->max_segment_size &&
|
||||
sht->max_segment_size != UINT_MAX);
|
||||
shost->max_segment_size = UINT_MAX;
|
||||
} else {
|
||||
if (sht->max_segment_size)
|
||||
shost->max_segment_size = sht->max_segment_size;
|
||||
else
|
||||
shost->max_segment_size = BLK_MAX_SEGMENT_SIZE;
|
||||
}
|
||||
|
||||
/* 32-byte (dword) is a common minimum for HBAs. */
|
||||
if (sht->dma_alignment)
|
||||
|
@ -492,9 +499,6 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv
|
|||
else
|
||||
shost->dma_boundary = 0xffffffff;
|
||||
|
||||
if (sht->virt_boundary_mask)
|
||||
shost->virt_boundary_mask = sht->virt_boundary_mask;
|
||||
|
||||
device_initialize(&shost->shost_gendev);
|
||||
dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
|
||||
shost->shost_gendev.bus = &scsi_bus_type;
|
||||
|
|
Loading…
Reference in New Issue
Block a user