Commit fe542396da73b7e2b0848618c7e95855c1b75689

Authored by Martin K. Petersen
Committed by James Bottomley
1 parent fe0c9610bb

[SCSI] sd: Ensure we correctly disable devices with unknown protection type

We set the capacity to zero when we discovered a device formatted with
an unknown DIF protection type. However, the read_capacity code would
override the capacity and cause the device to be enabled regardless.

Make sd_read_protection_type() return an error if the protection type is
unknown. Also prevent duplicate printk lines when the device is being
revalidated.

Reported-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

Showing 2 changed files with 37 additions and 19 deletions Side-by-side Diff

... ... @@ -1693,34 +1693,42 @@
1693 1693 /*
1694 1694 * Determine whether disk supports Data Integrity Field.
1695 1695 */
1696   -static void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer)
  1696 +static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer)
1697 1697 {
1698 1698 struct scsi_device *sdp = sdkp->device;
1699 1699 u8 type;
  1700 + int ret = 0;
1700 1701  
1701 1702 if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0)
1702   - return;
  1703 + return ret;
1703 1704  
1704 1705 type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
1705 1706  
1706   - if (type == sdkp->protection_type || !sdkp->first_scan)
1707   - return;
  1707 + if (type > SD_DIF_TYPE3_PROTECTION)
  1708 + ret = -ENODEV;
  1709 + else if (scsi_host_dif_capable(sdp->host, type))
  1710 + ret = 1;
1708 1711  
  1712 + if (sdkp->first_scan || type != sdkp->protection_type)
  1713 + switch (ret) {
  1714 + case -ENODEV:
  1715 + sd_printk(KERN_ERR, sdkp, "formatted with unsupported" \
  1716 + " protection type %u. Disabling disk!\n",
  1717 + type);
  1718 + break;
  1719 + case 1:
  1720 + sd_printk(KERN_NOTICE, sdkp,
  1721 + "Enabling DIF Type %u protection\n", type);
  1722 + break;
  1723 + case 0:
  1724 + sd_printk(KERN_NOTICE, sdkp,
  1725 + "Disabling DIF Type %u protection\n", type);
  1726 + break;
  1727 + }
  1728 +
1709 1729 sdkp->protection_type = type;
1710 1730  
1711   - if (type > SD_DIF_TYPE3_PROTECTION) {
1712   - sd_printk(KERN_ERR, sdkp, "formatted with unsupported " \
1713   - "protection type %u. Disabling disk!\n", type);
1714   - sdkp->capacity = 0;
1715   - return;
1716   - }
1717   -
1718   - if (scsi_host_dif_capable(sdp->host, type))
1719   - sd_printk(KERN_NOTICE, sdkp,
1720   - "Enabling DIF Type %u protection\n", type);
1721   - else
1722   - sd_printk(KERN_NOTICE, sdkp,
1723   - "Disabling DIF Type %u protection\n", type);
  1731 + return ret;
1724 1732 }
1725 1733  
1726 1734 static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
... ... @@ -1816,7 +1824,10 @@
1816 1824 sector_size = get_unaligned_be32(&buffer[8]);
1817 1825 lba = get_unaligned_be64(&buffer[0]);
1818 1826  
1819   - sd_read_protection_type(sdkp, buffer);
  1827 + if (sd_read_protection_type(sdkp, buffer) < 0) {
  1828 + sdkp->capacity = 0;
  1829 + return -ENODEV;
  1830 + }
1820 1831  
1821 1832 if ((sizeof(sdkp->capacity) == 4) && (lba >= 0xffffffffULL)) {
1822 1833 sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
... ... @@ -2654,7 +2665,8 @@
2654 2665 }
2655 2666  
2656 2667 add_disk(gd);
2657   - sd_dif_config_host(sdkp);
  2668 + if (sdkp->capacity)
  2669 + sd_dif_config_host(sdkp);
2658 2670  
2659 2671 sd_revalidate_disk(gd);
2660 2672  
include/scsi/scsi_host.h
... ... @@ -873,6 +873,9 @@
873 873 SHOST_DIF_TYPE2_PROTECTION,
874 874 SHOST_DIF_TYPE3_PROTECTION };
875 875  
  876 + if (target_type > SHOST_DIF_TYPE3_PROTECTION)
  877 + return 0;
  878 +
876 879 return shost->prot_capabilities & cap[target_type] ? target_type : 0;
877 880 }
878 881  
... ... @@ -883,6 +886,9 @@
883 886 SHOST_DIX_TYPE1_PROTECTION,
884 887 SHOST_DIX_TYPE2_PROTECTION,
885 888 SHOST_DIX_TYPE3_PROTECTION };
  889 +
  890 + if (target_type > SHOST_DIX_TYPE3_PROTECTION)
  891 + return 0;
886 892  
887 893 return shost->prot_capabilities & cap[target_type];
888 894 #endif