diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-07 15:34:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-07 15:34:16 -0400 |
commit | 85b1bb248071967135d22cc84e62292094f4a3c6 (patch) | |
tree | 45b9d706a141322ad051213c5d3d118feddb09a2 | |
parent | 67936a41e597331c991528c5e5bd791cfbb1b1d6 (diff) | |
parent | 88e65389fce1f68ba6d13ae2fc0f8d7e5c338c52 (diff) |
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI fixes from James Bottomley:
- a couple of serious fixes: use after free and blacklist for WRITE
SAME
- one error leg fix: write_pending failure
- one user experience problem: do not override max_sectors_kb
- one minor unused function removal
* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
scsi: ibmvscsis: Fix write_pending failure path
scsi: libiscsi: Remove iscsi_destroy_session
scsi: libiscsi: Fix use-after-free race during iscsi_session_teardown
scsi: sd: Do not override max_sectors_kb sysfs setting
scsi: sd: Implement blacklist option for WRITE SAME w/ UNMAP
-rw-r--r-- | drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 2 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 8 | ||||
-rw-r--r-- | drivers/scsi/scsi_scan.c | 3 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 16 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 35 | ||||
-rw-r--r-- | include/scsi/scsi_device.h | 1 | ||||
-rw-r--r-- | include/scsi/scsi_devinfo.h | 1 | ||||
-rw-r--r-- | include/scsi/scsi_transport_iscsi.h | 1 |
8 files changed, 36 insertions, 31 deletions
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index 785fb42f6650..2799a6b08f73 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | |||
@@ -3767,7 +3767,7 @@ static int ibmvscsis_write_pending(struct se_cmd *se_cmd) | |||
3767 | */ | 3767 | */ |
3768 | if ((vscsi->flags & (CLIENT_FAILED | RESPONSE_Q_DOWN))) { | 3768 | if ((vscsi->flags & (CLIENT_FAILED | RESPONSE_Q_DOWN))) { |
3769 | pr_err("write_pending failed since: %d\n", vscsi->flags); | 3769 | pr_err("write_pending failed since: %d\n", vscsi->flags); |
3770 | return 0; | 3770 | return -EIO; |
3771 | } | 3771 | } |
3772 | 3772 | ||
3773 | rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, | 3773 | rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index bd4605a34f54..c62e8d111fd9 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -2851,9 +2851,6 @@ EXPORT_SYMBOL_GPL(iscsi_session_setup); | |||
2851 | /** | 2851 | /** |
2852 | * iscsi_session_teardown - destroy session, host, and cls_session | 2852 | * iscsi_session_teardown - destroy session, host, and cls_session |
2853 | * @cls_session: iscsi session | 2853 | * @cls_session: iscsi session |
2854 | * | ||
2855 | * The driver must have called iscsi_remove_session before | ||
2856 | * calling this. | ||
2857 | */ | 2854 | */ |
2858 | void iscsi_session_teardown(struct iscsi_cls_session *cls_session) | 2855 | void iscsi_session_teardown(struct iscsi_cls_session *cls_session) |
2859 | { | 2856 | { |
@@ -2863,6 +2860,8 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) | |||
2863 | 2860 | ||
2864 | iscsi_pool_free(&session->cmdpool); | 2861 | iscsi_pool_free(&session->cmdpool); |
2865 | 2862 | ||
2863 | iscsi_remove_session(cls_session); | ||
2864 | |||
2866 | kfree(session->password); | 2865 | kfree(session->password); |
2867 | kfree(session->password_in); | 2866 | kfree(session->password_in); |
2868 | kfree(session->username); | 2867 | kfree(session->username); |
@@ -2877,7 +2876,8 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) | |||
2877 | kfree(session->portal_type); | 2876 | kfree(session->portal_type); |
2878 | kfree(session->discovery_parent_type); | 2877 | kfree(session->discovery_parent_type); |
2879 | 2878 | ||
2880 | iscsi_destroy_session(cls_session); | 2879 | iscsi_free_session(cls_session); |
2880 | |||
2881 | iscsi_host_dec_session_cnt(shost); | 2881 | iscsi_host_dec_session_cnt(shost); |
2882 | module_put(owner); | 2882 | module_put(owner); |
2883 | } | 2883 | } |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index e7818afeda2b..15590a063ad9 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -956,6 +956,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
956 | if (*bflags & BLIST_NO_DIF) | 956 | if (*bflags & BLIST_NO_DIF) |
957 | sdev->no_dif = 1; | 957 | sdev->no_dif = 1; |
958 | 958 | ||
959 | if (*bflags & BLIST_UNMAP_LIMIT_WS) | ||
960 | sdev->unmap_limit_for_ws = 1; | ||
961 | |||
959 | sdev->eh_timeout = SCSI_DEFAULT_EH_TIMEOUT; | 962 | sdev->eh_timeout = SCSI_DEFAULT_EH_TIMEOUT; |
960 | 963 | ||
961 | if (*bflags & BLIST_TRY_VPD_PAGES) | 964 | if (*bflags & BLIST_TRY_VPD_PAGES) |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 0190aeff5f7f..7404d26895f5 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -2211,22 +2211,6 @@ void iscsi_free_session(struct iscsi_cls_session *session) | |||
2211 | EXPORT_SYMBOL_GPL(iscsi_free_session); | 2211 | EXPORT_SYMBOL_GPL(iscsi_free_session); |
2212 | 2212 | ||
2213 | /** | 2213 | /** |
2214 | * iscsi_destroy_session - destroy iscsi session | ||
2215 | * @session: iscsi_session | ||
2216 | * | ||
2217 | * Can be called by a LLD or iscsi_transport. There must not be | ||
2218 | * any running connections. | ||
2219 | */ | ||
2220 | int iscsi_destroy_session(struct iscsi_cls_session *session) | ||
2221 | { | ||
2222 | iscsi_remove_session(session); | ||
2223 | ISCSI_DBG_TRANS_SESSION(session, "Completing session destruction\n"); | ||
2224 | iscsi_free_session(session); | ||
2225 | return 0; | ||
2226 | } | ||
2227 | EXPORT_SYMBOL_GPL(iscsi_destroy_session); | ||
2228 | |||
2229 | /** | ||
2230 | * iscsi_create_conn - create iscsi class connection | 2214 | * iscsi_create_conn - create iscsi class connection |
2231 | * @session: iscsi cls session | 2215 | * @session: iscsi cls session |
2232 | * @dd_size: private driver data size | 2216 | * @dd_size: private driver data size |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index fb9f8b5f4673..d175c5c5ccf8 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -715,13 +715,21 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) | |||
715 | break; | 715 | break; |
716 | 716 | ||
717 | case SD_LBP_WS16: | 717 | case SD_LBP_WS16: |
718 | max_blocks = min_not_zero(sdkp->max_ws_blocks, | 718 | if (sdkp->device->unmap_limit_for_ws) |
719 | (u32)SD_MAX_WS16_BLOCKS); | 719 | max_blocks = sdkp->max_unmap_blocks; |
720 | else | ||
721 | max_blocks = sdkp->max_ws_blocks; | ||
722 | |||
723 | max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS16_BLOCKS); | ||
720 | break; | 724 | break; |
721 | 725 | ||
722 | case SD_LBP_WS10: | 726 | case SD_LBP_WS10: |
723 | max_blocks = min_not_zero(sdkp->max_ws_blocks, | 727 | if (sdkp->device->unmap_limit_for_ws) |
724 | (u32)SD_MAX_WS10_BLOCKS); | 728 | max_blocks = sdkp->max_unmap_blocks; |
729 | else | ||
730 | max_blocks = sdkp->max_ws_blocks; | ||
731 | |||
732 | max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS10_BLOCKS); | ||
725 | break; | 733 | break; |
726 | 734 | ||
727 | case SD_LBP_ZERO: | 735 | case SD_LBP_ZERO: |
@@ -3099,8 +3107,6 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
3099 | sd_read_security(sdkp, buffer); | 3107 | sd_read_security(sdkp, buffer); |
3100 | } | 3108 | } |
3101 | 3109 | ||
3102 | sdkp->first_scan = 0; | ||
3103 | |||
3104 | /* | 3110 | /* |
3105 | * We now have all cache related info, determine how we deal | 3111 | * We now have all cache related info, determine how we deal |
3106 | * with flush requests. | 3112 | * with flush requests. |
@@ -3115,7 +3121,7 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
3115 | q->limits.max_dev_sectors = logical_to_sectors(sdp, dev_max); | 3121 | q->limits.max_dev_sectors = logical_to_sectors(sdp, dev_max); |
3116 | 3122 | ||
3117 | /* | 3123 | /* |
3118 | * Use the device's preferred I/O size for reads and writes | 3124 | * Determine the device's preferred I/O size for reads and writes |
3119 | * unless the reported value is unreasonably small, large, or | 3125 | * unless the reported value is unreasonably small, large, or |
3120 | * garbage. | 3126 | * garbage. |
3121 | */ | 3127 | */ |
@@ -3129,8 +3135,19 @@ static int sd_revalidate_disk(struct gendisk *disk) | |||
3129 | rw_max = min_not_zero(logical_to_sectors(sdp, dev_max), | 3135 | rw_max = min_not_zero(logical_to_sectors(sdp, dev_max), |
3130 | (sector_t)BLK_DEF_MAX_SECTORS); | 3136 | (sector_t)BLK_DEF_MAX_SECTORS); |
3131 | 3137 | ||
3132 | /* Combine with controller limits */ | 3138 | /* Do not exceed controller limit */ |
3133 | q->limits.max_sectors = min(rw_max, queue_max_hw_sectors(q)); | 3139 | rw_max = min(rw_max, queue_max_hw_sectors(q)); |
3140 | |||
3141 | /* | ||
3142 | * Only update max_sectors if previously unset or if the current value | ||
3143 | * exceeds the capabilities of the hardware. | ||
3144 | */ | ||
3145 | if (sdkp->first_scan || | ||
3146 | q->limits.max_sectors > q->limits.max_dev_sectors || | ||
3147 | q->limits.max_sectors > q->limits.max_hw_sectors) | ||
3148 | q->limits.max_sectors = rw_max; | ||
3149 | |||
3150 | sdkp->first_scan = 0; | ||
3134 | 3151 | ||
3135 | set_capacity(disk, logical_to_sectors(sdp, sdkp->capacity)); | 3152 | set_capacity(disk, logical_to_sectors(sdp, sdkp->capacity)); |
3136 | sd_config_write_same(sdkp); | 3153 | sd_config_write_same(sdkp); |
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 82e93ee94708..67c5a9f223f7 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h | |||
@@ -192,6 +192,7 @@ struct scsi_device { | |||
192 | unsigned no_dif:1; /* T10 PI (DIF) should be disabled */ | 192 | unsigned no_dif:1; /* T10 PI (DIF) should be disabled */ |
193 | unsigned broken_fua:1; /* Don't set FUA bit */ | 193 | unsigned broken_fua:1; /* Don't set FUA bit */ |
194 | unsigned lun_in_cdb:1; /* Store LUN bits in CDB[1] */ | 194 | unsigned lun_in_cdb:1; /* Store LUN bits in CDB[1] */ |
195 | unsigned unmap_limit_for_ws:1; /* Use the UNMAP limit for WRITE SAME */ | ||
195 | 196 | ||
196 | atomic_t disk_events_disable_depth; /* disable depth for disk events */ | 197 | atomic_t disk_events_disable_depth; /* disable depth for disk events */ |
197 | 198 | ||
diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h index 9592570e092a..36b03013d629 100644 --- a/include/scsi/scsi_devinfo.h +++ b/include/scsi/scsi_devinfo.h | |||
@@ -29,5 +29,6 @@ | |||
29 | #define BLIST_TRY_VPD_PAGES 0x10000000 /* Attempt to read VPD pages */ | 29 | #define BLIST_TRY_VPD_PAGES 0x10000000 /* Attempt to read VPD pages */ |
30 | #define BLIST_NO_RSOC 0x20000000 /* don't try to issue RSOC */ | 30 | #define BLIST_NO_RSOC 0x20000000 /* don't try to issue RSOC */ |
31 | #define BLIST_MAX_1024 0x40000000 /* maximum 1024 sector cdb length */ | 31 | #define BLIST_MAX_1024 0x40000000 /* maximum 1024 sector cdb length */ |
32 | #define BLIST_UNMAP_LIMIT_WS 0x80000000 /* Use UNMAP limit for WRITE SAME */ | ||
32 | 33 | ||
33 | #endif | 34 | #endif |
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 6183d20a01fb..b266d2a3bcb1 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h | |||
@@ -434,7 +434,6 @@ extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost, | |||
434 | unsigned int target_id); | 434 | unsigned int target_id); |
435 | extern void iscsi_remove_session(struct iscsi_cls_session *session); | 435 | extern void iscsi_remove_session(struct iscsi_cls_session *session); |
436 | extern void iscsi_free_session(struct iscsi_cls_session *session); | 436 | extern void iscsi_free_session(struct iscsi_cls_session *session); |
437 | extern int iscsi_destroy_session(struct iscsi_cls_session *session); | ||
438 | extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, | 437 | extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, |
439 | int dd_size, uint32_t cid); | 438 | int dd_size, uint32_t cid); |
440 | extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); | 439 | extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); |