diff options
author | Bart Van Assche <bvanassche@acm.org> | 2019-06-17 11:18:20 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2019-06-20 15:37:02 -0400 |
commit | fd56141244066a6a21ef458670071c58b6402035 (patch) | |
tree | dcb3ca3cbb75073084c3074c4530517d64227dac /drivers/infiniband/ulp | |
parent | bbe9fb0d04b96dda1fd7bd973e094004978b2166 (diff) |
scsi: RDMA/srp: Fix a sleep-in-invalid-context bug
The previous patch guarantees that srp_queuecommand() does not get
invoked while reconnecting occurs. Hence remove the code from
srp_queuecommand() that prevents command queueing while reconnecting.
This patch avoids that the following can appear in the kernel log:
BUG: sleeping function called from invalid context at kernel/locking/mutex.c:747
in_atomic(): 1, irqs_disabled(): 0, pid: 5600, name: scsi_eh_9
1 lock held by scsi_eh_9/5600:
#0: (rcu_read_lock){....}, at: [<00000000cbb798c7>] __blk_mq_run_hw_queue+0xf1/0x1e0
Preemption disabled at:
[<00000000139badf2>] __blk_mq_delay_run_hw_queue+0x78/0xf0
CPU: 9 PID: 5600 Comm: scsi_eh_9 Tainted: G W 4.15.0-rc4-dbg+ #1
Hardware name: Dell Inc. PowerEdge R720/0VWT90, BIOS 2.5.4 01/22/2016
Call Trace:
dump_stack+0x67/0x99
___might_sleep+0x16a/0x250 [ib_srp]
__mutex_lock+0x46/0x9d0
srp_queuecommand+0x356/0x420 [ib_srp]
scsi_dispatch_cmd+0xf6/0x3f0
scsi_queue_rq+0x4a8/0x5f0
blk_mq_dispatch_rq_list+0x73/0x440
blk_mq_sched_dispatch_requests+0x109/0x1a0
__blk_mq_run_hw_queue+0x131/0x1e0
__blk_mq_delay_run_hw_queue+0x9a/0xf0
blk_mq_run_hw_queue+0xc0/0x1e0
blk_mq_start_hw_queues+0x2c/0x40
scsi_run_queue+0x18e/0x2d0
scsi_run_host_queues+0x22/0x40
scsi_error_handler+0x18d/0x5f0
kthread+0x11c/0x140
ret_from_fork+0x24/0x30
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Laurence Oberman <loberman@redhat.com>
Cc: Jason Gunthorpe <jgg@mellanox.com>
Cc: Leon Romanovsky <leonro@mellanox.com>
Cc: Doug Ledford <dledford@redhat.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 21 |
1 files changed, 2 insertions, 19 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index be9ddcad8f28..b7c5a35f7daa 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -2338,7 +2338,6 @@ static void srp_handle_qp_err(struct ib_cq *cq, struct ib_wc *wc, | |||
2338 | static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) | 2338 | static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) |
2339 | { | 2339 | { |
2340 | struct srp_target_port *target = host_to_target(shost); | 2340 | struct srp_target_port *target = host_to_target(shost); |
2341 | struct srp_rport *rport = target->rport; | ||
2342 | struct srp_rdma_ch *ch; | 2341 | struct srp_rdma_ch *ch; |
2343 | struct srp_request *req; | 2342 | struct srp_request *req; |
2344 | struct srp_iu *iu; | 2343 | struct srp_iu *iu; |
@@ -2348,16 +2347,6 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) | |||
2348 | u32 tag; | 2347 | u32 tag; |
2349 | u16 idx; | 2348 | u16 idx; |
2350 | int len, ret; | 2349 | int len, ret; |
2351 | const bool in_scsi_eh = !in_interrupt() && current == shost->ehandler; | ||
2352 | |||
2353 | /* | ||
2354 | * The SCSI EH thread is the only context from which srp_queuecommand() | ||
2355 | * can get invoked for blocked devices (SDEV_BLOCK / | ||
2356 | * SDEV_CREATED_BLOCK). Avoid racing with srp_reconnect_rport() by | ||
2357 | * locking the rport mutex if invoked from inside the SCSI EH. | ||
2358 | */ | ||
2359 | if (in_scsi_eh) | ||
2360 | mutex_lock(&rport->mutex); | ||
2361 | 2350 | ||
2362 | scmnd->result = srp_chkready(target->rport); | 2351 | scmnd->result = srp_chkready(target->rport); |
2363 | if (unlikely(scmnd->result)) | 2352 | if (unlikely(scmnd->result)) |
@@ -2426,13 +2415,7 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) | |||
2426 | goto err_unmap; | 2415 | goto err_unmap; |
2427 | } | 2416 | } |
2428 | 2417 | ||
2429 | ret = 0; | 2418 | return 0; |
2430 | |||
2431 | unlock_rport: | ||
2432 | if (in_scsi_eh) | ||
2433 | mutex_unlock(&rport->mutex); | ||
2434 | |||
2435 | return ret; | ||
2436 | 2419 | ||
2437 | err_unmap: | 2420 | err_unmap: |
2438 | srp_unmap_data(scmnd, ch, req); | 2421 | srp_unmap_data(scmnd, ch, req); |
@@ -2454,7 +2437,7 @@ err: | |||
2454 | ret = SCSI_MLQUEUE_HOST_BUSY; | 2437 | ret = SCSI_MLQUEUE_HOST_BUSY; |
2455 | } | 2438 | } |
2456 | 2439 | ||
2457 | goto unlock_rport; | 2440 | return ret; |
2458 | } | 2441 | } |
2459 | 2442 | ||
2460 | /* | 2443 | /* |