Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1268951 > unrolled thread
| Started by | Christoph Hellwig <hch@lst.de> |
|---|---|
| First post | 2015-11-13 15:00 +0100 |
| Last post | 2015-11-15 10:40 +0100 |
| Articles | 4 — 3 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH 3/9] IB: add a helper to safely drain a QP Christoph Hellwig <hch@lst.de> - 2015-11-13 15:00 +0100
Re: [PATCH 3/9] IB: add a helper to safely drain a QP Steve Wise <swise@opengridcomputing.com> - 2015-11-13 17:20 +0100
Re: [PATCH 3/9] IB: add a helper to safely drain a QP Christoph Hellwig <hch@lst.de> - 2015-11-14 08:10 +0100
Re: [PATCH 3/9] IB: add a helper to safely drain a QP Sagi Grimberg <sagig@dev.mellanox.co.il> - 2015-11-15 10:40 +0100
| From | Christoph Hellwig <hch@lst.de> |
|---|---|
| Date | 2015-11-13 15:00 +0100 |
| Subject | [PATCH 3/9] IB: add a helper to safely drain a QP |
| Message-ID | <qun3t-77o-23@gated-at.bofh.it> |
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
drivers/infiniband/core/cq.c | 46 ++++++++++++++++++++++++++++++++++++++++++++
include/rdma/ib_verbs.h | 2 ++
2 files changed, 48 insertions(+)
diff --git a/drivers/infiniband/core/cq.c b/drivers/infiniband/core/cq.c
index d9eb796..bf2a079 100644
--- a/drivers/infiniband/core/cq.c
+++ b/drivers/infiniband/core/cq.c
@@ -206,3 +206,49 @@ void ib_free_cq(struct ib_cq *cq)
WARN_ON_ONCE(ret);
}
EXPORT_SYMBOL(ib_free_cq);
+
+struct ib_stop_cqe {
+ struct ib_cqe cqe;
+ struct completion done;
+};
+
+static void ib_stop_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct ib_stop_cqe *stop =
+ container_of(wc->wr_cqe, struct ib_stop_cqe, cqe);
+
+ complete(&stop->done);
+}
+
+/*
+ * Change a queue pair into the error state and wait until all receive
+ * completions have been processed before destroying it. This avoids that
+ * the receive completion handler can access the queue pair while it is
+ * being destroyed.
+ */
+void ib_drain_qp(struct ib_qp *qp)
+{
+ struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
+ struct ib_stop_cqe stop = { };
+ struct ib_recv_wr wr, *bad_wr;
+ int ret;
+
+ wr.wr_cqe = &stop.cqe;
+ stop.cqe.done = ib_stop_done;
+ init_completion(&stop.done);
+
+ ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
+ if (ret) {
+ WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
+ return;
+ }
+
+ ret = ib_post_recv(qp, &wr, &bad_wr);
+ if (ret) {
+ WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
+ return;
+ }
+
+ wait_for_completion(&stop.done);
+}
+EXPORT_SYMBOL(ib_drain_qp);
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index e11e038..f59a8d3 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -3075,4 +3075,6 @@ int ib_sg_to_pages(struct ib_mr *mr,
int sg_nents,
int (*set_page)(struct ib_mr *, u64));
+void ib_drain_qp(struct ib_qp *qp);
+
#endif /* IB_VERBS_H */
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Steve Wise <swise@opengridcomputing.com> |
|---|---|
| Date | 2015-11-13 17:20 +0100 |
| Message-ID | <qupeW-eJ-5@gated-at.bofh.it> |
| In reply to | #1268951 |
On 11/13/2015 7:46 AM, Christoph Hellwig wrote:
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
> drivers/infiniband/core/cq.c | 46 ++++++++++++++++++++++++++++++++++++++++++++
> include/rdma/ib_verbs.h | 2 ++
> 2 files changed, 48 insertions(+)
>
> diff --git a/drivers/infiniband/core/cq.c b/drivers/infiniband/core/cq.c
> index d9eb796..bf2a079 100644
> --- a/drivers/infiniband/core/cq.c
> +++ b/drivers/infiniband/core/cq.c
> @@ -206,3 +206,49 @@ void ib_free_cq(struct ib_cq *cq)
> WARN_ON_ONCE(ret);
> }
> EXPORT_SYMBOL(ib_free_cq);
> +
> +struct ib_stop_cqe {
> + struct ib_cqe cqe;
> + struct completion done;
> +};
> +
> +static void ib_stop_done(struct ib_cq *cq, struct ib_wc *wc)
> +{
> + struct ib_stop_cqe *stop =
> + container_of(wc->wr_cqe, struct ib_stop_cqe, cqe);
> +
> + complete(&stop->done);
> +}
> +
> +/*
> + * Change a queue pair into the error state and wait until all receive
> + * completions have been processed before destroying it. This avoids that
> + * the receive completion handler can access the queue pair while it is
> + * being destroyed.
> + */
> +void ib_drain_qp(struct ib_qp *qp)
> +{
> + struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
> + struct ib_stop_cqe stop = { };
> + struct ib_recv_wr wr, *bad_wr;
> + int ret;
> +
> + wr.wr_cqe = &stop.cqe;
> + stop.cqe.done = ib_stop_done;
> + init_completion(&stop.done);
> +
> + ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
> + if (ret) {
> + WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
> + return;
> + }
> +
> + ret = ib_post_recv(qp, &wr, &bad_wr);
> + if (ret) {
> + WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
> + return;
> + }
> +
> + wait_for_completion(&stop.done);
> +}
> +EXPORT_SYMBOL(ib_drain_qp);
This won't work with iwarp qps. Once the QP is in ERROR state,
post_send/post_recv can return a synchronous error vs async via the
cq. The IB spec explicitly states that posts while in ERROR will be
completed with "flushed" via the CQ.
From http://tools.ietf.org/html/draft-hilland-rddp-verbs-00#section-6.2.4:
* At some point in the execution of the flushing operation, the RI
MUST begin to return an Immediate Error for any attempt to post
a WR to a Work Queue; prior to that point, any WQEs posted to a
Work Queue MUST be enqueued and then flushed as described above
(e.g. The PostSQ is done in Non-Privileged Mode and the Non-
Privileged Mode portion of the RI has not yet been informed that
the QP is in the Error state).
Also pending send work requests can be completed with status "flushed",
and I would think we need to do something similar for send wrs. We
definitely can see this with cxgb4 in the presence of unsignaled wrs
that aren't followed by a signaled wr at the time the QP is moved out of
RTS. The driver has no way to know if these pending unsignaled wrs
completed or not. So it completes them with "flushed" status.
So how can we do this for iwarp? It seems like all that might be needed
is to modify the QP state to idle, retrying until it succeeds:
If the QP is transitioning to the Error state, or has not yet
finished flushing the Work Queues, a Modify QP request to transition
to the IDLE state MUST fail with an Immediate Error. If none of the
prior conditions are true, a Modify QP to the Idle state MUST take
the QP to the Idle state. No other state transitions out of Error
are supported. Any attempt to transition the QP to a state other
than Idle MUST result in an Immediate Error.
Steve.
> diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
> index e11e038..f59a8d3 100644
> --- a/include/rdma/ib_verbs.h
> +++ b/include/rdma/ib_verbs.h
> @@ -3075,4 +3075,6 @@ int ib_sg_to_pages(struct ib_mr *mr,
> int sg_nents,
> int (*set_page)(struct ib_mr *, u64));
>
> +void ib_drain_qp(struct ib_qp *qp);
> +
> #endif /* IB_VERBS_H */
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Christoph Hellwig <hch@lst.de> |
|---|---|
| Date | 2015-11-14 08:10 +0100 |
| Message-ID | <quD8d-Wt-1@gated-at.bofh.it> |
| In reply to | #1269053 |
On Fri, Nov 13, 2015 at 10:16:04AM -0600, Steve Wise wrote: > So how can we do this for iwarp? It seems like all that might be needed is > to modify the QP state to idle, retrying until it succeeds: > > If the QP is transitioning to the Error state, or has not yet > finished flushing the Work Queues, a Modify QP request to transition > to the IDLE state MUST fail with an Immediate Error. If none of the > prior conditions are true, a Modify QP to the Idle state MUST take > the QP to the Idle state. No other state transitions out of Error > are supported. Any attempt to transition the QP to a state other > than Idle MUST result in an Immediate Error. Can you try to write up some code for this? We could then wire it up in the common helper. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Sagi Grimberg <sagig@dev.mellanox.co.il> |
|---|---|
| Date | 2015-11-15 10:40 +0100 |
| Message-ID | <qv1WW-81C-1@gated-at.bofh.it> |
| In reply to | #1268951 |
> +
> +struct ib_stop_cqe {
> + struct ib_cqe cqe;
> + struct completion done;
> +};
> +
> +static void ib_stop_done(struct ib_cq *cq, struct ib_wc *wc)
> +{
> + struct ib_stop_cqe *stop =
> + container_of(wc->wr_cqe, struct ib_stop_cqe, cqe);
> +
> + complete(&stop->done);
> +}
> +
> +/*
> + * Change a queue pair into the error state and wait until all receive
> + * completions have been processed before destroying it. This avoids that
> + * the receive completion handler can access the queue pair while it is
> + * being destroyed.
> + */
> +void ib_drain_qp(struct ib_qp *qp)
> +{
> + struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
> + struct ib_stop_cqe stop = { };
> + struct ib_recv_wr wr, *bad_wr;
> + int ret;
> +
> + wr.wr_cqe = &stop.cqe;
> + stop.cqe.done = ib_stop_done;
> + init_completion(&stop.done);
> +
> + ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
> + if (ret) {
> + WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
> + return;
> + }
> +
> + ret = ib_post_recv(qp, &wr, &bad_wr);
> + if (ret) {
> + WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
> + return;
> + }
> +
> + wait_for_completion(&stop.done);
> +}
This is taken from srp, and srp drains using a recv wr due to a race
causing a use-after-free condition in srp which re-posts a recv buffer
in the recv completion handler. srp does not really care if there are
pending send flushes.
I'm not sure if there are ordering rules for send/recv queues in
terms of flush completions, meaning that even if all recv flushes
were consumed maybe there are send flushes still pending.
I think that for a general drain helper it would be useful to
make sure that both the recv _and_ send flushes were drained.
So, something like:
void ib_drain_qp(struct ib_qp *qp)
{
struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
struct ib_stop_cqe rstop, sstop;
struct ib_recv_wr rwr = {}, *bad_rwr;
struct ib_send_wr swr = {}, *bad_swr;
int ret;
rwr.wr_cqe = &rstop.cqe;
rstop.cqe.done = ib_stop_done;
init_completion(&rstop.done);
swr.wr_cqe = &sstop.cqe;
sstop.cqe.done = ib_stop_done;
init_completion(&sstop.done);
ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
if (ret) {
WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
return;
}
ret = ib_post_recv(qp, &rwr, &bad_rwr);
if (ret) {
WARN_ONCE(ret, "failed to drain recv queue: %d\n", ret);
return;
}
ret = ib_post_send(qp, &swr, &bad_swr);
if (ret) {
WARN_ONCE(ret, "failed to drain send queue: %d\n", ret);
return;
}
wait_for_completion(&rstop.done);
wait_for_completion(&sstop.done);
}
Thoughts?
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web