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
next prev 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.