Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1599124

[PATCH 4.4 17/36] IB/srp: Fix race conditions related to task management

From Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Newsgroups linux.kernel
Subject [PATCH 4.4 17/36] IB/srp: Fix race conditions related to task management
Date 2017-03-13 10:30 +0100
Message-ID <tkusG-6Sd-13@gated-at.bofh.it> (permalink)
References <tktPX-6ks-21@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


4.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Bart Van Assche <bart.vanassche@sandisk.com>

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

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Cc: Israel Rukshin <israelr@mellanox.com>
Cc: Max Gurtovoy <maxg@mellanox.com>
Cc: Laurence Oberman <loberman@redhat.com>
Cc: Steve Feeley <Steve.Feeley@sandisk.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 drivers/infiniband/ulp/srp/ib_srp.c |   45 +++++++++++++++++++++++-------------
 drivers/infiniband/ulp/srp/ib_srp.h |    1 
 2 files changed, 30 insertions(+), 16 deletions(-)

--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1787,12 +1787,17 @@ static void srp_process_rsp(struct srp_r
 	if (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) {
@@ -2471,19 +2476,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.
@@ -2506,10 +2510,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))) {
@@ -2518,13 +2528,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)
@@ -2550,7 +2562,7 @@ static int srp_abort(struct scsi_cmnd *s
 	shost_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;
@@ -2568,14 +2580,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++) {
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -168,6 +168,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;

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH 4.4 00/36] 4.4.54-stable review Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 09:50 +0100
  [PATCH 4.4 18/36] ktest: Fix child exit code processing Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 09:50 +0100
  [PATCH 4.4 11/36] s390: use correct input data address for setup_randomness Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 09:50 +0100
  [PATCH 4.4 27/36] drm/ast: Call open_key before enable_mmio in POST code Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 09:50 +0100
  [PATCH 4.4 05/36] KVM: VMX: use correct vmcs_read/write for guest segment selector/base Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 09:50 +0100
  [PATCH 4.4 31/36] drm/atomic: fix an error code in mode_fixup() Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:20 +0100
  [PATCH 4.4 35/36] fat: fix using uninitialized fields of fat_inode/fsinfo_inode Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:20 +0100
  [PATCH 4.4 08/36] s390/dcssblk: fix device size calculation in dcssblk_direct_access() Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:20 +0100
  [PATCH 4.4 07/36] s390/qdio: clear DSCI prior to scanning multiple input queues Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:20 +0100
  [PATCH 4.4 04/36] KVM: s390: Disable dirty log retrieval for UCONTROL guests Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:20 +0100
  [PATCH 4.4 36/36] drivers: hv: Turn off write permission on the hypercall page Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:20 +0100
  [PATCH 4.4 34/36] libceph: use BUG() instead of BUG_ON(1) Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:20 +0100
  [PATCH 4.4 23/36] xtensa: move parse_tag_fdt out of #ifdef CONFIG_BLK_DEV_INITRD Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  [PATCH 4.4 22/36] pwm: pca9685: Fix period change with same duty cycle Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  [PATCH 4.4 19/36] ceph: remove req from unsafe list when unregistering it Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  [PATCH 4.4 26/36] drm/ast: Fix test for VGA enabled Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  [PATCH 4.4 17/36] IB/srp: Fix race conditions related to task management Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  [PATCH 4.4 15/36] IB/IPoIB: Add destination address when re-queue packet Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  [PATCH 4.4 32/36] fakelb: fix schedule while atomic Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  [PATCH 4.4 21/36] nlm: Ensure callback code also checks that the files match Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  [PATCH 4.4 13/36] mnt: Tuck mounts under others instead of creating shadow/side mounts. Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  [PATCH 4.4 20/36] target: Fix NULL dereference during LUN lookup + active I/O shutdown Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  [PATCH 4.4 24/36] mac80211: flush delayed work when entering suspend Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  [PATCH 4.4 12/36] net: mvpp2: fix DMA address calculation in mvpp2_txq_inc_put() Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  [PATCH 4.4 10/36] s390: make setup_randomness work Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-03-13 10:30 +0100
  Re: [PATCH 4.4 00/36] 4.4.54-stable review Guenter Roeck <linux@roeck-us.net> - 2017-03-13 23:40 +0100

csiph-web