From c74f8056621738f5be9f5d3d7e0caa927b21aef6 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 16 Sep 2019 23:56:49 +0800 Subject: scsi: core: allow auto suspend override by low-level driver Rework from previous work by: Sujit Reddy Thumma Until now the scsi mid-layer forbids runtime suspend till userspace enables it. This is mainly to quarantine some disks with broken runtime power management or have high latencies executing suspend resume callbacks. If the userspace doesn't enable the runtime suspend the underlying hardware will be always on even when it is not doing any useful work and thus wasting power. Some low-level drivers for the controllers can efficiently use runtime power management to reduce power consumption and improve battery life. Allow runtime suspend parameters override within the LLD itself instead of waiting for userspace to control the power management. Link: https://lore.kernel.org/r/1568649411-5127-2-git-send-email-stanley.chu@mediatek.com Reviewed-by: Avri Altman Reviewed-by: Bart Van Assche Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- include/scsi/scsi_device.h | 3 ++- include/scsi/scsi_host.h | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 202f4d6a4342..039e289f295e 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -199,7 +199,8 @@ struct scsi_device { unsigned broken_fua:1; /* Don't set FUA bit */ unsigned lun_in_cdb:1; /* Store LUN bits in CDB[1] */ unsigned unmap_limit_for_ws:1; /* Use the UNMAP limit for WRITE SAME */ - + unsigned rpm_autosuspend:1; /* Enable runtime autosuspend at device + * creation time */ atomic_t disk_events_disable_depth; /* disable depth for disk events */ DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 31e0d6ca1eba..2c3f0c58869b 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -486,6 +486,9 @@ struct scsi_host_template { */ unsigned int cmd_size; struct scsi_host_cmd_pool *cmd_pool; + + /* Delay for runtime autosuspend */ + int rpm_autosuspend_delay; }; /* -- cgit v1.2.3 From d188b0675b21d5a6ca27b3e741381813983f4719 Mon Sep 17 00:00:00 2001 From: Ryan Attard Date: Thu, 26 Sep 2019 11:22:17 -0500 Subject: scsi: core: Add sysfs attributes for VPD pages 0h and 89h Add sysfs attributes for the ATA information page and Supported VPD Pages page. Link: https://lore.kernel.org/r/20190926162216.56591-1-ryanattard@ryanattard.info Signed-off-by: Ryan Attard Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi.c | 4 ++++ drivers/scsi/scsi_sysfs.c | 19 +++++++++++++++++++ include/scsi/scsi_device.h | 2 ++ 3 files changed, 25 insertions(+) (limited to 'include') diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 1f5b5c8a7f72..4f76841a7038 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -465,10 +465,14 @@ void scsi_attach_vpd(struct scsi_device *sdev) return; for (i = 4; i < vpd_buf->len; i++) { + if (vpd_buf->data[i] == 0x0) + scsi_update_vpd_page(sdev, 0x0, &sdev->vpd_pg0); if (vpd_buf->data[i] == 0x80) scsi_update_vpd_page(sdev, 0x80, &sdev->vpd_pg80); if (vpd_buf->data[i] == 0x83) scsi_update_vpd_page(sdev, 0x83, &sdev->vpd_pg83); + if (vpd_buf->data[i] == 0x89) + scsi_update_vpd_page(sdev, 0x89, &sdev->vpd_pg89); } kfree(vpd_buf); } diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index cebb9336c02b..2c76d7a43f67 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -437,6 +437,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work) struct device *parent; struct list_head *this, *tmp; struct scsi_vpd *vpd_pg80 = NULL, *vpd_pg83 = NULL; + struct scsi_vpd *vpd_pg0 = NULL, *vpd_pg89 = NULL; unsigned long flags; sdev = container_of(work, struct scsi_device, ew.work); @@ -466,16 +467,24 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work) sdev->request_queue = NULL; mutex_lock(&sdev->inquiry_mutex); + rcu_swap_protected(sdev->vpd_pg0, vpd_pg0, + lockdep_is_held(&sdev->inquiry_mutex)); rcu_swap_protected(sdev->vpd_pg80, vpd_pg80, lockdep_is_held(&sdev->inquiry_mutex)); rcu_swap_protected(sdev->vpd_pg83, vpd_pg83, lockdep_is_held(&sdev->inquiry_mutex)); + rcu_swap_protected(sdev->vpd_pg89, vpd_pg89, + lockdep_is_held(&sdev->inquiry_mutex)); mutex_unlock(&sdev->inquiry_mutex); + if (vpd_pg0) + kfree_rcu(vpd_pg0, rcu); if (vpd_pg83) kfree_rcu(vpd_pg83, rcu); if (vpd_pg80) kfree_rcu(vpd_pg80, rcu); + if (vpd_pg89) + kfree_rcu(vpd_pg89, rcu); kfree(sdev->inquiry); kfree(sdev); @@ -859,6 +868,8 @@ static struct bin_attribute dev_attr_vpd_##_page = { \ sdev_vpd_pg_attr(pg83); sdev_vpd_pg_attr(pg80); +sdev_vpd_pg_attr(pg89); +sdev_vpd_pg_attr(pg0); static ssize_t show_inquiry(struct file *filep, struct kobject *kobj, struct bin_attribute *bin_attr, @@ -1191,12 +1202,18 @@ static umode_t scsi_sdev_bin_attr_is_visible(struct kobject *kobj, struct scsi_device *sdev = to_scsi_device(dev); + if (attr == &dev_attr_vpd_pg0 && !sdev->vpd_pg0) + return 0; + if (attr == &dev_attr_vpd_pg80 && !sdev->vpd_pg80) return 0; if (attr == &dev_attr_vpd_pg83 && !sdev->vpd_pg83) return 0; + if (attr == &dev_attr_vpd_pg89 && !sdev->vpd_pg89) + return 0; + return S_IRUGO; } @@ -1239,8 +1256,10 @@ static struct attribute *scsi_sdev_attrs[] = { }; static struct bin_attribute *scsi_sdev_bin_attrs[] = { + &dev_attr_vpd_pg0, &dev_attr_vpd_pg83, &dev_attr_vpd_pg80, + &dev_attr_vpd_pg89, &dev_attr_inquiry, NULL }; diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 039e289f295e..3ed836db5306 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -140,8 +140,10 @@ struct scsi_device { const char * rev; /* ... "nullnullnullnull" before scan */ #define SCSI_VPD_PG_LEN 255 + struct scsi_vpd __rcu *vpd_pg0; struct scsi_vpd __rcu *vpd_pg83; struct scsi_vpd __rcu *vpd_pg80; + struct scsi_vpd __rcu *vpd_pg89; unsigned char current_tag; /* current tag */ struct scsi_target *sdev_target; /* used only for single_lun */ -- cgit v1.2.3 From 27f722ccbe1563629275bb7ee30c0e307f5837a2 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 30 Sep 2019 16:22:24 -0700 Subject: scsi: target: Remove tpg_list and se_portal_group.se_tpg_node Maintaining tpg_list without ever iterating over it is not useful. Hence remove tpg_list. This patch does not change the behavior of the SCSI target code. Cc: Mike Christie Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Nicholas Bellinger Link: https://lore.kernel.org/r/20190930232224.58980-1-bvanassche@acm.org Signed-off-by: Bart Van Assche Reviewed-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/target/target_core_tpg.c | 12 ------------ drivers/target/target_core_xcopy.c | 1 - include/target/target_core_base.h | 1 - 3 files changed, 14 deletions(-) (limited to 'include') diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index e5a71addbb06..d24e0a3ba3ff 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -32,9 +32,6 @@ extern struct se_device *g_lun0_dev; -static DEFINE_SPINLOCK(tpg_lock); -static LIST_HEAD(tpg_list); - /* __core_tpg_get_initiator_node_acl(): * * mutex_lock(&tpg->acl_node_mutex); must be held when calling @@ -475,7 +472,6 @@ int core_tpg_register( se_tpg->se_tpg_wwn = se_wwn; atomic_set(&se_tpg->tpg_pr_ref_count, 0); INIT_LIST_HEAD(&se_tpg->acl_node_list); - INIT_LIST_HEAD(&se_tpg->se_tpg_node); INIT_LIST_HEAD(&se_tpg->tpg_sess_list); spin_lock_init(&se_tpg->session_lock); mutex_init(&se_tpg->tpg_lun_mutex); @@ -494,10 +490,6 @@ int core_tpg_register( } } - spin_lock_bh(&tpg_lock); - list_add_tail(&se_tpg->se_tpg_node, &tpg_list); - spin_unlock_bh(&tpg_lock); - pr_debug("TARGET_CORE[%s]: Allocated portal_group for endpoint: %s, " "Proto: %d, Portal Tag: %u\n", se_tpg->se_tpg_tfo->fabric_name, se_tpg->se_tpg_tfo->tpg_get_wwn(se_tpg) ? @@ -519,10 +511,6 @@ int core_tpg_deregister(struct se_portal_group *se_tpg) tfo->tpg_get_wwn(se_tpg) ? tfo->tpg_get_wwn(se_tpg) : NULL, se_tpg->proto_id, tfo->tpg_get_tag(se_tpg)); - spin_lock_bh(&tpg_lock); - list_del(&se_tpg->se_tpg_node); - spin_unlock_bh(&tpg_lock); - while (atomic_read(&se_tpg->tpg_pr_ref_count) != 0) cpu_relax(); diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c index b9b1e92c6f8d..425c1070de08 100644 --- a/drivers/target/target_core_xcopy.c +++ b/drivers/target/target_core_xcopy.c @@ -467,7 +467,6 @@ int target_xcopy_setup_pt(void) } memset(&xcopy_pt_tpg, 0, sizeof(struct se_portal_group)); - INIT_LIST_HEAD(&xcopy_pt_tpg.se_tpg_node); INIT_LIST_HEAD(&xcopy_pt_tpg.acl_node_list); INIT_LIST_HEAD(&xcopy_pt_tpg.tpg_sess_list); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 7c9716fe731e..1728e883b7b2 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -876,7 +876,6 @@ struct se_portal_group { /* Spinlock for adding/removing sessions */ spinlock_t session_lock; struct mutex tpg_lun_mutex; - struct list_head se_tpg_node; /* linked list for initiator ACL list */ struct list_head acl_node_list; struct hlist_head tpg_lun_hlist; -- cgit v1.2.3 From c51c4841f1571673d9075b8cf5efa6995ea91d0e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 29 Jul 2019 01:46:43 +0900 Subject: scsi: ch: add include guard to chio.h Add a header include guard just in case. Link: https://lore.kernel.org/r/20190728164643.16335-1-yamada.masahiro@socionext.com Signed-off-by: Masahiro Yamada Signed-off-by: Martin K. Petersen --- include/uapi/linux/chio.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/uapi/linux/chio.h b/include/uapi/linux/chio.h index 689fc93fafda..e1cad4c319ee 100644 --- a/include/uapi/linux/chio.h +++ b/include/uapi/linux/chio.h @@ -3,6 +3,9 @@ * ioctl interface for the scsi media changer driver */ +#ifndef _UAPI_LINUX_CHIO_H +#define _UAPI_LINUX_CHIO_H + /* changer element types */ #define CHET_MT 0 /* media transport element (robot) */ #define CHET_ST 1 /* storage element (media slots) */ @@ -160,10 +163,4 @@ struct changer_set_voltag { #define CHIOSVOLTAG _IOW('c',18,struct changer_set_voltag) #define CHIOGVPARAMS _IOR('c',19,struct changer_vendor_params) -/* ---------------------------------------------------------------------- */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ +#endif /* _UAPI_LINUX_CHIO_H */ -- cgit v1.2.3 From 6eb045e092efefafc6687409a6fa6d1dabf0fb69 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 25 Oct 2019 14:58:55 +0800 Subject: scsi: core: avoid host-wide host_busy counter for scsi_mq It isn't necessary to check the host depth in scsi_queue_rq() any more since it has been respected by blk-mq before calling scsi_queue_rq() via getting driver tag. Lots of LUNs may attach to same host and per-host IOPS may reach millions, so we should avoid expensive atomic operations on the host-wide counter in the IO path. This patch implements scsi_host_busy() via blk_mq_tagset_busy_iter() with one scsi command state for reading the count of busy IOs for scsi_mq. It is observed that IOPS is increased by 15% in IO test on scsi_debug (32 LUNs, 32 submit queues, 1024 can_queue, libaio/dio) in a dual-socket system. Cc: Jens Axboe Cc: Ewan D. Milne Cc: Omar Sandoval , Cc: "Martin K. Petersen" , Cc: James Bottomley , Cc: Christoph Hellwig , Cc: Kashyap Desai Cc: Hannes Reinecke Cc: Laurence Oberman Cc: Bart Van Assche Link: https://lore.kernel.org/r/20191025065855.6309-1-ming.lei@redhat.com Signed-off-by: Ming Lei Reviewed-by: Jens Axboe Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/hosts.c | 19 ++++++++++++++++++- drivers/scsi/scsi.c | 2 +- drivers/scsi/scsi_lib.c | 45 ++++++++++++++++++++++----------------------- drivers/scsi/scsi_priv.h | 2 +- include/scsi/scsi_cmnd.h | 1 + include/scsi/scsi_host.h | 3 +-- 6 files changed, 44 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 55522b7162d3..1d669e47b692 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "scsi_priv.h" #include "scsi_logging.h" @@ -554,13 +555,29 @@ struct Scsi_Host *scsi_host_get(struct Scsi_Host *shost) } EXPORT_SYMBOL(scsi_host_get); +static bool scsi_host_check_in_flight(struct request *rq, void *data, + bool reserved) +{ + int *count = data; + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); + + if (test_bit(SCMD_STATE_INFLIGHT, &cmd->state)) + (*count)++; + + return true; +} + /** * scsi_host_busy - Return the host busy counter * @shost: Pointer to Scsi_Host to inc. **/ int scsi_host_busy(struct Scsi_Host *shost) { - return atomic_read(&shost->host_busy); + int cnt = 0; + + blk_mq_tagset_busy_iter(&shost->tag_set, + scsi_host_check_in_flight, &cnt); + return cnt; } EXPORT_SYMBOL(scsi_host_busy); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 4f76841a7038..adfe8b3693d5 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -186,7 +186,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd) struct scsi_driver *drv; unsigned int good_bytes; - scsi_device_unbusy(sdev); + scsi_device_unbusy(sdev, cmd); /* * Clear the flags that say that the device/target/host is no longer diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index dc210b9d4896..2563b061f56b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -189,7 +189,7 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy) * active on the host/device. */ if (unbusy) - scsi_device_unbusy(device); + scsi_device_unbusy(device, cmd); /* * Requeue this command. It will go before all other commands @@ -321,20 +321,20 @@ static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) } /* - * Decrement the host_busy counter and wake up the error handler if necessary. - * Avoid as follows that the error handler is not woken up if shost->host_busy - * == shost->host_failed: use call_rcu() in scsi_eh_scmd_add() in combination - * with an RCU read lock in this function to ensure that this function in its - * entirety either finishes before scsi_eh_scmd_add() increases the + * Wake up the error handler if necessary. Avoid as follows that the error + * handler is not woken up if host in-flight requests number == + * shost->host_failed: use call_rcu() in scsi_eh_scmd_add() in combination + * with an RCU read lock in this function to ensure that this function in + * its entirety either finishes before scsi_eh_scmd_add() increases the * host_failed counter or that it notices the shost state change made by * scsi_eh_scmd_add(). */ -static void scsi_dec_host_busy(struct Scsi_Host *shost) +static void scsi_dec_host_busy(struct Scsi_Host *shost, struct scsi_cmnd *cmd) { unsigned long flags; rcu_read_lock(); - atomic_dec(&shost->host_busy); + __clear_bit(SCMD_STATE_INFLIGHT, &cmd->state); if (unlikely(scsi_host_in_recovery(shost))) { spin_lock_irqsave(shost->host_lock, flags); if (shost->host_failed || shost->host_eh_scheduled) @@ -344,12 +344,12 @@ static void scsi_dec_host_busy(struct Scsi_Host *shost) rcu_read_unlock(); } -void scsi_device_unbusy(struct scsi_device *sdev) +void scsi_device_unbusy(struct scsi_device *sdev, struct scsi_cmnd *cmd) { struct Scsi_Host *shost = sdev->host; struct scsi_target *starget = scsi_target(sdev); - scsi_dec_host_busy(shost); + scsi_dec_host_busy(shost, cmd); if (starget->can_queue > 0) atomic_dec(&starget->target_busy); @@ -430,9 +430,6 @@ static inline bool scsi_target_is_busy(struct scsi_target *starget) static inline bool scsi_host_is_busy(struct Scsi_Host *shost) { - if (shost->can_queue > 0 && - atomic_read(&shost->host_busy) >= shost->can_queue) - return true; if (atomic_read(&shost->host_blocked) > 0) return true; if (shost->host_self_blocked) @@ -1139,6 +1136,7 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) unsigned int flags = cmd->flags & SCMD_PRESERVED_FLAGS; unsigned long jiffies_at_alloc; int retries; + bool in_flight; if (!blk_rq_is_scsi(rq) && !(flags & SCMD_INITIALIZED)) { flags |= SCMD_INITIALIZED; @@ -1147,6 +1145,7 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) jiffies_at_alloc = cmd->jiffies_at_alloc; retries = cmd->retries; + in_flight = test_bit(SCMD_STATE_INFLIGHT, &cmd->state); /* zero out the cmd, except for the embedded scsi_request */ memset((char *)cmd + sizeof(cmd->req), 0, sizeof(*cmd) - sizeof(cmd->req) + dev->host->hostt->cmd_size); @@ -1158,6 +1157,8 @@ void scsi_init_command(struct scsi_device *dev, struct scsi_cmnd *cmd) INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler); cmd->jiffies_at_alloc = jiffies_at_alloc; cmd->retries = retries; + if (in_flight) + __set_bit(SCMD_STATE_INFLIGHT, &cmd->state); scsi_add_cmd_to_list(cmd); } @@ -1367,16 +1368,14 @@ out_dec: */ static inline int scsi_host_queue_ready(struct request_queue *q, struct Scsi_Host *shost, - struct scsi_device *sdev) + struct scsi_device *sdev, + struct scsi_cmnd *cmd) { - unsigned int busy; - if (scsi_host_in_recovery(shost)) return 0; - busy = atomic_inc_return(&shost->host_busy) - 1; if (atomic_read(&shost->host_blocked) > 0) { - if (busy) + if (scsi_host_busy(shost) > 0) goto starved; /* @@ -1390,8 +1389,6 @@ static inline int scsi_host_queue_ready(struct request_queue *q, "unblocking host at zero depth\n")); } - if (shost->can_queue > 0 && busy >= shost->can_queue) - goto starved; if (shost->host_self_blocked) goto starved; @@ -1403,6 +1400,8 @@ static inline int scsi_host_queue_ready(struct request_queue *q, spin_unlock_irq(shost->host_lock); } + __set_bit(SCMD_STATE_INFLIGHT, &cmd->state); + return 1; starved: @@ -1411,7 +1410,7 @@ starved: list_add_tail(&sdev->starved_entry, &shost->starved_list); spin_unlock_irq(shost->host_lock); out_dec: - scsi_dec_host_busy(shost); + scsi_dec_host_busy(shost, cmd); return 0; } @@ -1665,7 +1664,7 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, ret = BLK_STS_RESOURCE; if (!scsi_target_queue_ready(shost, sdev)) goto out_put_budget; - if (!scsi_host_queue_ready(q, shost, sdev)) + if (!scsi_host_queue_ready(q, shost, sdev, cmd)) goto out_dec_target_busy; if (!(req->rq_flags & RQF_DONTPREP)) { @@ -1697,7 +1696,7 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, return BLK_STS_OK; out_dec_host_busy: - scsi_dec_host_busy(shost); + scsi_dec_host_busy(shost, cmd); out_dec_target_busy: if (scsi_target(sdev)->can_queue > 0) atomic_dec(&scsi_target(sdev)->target_busy); diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index cc2859d76d81..3bff9f7aa684 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -87,7 +87,7 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd); extern void scsi_add_cmd_to_list(struct scsi_cmnd *cmd); extern void scsi_del_cmd_from_list(struct scsi_cmnd *cmd); extern int scsi_maybe_unblock_host(struct scsi_device *sdev); -extern void scsi_device_unbusy(struct scsi_device *sdev); +extern void scsi_device_unbusy(struct scsi_device *sdev, struct scsi_cmnd *cmd); extern void scsi_queue_insert(struct scsi_cmnd *cmd, int reason); extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_run_host_queues(struct Scsi_Host *shost); diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 91bd749a02f7..9c22e85902ec 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -63,6 +63,7 @@ struct scsi_pointer { /* for scmd->state */ #define SCMD_STATE_COMPLETE 0 +#define SCMD_STATE_INFLIGHT 1 struct scsi_cmnd { struct scsi_request req; diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 2c3f0c58869b..fccdf84ec7e2 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -345,7 +345,7 @@ struct scsi_host_template { /* * This determines if we will use a non-interrupt driven * or an interrupt driven scheme. It is set to the maximum number - * of simultaneous commands a given host adapter will accept. + * of simultaneous commands a single hw queue in HBA will accept. */ int can_queue; @@ -554,7 +554,6 @@ struct Scsi_Host { /* Area to keep a shared tag map */ struct blk_mq_tag_set tag_set; - atomic_t host_busy; /* commands actually active on low-level */ atomic_t host_blocked; unsigned int host_failed; /* commands that failed. -- cgit v1.2.3 From 9237f04e12cc385334043cd7cf84b74dcbda0256 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Wed, 30 Oct 2019 18:08:47 +0900 Subject: scsi: core: Fix scsi_get/set_resid() interface struct scsi_cmnd cmd->req.resid_len which is returned and set respectively by the helper functions scsi_get_resid() and scsi_set_resid() is an unsigned int. Reflect this fact in the interface of these helper functions. Also fix compilation errors due to min() and max() type mismatch introduced by this change in scsi debug code, usb transport code and in the USB ENE card reader driver. Link: https://lore.kernel.org/r/20191030090847.25650-1-damien.lemoal@wdc.com Signed-off-by: Damien Le Moal Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_debug.c | 4 ++-- drivers/usb/storage/ene_ub6250.c | 2 +- drivers/usb/storage/transport.c | 3 +-- include/scsi/scsi_cmnd.h | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index d323523f5f9d..4daf2637c011 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -1025,7 +1025,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, static int p_fill_from_dev_buffer(struct scsi_cmnd *scp, const void *arr, int arr_len, unsigned int off_dst) { - int act_len, n; + unsigned int act_len, n; struct scsi_data_buffer *sdb = &scp->sdb; off_t skip = off_dst; @@ -1039,7 +1039,7 @@ static int p_fill_from_dev_buffer(struct scsi_cmnd *scp, const void *arr, pr_debug("%s: off_dst=%u, scsi_bufflen=%u, act_len=%u, resid=%d\n", __func__, off_dst, scsi_bufflen(scp), act_len, scsi_get_resid(scp)); - n = (int)scsi_bufflen(scp) - ((int)off_dst + act_len); + n = scsi_bufflen(scp) - (off_dst + act_len); scsi_set_resid(scp, min(scsi_get_resid(scp), n)); return 0; } diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 8b1b73065421..98c1aa594e6c 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -561,7 +561,7 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg) residue = min(residue, transfer_length); if (us->srb != NULL) scsi_set_resid(us->srb, max(scsi_get_resid(us->srb), - (int)residue)); + residue)); } if (bcs->Status != US_BULK_STAT_OK) diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 96cb0409dd89..238a8088e17f 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -1284,8 +1284,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) } else { residue = min(residue, transfer_length); - scsi_set_resid(srb, max(scsi_get_resid(srb), - (int) residue)); + scsi_set_resid(srb, max(scsi_get_resid(srb), residue)); } } diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 9c22e85902ec..a2849bb9cd19 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -191,12 +191,12 @@ static inline unsigned scsi_bufflen(struct scsi_cmnd *cmd) return cmd->sdb.length; } -static inline void scsi_set_resid(struct scsi_cmnd *cmd, int resid) +static inline void scsi_set_resid(struct scsi_cmnd *cmd, unsigned int resid) { cmd->req.resid_len = resid; } -static inline int scsi_get_resid(struct scsi_cmnd *cmd) +static inline unsigned int scsi_get_resid(struct scsi_cmnd *cmd) { return cmd->req.resid_len; } -- cgit v1.2.3 From 35c3363363ac7c8877b4984cdd8a2af377a4e92e Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sat, 2 Nov 2019 12:06:54 +1100 Subject: scsi: core: Clean up SG_NONE Remove SG_NONE and a related misleading comment. Update documentation. This patch does not affect behaviour as zero initialization is redundant. Cc: Jonathan Corbet Cc: Bartlomiej Zolnierkiewicz Cc: Jens Axboe Cc: Viresh Kumar Cc: Oliver Neukum Cc: Alan Stern Cc: Greg Kroah-Hartman Cc: usb-storage@lists.one-eyed-alien.net Link: https://lore.kernel.org/r/b4779b7a6563f6bd8d259ee457871c1c463c420e.1572656814.git.fthain@telegraphics.com.au Signed-off-by: Finn Thain Signed-off-by: Martin K. Petersen --- Documentation/scsi/scsi_mid_low_api.txt | 3 ++- drivers/ata/pata_arasan_cf.c | 1 - drivers/scsi/atp870u.c | 2 +- drivers/usb/storage/uas.c | 1 - include/scsi/scsi_host.h | 13 ------------- 5 files changed, 3 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt index c1dd4939f4ae..2a4be1c3e6db 100644 --- a/Documentation/scsi/scsi_mid_low_api.txt +++ b/Documentation/scsi/scsi_mid_low_api.txt @@ -1084,7 +1084,8 @@ of interest: commands to the adapter. this_id - scsi id of host (scsi initiator) or -1 if not known sg_tablesize - maximum scatter gather elements allowed by host. - 0 implies scatter gather not supported by host + Set this to SG_ALL or less to avoid chained SG lists. + Must be at least 1. max_sectors - maximum number of sectors (usually 512 bytes) allowed in a single SCSI command. The default value of 0 leads to a setting of SCSI_DEFAULT_MAX_SECTORS (defined in diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index ebecab8c3f36..135173c8d138 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -219,7 +219,6 @@ struct arasan_cf_dev { static struct scsi_host_template arasan_cf_sht = { ATA_BASE_SHT(DRIVER_NAME), - .sg_tablesize = SG_NONE, .dma_boundary = 0xFFFFFFFFUL, }; diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index e41f0bbdc9fd..c6a752309dda 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -1680,7 +1680,7 @@ static struct scsi_host_template atp870u_template = { .bios_param = atp870u_biosparam /* biosparm */, .can_queue = qcnt /* can_queue */, .this_id = 7 /* SCSI ID */, - .sg_tablesize = ATP870U_SCATTER /*SG_ALL*/ /*SG_NONE*/, + .sg_tablesize = ATP870U_SCATTER /*SG_ALL*/, .max_sectors = ATP870U_MAX_SECTORS, }; diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index bf80d6f81f58..fd9c0d2c111f 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -879,7 +879,6 @@ static struct scsi_host_template uas_host_template = { .eh_abort_handler = uas_eh_abort_handler, .eh_device_reset_handler = uas_eh_device_reset_handler, .this_id = -1, - .sg_tablesize = SG_NONE, .skip_settle_delay = 1, .dma_boundary = PAGE_SIZE - 1, }; diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index fccdf84ec7e2..f577647bf5f2 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -23,19 +23,6 @@ struct scsi_host_cmd_pool; struct scsi_transport_template; -/* - * The various choices mean: - * NONE: Self evident. Host adapter is not capable of scatter-gather. - * ALL: Means that the host adapter module can do scatter-gather, - * and that there is no limit to the size of the table to which - * we scatter/gather data. The value we set here is the maximum - * single element sglist. To use chained sglists, the adapter - * has to set a value beyond ALL (and correctly use the chain - * handling API. - * Anything else: Indicates the maximum number of chains that can be - * used in one scatter-gather request. - */ -#define SG_NONE 0 #define SG_ALL SG_CHUNK_SIZE #define MODE_UNKNOWN 0x00 -- cgit v1.2.3 From e9d3009cb936bd0faf0719f68d98ad8afb1e613b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 13 Nov 2019 14:05:08 -0800 Subject: scsi: target: iscsi: Wait for all commands to finish before freeing a session The iSCSI target driver is the only target driver that does not wait for ongoing commands to finish before freeing a session. Make the iSCSI target driver wait for ongoing commands to finish before freeing a session. This patch fixes the following KASAN complaint: BUG: KASAN: use-after-free in __lock_acquire+0xb1a/0x2710 Read of size 8 at addr ffff8881154eca70 by task kworker/0:2/247 CPU: 0 PID: 247 Comm: kworker/0:2 Not tainted 5.4.0-rc1-dbg+ #6 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014 Workqueue: target_completion target_complete_ok_work [target_core_mod] Call Trace: dump_stack+0x8a/0xd6 print_address_description.constprop.0+0x40/0x60 __kasan_report.cold+0x1b/0x33 kasan_report+0x16/0x20 __asan_load8+0x58/0x90 __lock_acquire+0xb1a/0x2710 lock_acquire+0xd3/0x200 _raw_spin_lock_irqsave+0x43/0x60 target_release_cmd_kref+0x162/0x7f0 [target_core_mod] target_put_sess_cmd+0x2e/0x40 [target_core_mod] lio_check_stop_free+0x12/0x20 [iscsi_target_mod] transport_cmd_check_stop_to_fabric+0xd8/0xe0 [target_core_mod] target_complete_ok_work+0x1b0/0x790 [target_core_mod] process_one_work+0x549/0xa40 worker_thread+0x7a/0x5d0 kthread+0x1bc/0x210 ret_from_fork+0x24/0x30 Allocated by task 889: save_stack+0x23/0x90 __kasan_kmalloc.constprop.0+0xcf/0xe0 kasan_slab_alloc+0x12/0x20 kmem_cache_alloc+0xf6/0x360 transport_alloc_session+0x29/0x80 [target_core_mod] iscsi_target_login_thread+0xcd6/0x18f0 [iscsi_target_mod] kthread+0x1bc/0x210 ret_from_fork+0x24/0x30 Freed by task 1025: save_stack+0x23/0x90 __kasan_slab_free+0x13a/0x190 kasan_slab_free+0x12/0x20 kmem_cache_free+0x146/0x400 transport_free_session+0x179/0x2f0 [target_core_mod] transport_deregister_session+0x130/0x180 [target_core_mod] iscsit_close_session+0x12c/0x350 [iscsi_target_mod] iscsit_logout_post_handler+0x136/0x380 [iscsi_target_mod] iscsit_response_queue+0x8de/0xbe0 [iscsi_target_mod] iscsi_target_tx_thread+0x27f/0x370 [iscsi_target_mod] kthread+0x1bc/0x210 ret_from_fork+0x24/0x30 The buggy address belongs to the object at ffff8881154ec9c0 which belongs to the cache se_sess_cache of size 352 The buggy address is located 176 bytes inside of 352-byte region [ffff8881154ec9c0, ffff8881154ecb20) The buggy address belongs to the page: page:ffffea0004553b00 refcount:1 mapcount:0 mapping:ffff888101755400 index:0x0 compound_mapcount: 0 flags: 0x2fff000000010200(slab|head) raw: 2fff000000010200 dead000000000100 dead000000000122 ffff888101755400 raw: 0000000000000000 0000000080130013 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff8881154ec900: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff8881154ec980: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb >ffff8881154eca00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff8881154eca80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff8881154ecb00: fb fb fb fb fc fc fc fc fc fc fc fc fc fc fc fc Cc: Mike Christie Link: https://lore.kernel.org/r/20191113220508.198257-3-bvanassche@acm.org Reviewed-by: Roman Bolshakov Signed-off-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/target/iscsi/iscsi_target.c | 10 ++++++++-- include/scsi/iscsi_proto.h | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 09e55ea0bf5d..7251a87bb576 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1165,7 +1165,9 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length, conn->cid); - target_get_sess_cmd(&cmd->se_cmd, true); + if (target_get_sess_cmd(&cmd->se_cmd, true) < 0) + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_WAITING_FOR_LOGOUT, buf); cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd, scsilun_to_int(&hdr->lun)); @@ -2002,7 +2004,9 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, conn->sess->se_sess, 0, DMA_NONE, TCM_SIMPLE_TAG, cmd->sense_buffer + 2); - target_get_sess_cmd(&cmd->se_cmd, true); + if (target_get_sess_cmd(&cmd->se_cmd, true) < 0) + return iscsit_add_reject_cmd(cmd, + ISCSI_REASON_WAITING_FOR_LOGOUT, buf); /* * TASK_REASSIGN for ERL=2 / connection stays inside of @@ -4230,6 +4234,8 @@ int iscsit_close_connection( * must wait until they have completed. */ iscsit_check_conn_usage_count(conn); + target_sess_cmd_list_set_waiting(sess->se_sess); + target_wait_for_sess_cmds(sess->se_sess); ahash_request_free(conn->conn_tx_hash); if (conn->conn_rx_hash) { diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h index b71b5c4f418c..533f56733ba8 100644 --- a/include/scsi/iscsi_proto.h +++ b/include/scsi/iscsi_proto.h @@ -627,6 +627,7 @@ struct iscsi_reject { #define ISCSI_REASON_BOOKMARK_INVALID 9 #define ISCSI_REASON_BOOKMARK_NO_RESOURCES 10 #define ISCSI_REASON_NEGOTIATION_RESET 11 +#define ISCSI_REASON_WAITING_FOR_LOGOUT 12 /* Max. number of Key=Value pairs in a text message */ #define MAX_KEY_VALUE_PAIRS 8192 -- cgit v1.2.3