public inbox for linux-rdma@vger.kernel.org
 help / color / mirror / Atom feed
From: "Nicholas A. Bellinger" <nab@linux-iscsi.org>
To: target-devel <target-devel@vger.kernel.org>,
	linux-rdma <linux-rdma@vger.kernel.org>
Cc: linux-scsi <linux-scsi@vger.kernel.org>,
	Roland Dreier <roland@purestorage.com>,
	Bart Van Assche <bvanassche@acm.org>,
	"Nicholas A. Bellinger" <nab@linux-iscsi.org>
Subject: [PATCH 2/9] ib_srpt: Avoid failed multipart RDMA transfers
Date: Mon, 24 Oct 2011 05:33:35 +0000	[thread overview]
Message-ID: <1319434422-15354-3-git-send-email-nab@linux-iscsi.org> (raw)
In-Reply-To: <1319434422-15354-1-git-send-email-nab@linux-iscsi.org>

From: Bart Van Assche <bvanassche@acm.org>

Multipart RDMA transfers can fail after one or more but not all RDMA
transfers have been initiated because either an IB cable has been pulled
or the ib_srpt kernel module has been unloaded while an RDMA transfer is
being setup.

This is a bugfix port from SCST svn r3632 as recommended by Bart Van
Assche.

Cc: Bart Van Assche <bvanassche@acm.org>
Cc: Roland Dreier <roland@purestorage.com>
Signed-off-by: Nicholas A. Bellinger <nab@linux-iscsi.org>
---
 drivers/infiniband/ulp/srpt/ib_srpt.c |  101 +++++++++++++++++++++-----------
 drivers/infiniband/ulp/srpt/ib_srpt.h |   26 +++++++-
 2 files changed, 88 insertions(+), 39 deletions(-)

diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index 383994d..6aba709 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -807,7 +807,7 @@ static int srpt_post_recv(struct srpt_device *sdev,
 	struct ib_recv_wr wr, *bad_wr;
 
 	BUG_ON(!sdev);
-	wr.wr_id = encode_wr_id(IB_WC_RECV, ioctx->ioctx.index);
+	wr.wr_id = encode_wr_id(SRPT_RECV, ioctx->ioctx.index);
 
 	list.addr = ioctx->ioctx.dma;
 	list.length = srp_max_req_size;
@@ -849,7 +849,7 @@ static int srpt_post_send(struct srpt_rdma_ch *ch,
 	list.lkey = sdev->mr->lkey;
 
 	wr.next = NULL;
-	wr.wr_id = encode_wr_id(IB_WC_SEND, ioctx->ioctx.index);
+	wr.wr_id = encode_wr_id(SRPT_SEND, ioctx->ioctx.index);
 	wr.sg_list = &list;
 	wr.num_sge = 1;
 	wr.opcode = IB_WR_SEND;
@@ -1494,17 +1494,26 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch,
  * check_stop_free() callback.
  */
 static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
-				  struct srpt_send_ioctx *ioctx)
+				  struct srpt_send_ioctx *ioctx,
+				  enum srpt_opcode opcode)
 {
 	WARN_ON(ioctx->n_rdma <= 0);
 	atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);
 
-	if (srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA,
-					SRPT_STATE_DATA_IN))
-		transport_generic_handle_data(&ioctx->cmd);
-	else
-		printk(KERN_ERR "%s[%d]: wrong state = %d\n", __func__,
-		       __LINE__, srpt_get_cmd_state(ioctx));
+	if (opcode == SRPT_RDMA_READ_LAST) {
+		if (srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA,
+						SRPT_STATE_DATA_IN))
+			transport_generic_handle_data(&ioctx->cmd);
+		else
+			printk(KERN_ERR "%s[%d]: wrong state = %d\n", __func__,
+			       __LINE__, srpt_get_cmd_state(ioctx));
+	} else if (opcode == SRPT_RDMA_ABORT) {
+		ioctx->rdma_aborted = true;
+	} else {
+		WARN_ON(opcode != SRPT_RDMA_READ_LAST);
+		printk(KERN_ERR "%s[%d]: scmnd == NULL (opcode %d)", __func__,
+				__LINE__, opcode);
+	}
 }
 
 /**
@@ -1512,7 +1521,7 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
  */
 static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch,
 				      struct srpt_send_ioctx *ioctx,
-				      u8 opcode)
+				      enum srpt_opcode opcode)
 {
 	struct se_cmd *cmd;
 	enum srpt_command_state state;
@@ -1520,7 +1529,7 @@ static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch,
 	cmd = &ioctx->cmd;
 	state = srpt_get_cmd_state(ioctx);
 	switch (opcode) {
-	case IB_WC_RDMA_READ:
+	case SRPT_RDMA_READ_LAST:
 		if (ioctx->n_rdma <= 0) {
 			printk(KERN_ERR "Received invalid RDMA read"
 			       " error completion with idx %d\n",
@@ -1534,9 +1543,8 @@ static void srpt_handle_rdma_err_comp(struct srpt_rdma_ch *ch,
 			printk(KERN_ERR "%s[%d]: wrong state = %d\n",
 			       __func__, __LINE__, state);
 		break;
-	case IB_WC_RDMA_WRITE:
-		atomic_set(&ioctx->cmd.transport_lun_stop,
-			   1);
+	case SRPT_RDMA_WRITE_LAST:
+		atomic_set(&ioctx->cmd.transport_lun_stop, 1);
 		break;
 	default:
 		printk(KERN_ERR "%s[%d]: opcode = %u\n", __func__,
@@ -2041,33 +2049,32 @@ static void srpt_process_send_completion(struct ib_cq *cq,
 {
 	struct srpt_send_ioctx *send_ioctx;
 	uint32_t index;
-	u8 opcode;
+	enum srpt_opcode opcode;
 
 	index = idx_from_wr_id(wc->wr_id);
 	opcode = opcode_from_wr_id(wc->wr_id);
 	send_ioctx = ch->ioctx_ring[index];
 	if (wc->status == IB_WC_SUCCESS) {
-		if (opcode == IB_WC_SEND)
+		if (opcode == SRPT_SEND)
 			srpt_handle_send_comp(ch, send_ioctx);
 		else {
-			WARN_ON(wc->opcode != IB_WC_RDMA_READ);
-			srpt_handle_rdma_comp(ch, send_ioctx);
+			WARN_ON(opcode != SRPT_RDMA_ABORT &&
+				wc->opcode != IB_WC_RDMA_READ);
+			srpt_handle_rdma_comp(ch, send_ioctx, opcode);
 		}
 	} else {
-		if (opcode == IB_WC_SEND) {
+		if (opcode == SRPT_SEND) {
 			printk(KERN_INFO "sending response for idx %u failed"
 			       " with status %d\n", index, wc->status);
 			srpt_handle_send_err_comp(ch, wc->wr_id);
-		} else {
-			printk(KERN_INFO "RDMA %s for idx %u failed with status"
-			       " %d\n", opcode == IB_WC_RDMA_READ ? "read"
-			       : opcode == IB_WC_RDMA_WRITE ? "write"
-			       : "???", index, wc->status);
+		} else if (opcode != SRPT_RDMA_MID) {
+			printk(KERN_INFO "RDMA t %d for idx %u failed with"
+				" status %d", opcode, index, wc->status);
 			srpt_handle_rdma_err_comp(ch, send_ioctx, opcode);
 		}
 	}
 
-	while (unlikely(opcode == IB_WC_SEND
+	while (unlikely(opcode == SRPT_SEND
 			&& !list_empty(&ch->cmd_wait_list)
 			&& srpt_get_ch_state(ch) == CH_LIVE
 			&& (send_ioctx = srpt_get_send_ioctx(ch)) != NULL)) {
@@ -2091,7 +2098,7 @@ static void srpt_process_completion(struct ib_cq *cq, struct srpt_rdma_ch *ch)
 	ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
 	while ((n = ib_poll_cq(cq, ARRAY_SIZE(ch->wc), wc)) > 0) {
 		for (i = 0; i < n; i++) {
-			if (opcode_from_wr_id(wc[i].wr_id) & IB_WC_RECV)
+			if (opcode_from_wr_id(wc[i].wr_id) == SRPT_RECV)
 				srpt_process_rcv_completion(cq, ch, &wc[i]);
 			else
 				srpt_process_send_completion(cq, ch, &wc[i]);
@@ -2882,32 +2889,37 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
 	int ret;
 	int sq_wr_avail;
 	enum dma_data_direction dir;
+	const int n_rdma = ioctx->n_rdma;
 
 	dir = ioctx->cmd.data_direction;
 	if (dir == DMA_TO_DEVICE) {
 		/* write */
 		ret = -ENOMEM;
-		sq_wr_avail = atomic_sub_return(ioctx->n_rdma,
-						 &ch->sq_wr_avail);
+		sq_wr_avail = atomic_sub_return(n_rdma, &ch->sq_wr_avail);
 		if (sq_wr_avail < 0) {
 			printk(KERN_WARNING "IB send queue full (needed %d)\n",
-			       ioctx->n_rdma);
+			       n_rdma);
 			goto out;
 		}
 	}
 
+	ioctx->rdma_aborted = false;
 	ret = 0;
 	riu = ioctx->rdma_ius;
 	memset(&wr, 0, sizeof wr);
 
-	for (i = 0; i < ioctx->n_rdma; ++i, ++riu) {
+	for (i = 0; i < n_rdma; ++i, ++riu) {
 		if (dir == DMA_FROM_DEVICE) {
 			wr.opcode = IB_WR_RDMA_WRITE;
-			wr.wr_id = encode_wr_id(IB_WC_RDMA_WRITE,
+			wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
+						SRPT_RDMA_WRITE_LAST :
+						SRPT_RDMA_MID,
 						ioctx->ioctx.index);
 		} else {
 			wr.opcode = IB_WR_RDMA_READ;
-			wr.wr_id = encode_wr_id(IB_WC_RDMA_READ,
+			wr.wr_id = encode_wr_id(i == n_rdma - 1 ?
+						SRPT_RDMA_READ_LAST :
+						SRPT_RDMA_MID,
 						ioctx->ioctx.index);
 		}
 		wr.next = NULL;
@@ -2917,17 +2929,36 @@ static int srpt_perform_rdmas(struct srpt_rdma_ch *ch,
 		wr.sg_list = riu->sge;
 
 		/* only get completion event for the last rdma write */
-		if (i == (ioctx->n_rdma - 1) && dir == DMA_TO_DEVICE)
+		if (i == (n_rdma - 1) && dir == DMA_TO_DEVICE)
 			wr.send_flags = IB_SEND_SIGNALED;
 
 		ret = ib_post_send(ch->qp, &wr, &bad_wr);
 		if (ret)
-			goto out;
+			break;
 	}
 
+	if (ret)
+		printk(KERN_ERR "%s[%d]: ib_post_send() returned %d for %d/%d",
+				 __func__, __LINE__, ret, i, n_rdma);
+	if (ret && i > 0) {
+		wr.num_sge = 0;
+		wr.wr_id = encode_wr_id(SRPT_RDMA_ABORT, ioctx->ioctx.index);
+		wr.send_flags = IB_SEND_SIGNALED;
+		while (ch->state == CH_LIVE &&
+			ib_post_send(ch->qp, &wr, &bad_wr) != 0) {
+			printk(KERN_INFO "Trying to abort failed RDMA transfer [%d]",
+				ioctx->ioctx.index);
+			msleep(1000);
+		}
+		while (ch->state != CH_RELEASING && !ioctx->rdma_aborted) {
+			printk(KERN_INFO "Waiting until RDMA abort finished [%d]",
+				ioctx->ioctx.index);
+			msleep(1000);
+		}
+	}
 out:
 	if (unlikely(dir == DMA_TO_DEVICE && ret < 0))
-		atomic_add(ioctx->n_rdma, &ch->sq_wr_avail);
+		atomic_add(n_rdma, &ch->sq_wr_avail);
 	return ret;
 }
 
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h
index 045fb7b..59ee2d7 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.h
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.h
@@ -127,12 +127,27 @@ enum {
 	DEFAULT_MAX_RDMA_SIZE = 65536,
 };
 
+enum srpt_opcode {
+	SRPT_RECV,
+	SRPT_SEND,
+	SRPT_RDMA_MID,
+	SRPT_RDMA_ABORT,
+	SRPT_RDMA_READ_LAST,
+	SRPT_RDMA_WRITE_LAST,
+};
+
 static inline u64 encode_wr_id(u8 opcode, u32 idx)
-{ return ((u64)opcode << 32) | idx; }
-static inline u8 opcode_from_wr_id(u64 wr_id)
-{ return wr_id >> 32; }
+{
+	return ((u64)opcode << 32) | idx;
+}
+static inline enum srpt_opcode opcode_from_wr_id(u64 wr_id)
+{
+	return wr_id >> 32;
+}
 static inline u32 idx_from_wr_id(u64 wr_id)
-{ return (u32)wr_id; }
+{
+	return (u32)wr_id;
+}
 
 struct rdma_iu {
 	u64		raddr;
@@ -204,6 +219,8 @@ struct srpt_recv_ioctx {
  * @tag:         Tag of the received SRP information unit.
  * @spinlock:    Protects 'state'.
  * @state:       I/O context state.
+ * @rdma_aborted: If initiating a multipart RDMA transfer failed, whether
+ * 		 the already initiated transfers have finished.
  * @cmd:         Target core command data structure.
  * @sense_data:  SCSI sense data.
  */
@@ -218,6 +235,7 @@ struct srpt_send_ioctx {
 	struct list_head	free_list;
 	spinlock_t		spinlock;
 	enum srpt_command_state	state;
+	bool			rdma_aborted;
 	struct se_cmd		cmd;
 	struct completion	tx_done;
 	u64			tag;
-- 
1.7.2.5


  parent reply	other threads:[~2011-10-24  5:33 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-10-24  5:33 [PATCH 0/9] ib_srpt: Changes from RFC for v3.2-rc1 mainline merge Nicholas A. Bellinger
2011-10-24  5:33 ` [PATCH 1/9] ib_srpt: Fix potential out-of-bounds array access Nicholas A. Bellinger
2011-10-24  5:33 ` Nicholas A. Bellinger [this message]
2011-10-24  5:33 ` [PATCH 3/9] ib_srpt: Fix srpt_alloc_fabric_acl failure case return value Nicholas A. Bellinger
2011-10-24  5:33 ` [PATCH 4/9] ib_srpt: Update comments to reference $driver/$port layout Nicholas A. Bellinger
2011-10-24  5:33 ` [PATCH 5/9] ib_srpt: Fix sport->port_guid formatting code Nicholas A. Bellinger
     [not found]   ` <1319434422-15354-6-git-send-email-nab-IzHhD5pYlfBP7FQvKIMDCQ@public.gmane.org>
2011-10-24 19:57     ` Bart Van Assche
2011-10-24 20:25       ` Nicholas A. Bellinger
     [not found]         ` <1319487952.17450.72.camel-Y1+j5t8j3WgjMeEPmliV8E/sVC8ogwMJ@public.gmane.org>
2011-10-26 18:23           ` Bart Van Assche
     [not found]             ` <CAO+b5-qjOT2rqeLn=DJi5ogk+KTV8_Fi0tYwj4gECtcSNNhHRQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-10-27  0:37               ` Nicholas A. Bellinger
2011-10-24  5:33 ` [PATCH 6/9] ib_srpt: Remove legacy use_port_guid_in_session_name module parameter Nicholas A. Bellinger
     [not found]   ` <1319434422-15354-7-git-send-email-nab-IzHhD5pYlfBP7FQvKIMDCQ@public.gmane.org>
2011-10-24 18:24     ` Bart Van Assche
2011-10-24  5:33 ` [PATCH 7/9] ib_srpt: Convert srp_max_rdma_size into per port configfs attribute Nicholas A. Bellinger
     [not found]   ` <1319434422-15354-8-git-send-email-nab-IzHhD5pYlfBP7FQvKIMDCQ@public.gmane.org>
2011-10-24 16:34     ` Bart Van Assche
2011-10-24 18:27       ` Nicholas A. Bellinger
2011-10-24 20:29   ` Nicholas A. Bellinger
     [not found]     ` <1319488195.17450.73.camel-Y1+j5t8j3WgjMeEPmliV8E/sVC8ogwMJ@public.gmane.org>
2011-10-25  6:22       ` Nicholas A. Bellinger
2011-10-25 10:32       ` Bart Van Assche
     [not found]         ` <CAO+b5-p9xXB_sWes=uet6skkFn=xWD+vKuoOeuGwjbxYhE-ctg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-10-25 10:35           ` Nicholas A. Bellinger
2011-10-24  5:33 ` [PATCH 8/9] ib_srpt: Convert srp_max_rsp_size " Nicholas A. Bellinger
     [not found]   ` <1319434422-15354-9-git-send-email-nab-IzHhD5pYlfBP7FQvKIMDCQ@public.gmane.org>
2011-10-24 19:44     ` Bart Van Assche
     [not found]       ` <CAO+b5-p24uYKbwqCRWVik63gL-ZABgcJrqAi7ULJZEP+CK1WEg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-10-24 19:49         ` Nicholas A. Bellinger
     [not found]           ` <1319485752.17450.57.camel-Y1+j5t8j3WgjMeEPmliV8E/sVC8ogwMJ@public.gmane.org>
2011-10-24 19:58             ` Bart Van Assche
2011-10-24 20:05               ` Nicholas A. Bellinger
     [not found]                 ` <1319486723.17450.59.camel-Y1+j5t8j3WgjMeEPmliV8E/sVC8ogwMJ@public.gmane.org>
2011-10-24 20:11                   ` Bart Van Assche
2011-10-24 20:19                     ` Nicholas A. Bellinger
2011-10-24 20:16             ` Bart Van Assche
     [not found]               ` <CAO+b5-rzo478a07CuaYS2itAdV9dK65+GHj2Si4PZFM6qkmL3A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2011-10-24 20:22                 ` Nicholas A. Bellinger
2011-10-24  5:33 ` [PATCH 9/9] ib_srpt: Convert srpt_sq_size " Nicholas A. Bellinger
     [not found]   ` <1319434422-15354-10-git-send-email-nab-IzHhD5pYlfBP7FQvKIMDCQ@public.gmane.org>
2011-10-24 18:32     ` Bart Van Assche
2011-10-24 18:39       ` Nicholas A. Bellinger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1319434422-15354-3-git-send-email-nab@linux-iscsi.org \
    --to=nab@linux-iscsi.org \
    --cc=bvanassche@acm.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=roland@purestorage.com \
    --cc=target-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox