scsi: sd: Update DIX config every time sd_revalidate_disk() is called
If a controller has DIX is enabled and an attached disk is formatted using a protection type supported by the controller, a block integrity profile is registered to enable protected transfers. If the disk is subsequently reformatted to disable PI, and the controller does not support DIX Type 0, this can lead to failures such as this: [142829.032340] hisi_sas_v3_hw 0000:b4:04.0: erroneous completion iptt=2375 task=00000000bea0970c dev id=5 direct-attached phy4 addr=51c20dbaf642a000 CQ hdr: 0x1023 0x50947 0x0 0x20000 Error info: 0x0 0x0 0x4 0x0 [142829.073883] sas: Enter sas_scsi_recover_host busy: 1 failed: 1 [142829.079783] sas: sas_scsi_find_task: aborting task 0x00000000bea0970c [142829.102342] sas: Internal abort: task to dev 51c20dbaf642a000 response: 0x0 status 0x5 [142829.110319] sas: sas_eh_handle_sas_errors: task 0x00000000bea0970c is done [142829.117275] sd 7:0:5:0: [sdc] tag#2375 UNKNOWN(0x2003) Result: hostbyte=0x05 driverbyte=DRIVER_OK cmd_age=0s [142829.127171] sd 7:0:5:0: [sdc] tag#2375 CDB: opcode=0x2a 2a 00 00 00 00 00 00 00 08 00 [142829.135059] I/O error, dev sdc, sector 0 op 0x1:(WRITE) flags 0x18800 phys_seg 1 prio class 2 This is because the block layer integrity profile is currently only set up the first time a disk is discovered. To address this, remove the first_scan check when configuring protection information during revalidate. Also unregister the block integrity profile if DIX is not supported with a given protection type. [mkp: commit description + printk dedup] Link: https://lore.kernel.org/r/20230221081026.24736-1-yangxingui@huawei.com Signed-off-by: Xingui Yang <yangxingui@huawei.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
2b3795167e
commit
26a02d972b
@ -2253,23 +2253,20 @@ static void sd_config_protection(struct scsi_disk *sdkp)
|
||||
{
|
||||
struct scsi_device *sdp = sdkp->device;
|
||||
|
||||
if (!sdkp->first_scan)
|
||||
return;
|
||||
|
||||
sd_dif_config_host(sdkp);
|
||||
|
||||
if (!sdkp->protection_type)
|
||||
return;
|
||||
|
||||
if (!scsi_host_dif_capable(sdp->host, sdkp->protection_type)) {
|
||||
sd_printk(KERN_NOTICE, sdkp,
|
||||
"Disabling DIF Type %u protection\n",
|
||||
sdkp->protection_type);
|
||||
sd_first_printk(KERN_NOTICE, sdkp,
|
||||
"Disabling DIF Type %u protection\n",
|
||||
sdkp->protection_type);
|
||||
sdkp->protection_type = 0;
|
||||
}
|
||||
|
||||
sd_printk(KERN_NOTICE, sdkp, "Enabling DIF Type %u protection\n",
|
||||
sdkp->protection_type);
|
||||
sd_first_printk(KERN_NOTICE, sdkp, "Enabling DIF Type %u protection\n",
|
||||
sdkp->protection_type);
|
||||
}
|
||||
|
||||
static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
|
||||
|
@ -39,8 +39,10 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
|
||||
dif = 0; dix = 1;
|
||||
}
|
||||
|
||||
if (!dix)
|
||||
if (!dix) {
|
||||
blk_integrity_unregister(disk);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
|
||||
@ -72,9 +74,9 @@ void sd_dif_config_host(struct scsi_disk *sdkp)
|
||||
bi.tag_size = sizeof(u16);
|
||||
}
|
||||
|
||||
sd_printk(KERN_NOTICE, sdkp,
|
||||
"Enabling DIX %s, application tag size %u bytes\n",
|
||||
bi.profile->name, bi.tag_size);
|
||||
sd_first_printk(KERN_NOTICE, sdkp,
|
||||
"Enabling DIX %s, application tag size %u bytes\n",
|
||||
bi.profile->name, bi.tag_size);
|
||||
out:
|
||||
blk_integrity_register(disk, &bi);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user