[PATCH 4.14 058/140] scsi: core: Avoid that ATA error handling can trigger a kernel hang or oops

2018-03-13 Thread Greg Kroah-Hartman
4.14-stable review patch.  If anyone has any objections, please let me know.

--

From: Bart Van Assche 

commit 3be8828fc507cdafe7040a3dcf361a2bcd8e305b upstream.

Avoid that the recently introduced call_rcu() call in the SCSI core
triggers a double call_rcu() call.

Reported-by: Natanael Copa 
Reported-by: Damien Le Moal 
References: https://bugzilla.kernel.org/show_bug.cgi?id=198861
Fixes: 3bd6f43f5cb3 ("scsi: core: Ensure that the SCSI error handler gets woken 
up")
Signed-off-by: Bart Van Assche 
Reviewed-by: Damien Le Moal 
Tested-by: Damien Le Moal 
Cc: Natanael Copa 
Cc: Damien Le Moal 
Cc: Alexandre Oliva 
Cc: Pavel Tikhomirov 
Cc: Hannes Reinecke 
Cc: Johannes Thumshirn 
Cc: 
Signed-off-by: Martin K. Petersen 
Signed-off-by: Greg Kroah-Hartman 

---
 drivers/scsi/hosts.c  |3 ---
 drivers/scsi/scsi_error.c |5 +++--
 drivers/scsi/scsi_lib.c   |2 ++
 include/scsi/scsi_cmnd.h  |3 +++
 include/scsi/scsi_host.h  |2 --
 5 files changed, 8 insertions(+), 7 deletions(-)

--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -328,8 +328,6 @@ static void scsi_host_dev_release(struct
if (shost->work_q)
destroy_workqueue(shost->work_q);
 
-   destroy_rcu_head(>rcu);
-
if (shost->shost_state == SHOST_CREATED) {
/*
 * Free the shost_dev device name here if scsi_host_alloc()
@@ -404,7 +402,6 @@ struct Scsi_Host *scsi_host_alloc(struct
INIT_LIST_HEAD(>starved_list);
init_waitqueue_head(>host_wait);
mutex_init(>scan_mutex);
-   init_rcu_head(>rcu);
 
index = ida_simple_get(_index_ida, 0, 0, GFP_KERNEL);
if (index < 0)
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -222,7 +222,8 @@ static void scsi_eh_reset(struct scsi_cm
 
 static void scsi_eh_inc_host_failed(struct rcu_head *head)
 {
-   struct Scsi_Host *shost = container_of(head, typeof(*shost), rcu);
+   struct scsi_cmnd *scmd = container_of(head, typeof(*scmd), rcu);
+   struct Scsi_Host *shost = scmd->device->host;
unsigned long flags;
 
spin_lock_irqsave(shost->host_lock, flags);
@@ -258,7 +259,7 @@ void scsi_eh_scmd_add(struct scsi_cmnd *
 * Ensure that all tasks observe the host state change before the
 * host_failed change.
 */
-   call_rcu(>rcu, scsi_eh_inc_host_failed);
+   call_rcu(>rcu, scsi_eh_inc_host_failed);
 }
 
 /**
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -670,6 +670,7 @@ static bool scsi_end_request(struct requ
if (!blk_rq_is_scsi(req)) {
WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED));
cmd->flags &= ~SCMD_INITIALIZED;
+   destroy_rcu_head(>rcu);
}
 
if (req->mq_ctx) {
@@ -1150,6 +1151,7 @@ void scsi_initialize_rq(struct request *
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
 
scsi_req_init(>req);
+   init_rcu_head(>rcu);
cmd->jiffies_at_alloc = jiffies;
cmd->retries = 0;
 }
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -69,6 +69,9 @@ struct scsi_cmnd {
struct list_head list;  /* scsi_cmnd participates in queue lists */
struct list_head eh_entry; /* entry for the host eh_cmd_q */
struct delayed_work abort_work;
+
+   struct rcu_head rcu;
+
int eh_eflags;  /* Used by error handlr */
 
/*
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -571,8 +571,6 @@ struct Scsi_Host {
struct blk_mq_tag_set   tag_set;
};
 
-   struct rcu_head rcu;
-
atomic_t host_busy;/* commands actually active on 
low-level */
atomic_t host_blocked;
 




[PATCH 4.14 058/140] scsi: core: Avoid that ATA error handling can trigger a kernel hang or oops

2018-03-13 Thread Greg Kroah-Hartman
4.14-stable review patch.  If anyone has any objections, please let me know.

--

From: Bart Van Assche 

commit 3be8828fc507cdafe7040a3dcf361a2bcd8e305b upstream.

Avoid that the recently introduced call_rcu() call in the SCSI core
triggers a double call_rcu() call.

Reported-by: Natanael Copa 
Reported-by: Damien Le Moal 
References: https://bugzilla.kernel.org/show_bug.cgi?id=198861
Fixes: 3bd6f43f5cb3 ("scsi: core: Ensure that the SCSI error handler gets woken 
up")
Signed-off-by: Bart Van Assche 
Reviewed-by: Damien Le Moal 
Tested-by: Damien Le Moal 
Cc: Natanael Copa 
Cc: Damien Le Moal 
Cc: Alexandre Oliva 
Cc: Pavel Tikhomirov 
Cc: Hannes Reinecke 
Cc: Johannes Thumshirn 
Cc: 
Signed-off-by: Martin K. Petersen 
Signed-off-by: Greg Kroah-Hartman 

---
 drivers/scsi/hosts.c  |3 ---
 drivers/scsi/scsi_error.c |5 +++--
 drivers/scsi/scsi_lib.c   |2 ++
 include/scsi/scsi_cmnd.h  |3 +++
 include/scsi/scsi_host.h  |2 --
 5 files changed, 8 insertions(+), 7 deletions(-)

--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -328,8 +328,6 @@ static void scsi_host_dev_release(struct
if (shost->work_q)
destroy_workqueue(shost->work_q);
 
-   destroy_rcu_head(>rcu);
-
if (shost->shost_state == SHOST_CREATED) {
/*
 * Free the shost_dev device name here if scsi_host_alloc()
@@ -404,7 +402,6 @@ struct Scsi_Host *scsi_host_alloc(struct
INIT_LIST_HEAD(>starved_list);
init_waitqueue_head(>host_wait);
mutex_init(>scan_mutex);
-   init_rcu_head(>rcu);
 
index = ida_simple_get(_index_ida, 0, 0, GFP_KERNEL);
if (index < 0)
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -222,7 +222,8 @@ static void scsi_eh_reset(struct scsi_cm
 
 static void scsi_eh_inc_host_failed(struct rcu_head *head)
 {
-   struct Scsi_Host *shost = container_of(head, typeof(*shost), rcu);
+   struct scsi_cmnd *scmd = container_of(head, typeof(*scmd), rcu);
+   struct Scsi_Host *shost = scmd->device->host;
unsigned long flags;
 
spin_lock_irqsave(shost->host_lock, flags);
@@ -258,7 +259,7 @@ void scsi_eh_scmd_add(struct scsi_cmnd *
 * Ensure that all tasks observe the host state change before the
 * host_failed change.
 */
-   call_rcu(>rcu, scsi_eh_inc_host_failed);
+   call_rcu(>rcu, scsi_eh_inc_host_failed);
 }
 
 /**
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -670,6 +670,7 @@ static bool scsi_end_request(struct requ
if (!blk_rq_is_scsi(req)) {
WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED));
cmd->flags &= ~SCMD_INITIALIZED;
+   destroy_rcu_head(>rcu);
}
 
if (req->mq_ctx) {
@@ -1150,6 +1151,7 @@ void scsi_initialize_rq(struct request *
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
 
scsi_req_init(>req);
+   init_rcu_head(>rcu);
cmd->jiffies_at_alloc = jiffies;
cmd->retries = 0;
 }
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -69,6 +69,9 @@ struct scsi_cmnd {
struct list_head list;  /* scsi_cmnd participates in queue lists */
struct list_head eh_entry; /* entry for the host eh_cmd_q */
struct delayed_work abort_work;
+
+   struct rcu_head rcu;
+
int eh_eflags;  /* Used by error handlr */
 
/*
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -571,8 +571,6 @@ struct Scsi_Host {
struct blk_mq_tag_set   tag_set;
};
 
-   struct rcu_head rcu;
-
atomic_t host_busy;/* commands actually active on 
low-level */
atomic_t host_blocked;