Patch "IB/srp: Fix race conditions related to task management" has been added to the 4.9-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
IB/srp: Fix race conditions related to task management
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ib-srp-fix-race-conditions-related-to-task-management.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
0a6fdbdeb1c25e31763c1fb333fa2723a7d2aba6Mon Sep 17 00:00:00 2001
From: Bart Van Assche <[email protected]>
Date: Tue, 14 Feb 2017 10:56:31 -0800
Subject: IB/srp: Fix race conditions related to task management
From: Bart Van Assche <[email protected]>
commit 0a6fdbdeb1c25e31763c1fb333fa2723a7d2aba6 upstream.
Avoid that srp_process_rsp() overwrites the status information in ch if the SRP target response timed out and processing of another task management function has already started. Avoid that issuing multiple task management functions concurrently triggers list corruption. This patch prevents that the following stack trace appears in the system log:
WARNING: CPU: 8 PID: 9269 at lib/list_debug.c:52 __list_del_entry_valid+0xbc/0xc0 list_del corruption. prev->next should be ffffc90004bb7b00, but was ffff8804052ecc68 CPU: 8 PID: 9269 Comm: sg_reset Tainted: G W 4.10.0-rc7-dbg+ #3 Call Trace: dump_stack+0x68/0x93 __warn+0xc6/0xe0 warn_slowpath_fmt+0x4a/0x50 __list_del_entry_valid+0xbc/0xc0 wait_for_completion_timeout+0x12e/0x170 srp_send_tsk_mgmt+0x1ef/0x2d0 [ib_srp] srp_reset_device+0x5b/0x110 [ib_srp] scsi_ioctl_reset+0x1c7/0x290 scsi_ioctl+0x12a/0x420 sd_ioctl+0x9d/0x100 blkdev_ioctl+0x51e/0x9f0 block_ioctl+0x38/0x40 do_vfs_ioctl+0x8f/0x700 SyS_ioctl+0x3c/0x70 entry_SYSCALL_64_fastpath+0x18/0xad
--- drivers/infiniband/ulp/srp/ib_srp.c | 45 +++++++++++++++++++++++------------- drivers/infiniband/ulp/srp/ib_srp.h | 1 2 files changed, 30 insertions(+), 16 deletions(-)
drivers/infiniband/ulp/srp/ib_srp.c +29 -16
@@ -1872,12 +1872,17 @@ static void srp_process_rsp(struct srp_rif (unlikely (rsp->tag &SRP_TAG_TSK_MGMT )) {spin_lock_irqsave (&ch->lock, flags); ch->req_lim +=be32_to_cpu (rsp->req_lim_delta); +if (rsp->tag == ch->tsk_mgmt_tag) { + ch->tsk_mgmt_status =-1 ; +if (be32_to_cpu (rsp->resp_data_len) >=4 ) + ch->tsk_mgmt_status = rsp->data[3 ]; +complete (&ch->tsk_mgmt_done); + }else { +shost_printk (KERN_ERR , target->scsi_host, +"Received tsk mgmt response too late for tag %#llx\n" , + rsp->tag); + }spin_unlock_irqrestore (&ch->lock, flags); - - ch->tsk_mgmt_status =-1 ; -if (be32_to_cpu (rsp->resp_data_len) >=4 ) - ch->tsk_mgmt_status = rsp->data[3 ]; -complete (&ch->tsk_mgmt_done); }else { scmnd =scsi_host_find_tag (target->scsi_host, rsp->tag);if (scmnd && scmnd->host_scribble) {
@@ -2516,19 +2521,18 @@ srp_change_queue_depth(struct scsi_devic }static int srp_send_tsk_mgmt (struct srp_rdma_ch *ch,u64 req_tag,u64 lun, -u8 func) +u8 func,u8 *status) {struct srp_target_port *target = ch->target;struct srp_rport *rport = target->rport;struct ib_device *dev = target->srp_host->srp_dev->dev;struct srp_iu *iu;struct srp_tsk_mgmt *tsk_mgmt; +int res;if (!ch->connected || target->qp_in_error)return -1 ; -init_completion (&ch->tsk_mgmt_done); -/* * Lock the rport mutex to avoid that srp_create_ch_ib() is * invoked while a task management function is being sent.
@@ -2551,10 +2555,16 @@ static int srp_send_tsk_mgmt(struct srp_ tsk_mgmt->opcode =SRP_TSK_MGMT ;int_to_scsilun (lun, &tsk_mgmt->lun); - tsk_mgmt->tag = req_tag |SRP_TAG_TSK_MGMT ; tsk_mgmt->tsk_mgmt_func = func; tsk_mgmt->task_tag = req_tag; +spin_lock_irq (&ch->lock); + ch->tsk_mgmt_tag = (ch->tsk_mgmt_tag +1 ) |SRP_TAG_TSK_MGMT ; + tsk_mgmt->tag = ch->tsk_mgmt_tag; +spin_unlock_irq (&ch->lock); + +init_completion (&ch->tsk_mgmt_done); +ib_dma_sync_single_for_device (dev, iu->dma,sizeof *tsk_mgmt,DMA_TO_DEVICE );if (srp_post_send (ch, iu,sizeof (*tsk_mgmt))) {
@@ -2563,13 +2573,15 @@ static int srp_send_tsk_mgmt(struct srp_return -1 ; } + res =wait_for_completion_timeout (&ch->tsk_mgmt_done, +msecs_to_jiffies (SRP_ABORT_TIMEOUT_MS )); +if (res >0 && status) + *status = ch->tsk_mgmt_status;mutex_unlock (&rport->mutex); -if (!wait_for_completion_timeout (&ch->tsk_mgmt_done, -msecs_to_jiffies (SRP_ABORT_TIMEOUT_MS ))) -return -1 ; +WARN_ON_ONCE (res <0 ); -return 0 ; +return res >0 ?0 :-1 ; }static int srp_abort (struct scsi_cmnd *scmnd)
@@ -2595,7 +2607,7 @@ static int srp_abort(struct scsi_cmnd *sshost_printk (KERN_ERR , target->scsi_host,"Sending SRP abort for tag %#x\n" , tag);if (srp_send_tsk_mgmt (ch, tag, scmnd->device->lun, -SRP_TSK_ABORT_TASK ) ==0 ) +SRP_TSK_ABORT_TASK ,NULL ) ==0 ) ret =SUCCESS ;else if (target->rport->state ==SRP_RPORT_LOST ) ret =FAST_IO_FAIL ;
@@ -2613,14 +2625,15 @@ static int srp_reset_device(struct scsi_struct srp_target_port *target =host_to_target (scmnd->device->host);struct srp_rdma_ch *ch;int i; +u8 status;shost_printk (KERN_ERR , target->scsi_host,"SRP reset_device called\n" ); ch = &target->ch[0 ];if (srp_send_tsk_mgmt (ch,SRP_TAG_NO_REQ , scmnd->device->lun, -SRP_TSK_LUN_RESET )) +SRP_TSK_LUN_RESET , &status))return FAILED ; -if (ch->tsk_mgmt_status) +if (status)return FAILED ;for (i =0 ; i < target->ch_count; i++) {
drivers/infiniband/ulp/srp/ib_srp.h +1 -0
@@ -163,6 +163,7 @@ struct srp_rdma_ch {int max_ti_iu_len;int comp_vector; +u64 tsk_mgmt_tag;struct completion tsk_mgmt_done;u8 tsk_mgmt_status;bool connected;
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/ib-srp-avoid-that-duplicate-responses-trigger-a-kernel-bug.patch queue-4.9/ib-srp-fix-race-conditions-related-to-task-management.patch queue-4.9/ib-srp-avoid-using-ib_mr_type_sg_gaps.patch