Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] mpt fusion: fix for mounted raid volume filesytem that goes read-only

If there is IO going to the volume while a hidden disk is being torn down,
there is a case where we would return a DID_NO_CONNECT for IO sent to the
volume. The end result is the volume goes read-only. This problem is due to the
fact the firmware mapped target ids saved in per device object is phys_disk_num
for hidden raid components, and target_id for the volume. There is a single
case when both phys_disk_num and target_id are equal, so enters this issue. We
fix this issue by checking the tflags when the device is torned down,
insuring the IO being completed is meant for hidden raid component, not the
volume. In addition to this fix, there are a couple other cases to address
hidden raid components. For instance task_abort and device reset are not
supported by mpt fw for hidden raid components, a bus reset would be required
or target reset to volume.

Signed-off-by: Eric Moore <Eric.Moore@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>

authored by

Eric Moore and committed by
James Bottomley
cc78d30a 958d4a32

+45 -8
+45 -8
drivers/message/fusion/mptscsih.c
··· 447 447 MPT_FRAME_HDR *mf; 448 448 SEPRequest_t *SEPMsg; 449 449 450 - if (ioc->bus_type == FC) 450 + if (ioc->bus_type != SAS) 451 + return; 452 + 453 + /* Not supported for hidden raid components 454 + */ 455 + if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) 451 456 return; 452 457 453 458 if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { ··· 996 991 mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); 997 992 if (mf == NULL) 998 993 continue; 994 + /* If the device is a hidden raid component, then its 995 + * expected that the mf->function will be RAID_SCSI_IO 996 + */ 997 + if (vdevice->vtarget->tflags & 998 + MPT_TARGET_FLAGS_RAID_COMPONENT && mf->Function != 999 + MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) 1000 + continue; 1001 + 999 1002 int_to_scsilun(vdevice->lun, &lun); 1000 1003 if ((mf->Bus != vdevice->vtarget->channel) || 1001 1004 (mf->TargetID != vdevice->vtarget->id) || 1002 1005 memcmp(lun.scsi_lun, mf->LUN, 8)) 1003 1006 continue; 1004 - dsprintk(( "search_running: found (sc=%p, mf = %p) " 1005 - "channel %d id %d, lun %d \n", hd->ScsiLookup[ii], 1006 - mf, mf->Bus, mf->TargetID, vdevice->lun)); 1007 1007 1008 1008 /* Cleanup 1009 1009 */ ··· 1018 1008 if ((unsigned char *)mf != sc->host_scribble) 1019 1009 continue; 1020 1010 scsi_dma_unmap(sc); 1021 - 1022 1011 sc->host_scribble = NULL; 1023 1012 sc->result = DID_NO_CONNECT << 16; 1013 + dsprintk(( "search_running: found (sc=%p, mf = %p) " 1014 + "channel %d id %d, lun %d \n", sc, mf, 1015 + vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun)); 1024 1016 sc->scsi_done(sc); 1025 1017 } 1026 1018 } ··· 1768 1756 goto out; 1769 1757 } 1770 1758 1759 + /* Task aborts are not supported for hidden raid components. 1760 + */ 1761 + if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { 1762 + dtmprintk((MYIOC_s_DEBUG_FMT "task abort: hidden raid " 1763 + "component (sc=%p)\n", ioc->name, SCpnt)); 1764 + SCpnt->result = DID_RESET << 16; 1765 + retval = FAILED; 1766 + goto out; 1767 + } 1768 + 1771 1769 /* Find this command 1772 1770 */ 1773 1771 if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { ··· 1868 1846 vdevice = SCpnt->device->hostdata; 1869 1847 if (!vdevice || !vdevice->vtarget) { 1870 1848 retval = 0; 1849 + goto out; 1850 + } 1851 + 1852 + /* Target reset to hidden raid component is not supported 1853 + */ 1854 + if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { 1855 + retval = FAILED; 1871 1856 goto out; 1872 1857 } 1873 1858 ··· 3160 3131 { 3161 3132 INTERNAL_CMD iocmd; 3162 3133 3134 + /* Ignore hidden raid components, this is handled when the command 3135 + * is sent to the volume 3136 + */ 3137 + if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) 3138 + return; 3139 + 3140 + if (vdevice->vtarget->type != TYPE_DISK || vdevice->vtarget->deleted || 3141 + !vdevice->configured_lun) 3142 + return; 3143 + 3163 3144 /* Following parameters will not change 3164 3145 * in this routine. 3165 3146 */ ··· 3184 3145 iocmd.id = vdevice->vtarget->id; 3185 3146 iocmd.lun = vdevice->lun; 3186 3147 3187 - if ((vdevice->vtarget->type == TYPE_DISK) && 3188 - (vdevice->configured_lun)) 3189 - mptscsih_do_cmd(hd, &iocmd); 3148 + mptscsih_do_cmd(hd, &iocmd); 3190 3149 } 3191 3150 3192 3151 EXPORT_SYMBOL(mptscsih_remove);