[RHEL7,COMMIT] fs/fuse kio: post rdma work requests only after connection is established

Submitted by Vasily Averin on Nov. 10, 2020, 10:43 a.m.

Details

Message ID 202011101043.0AAAhxiO010372@vz7build.vvs.sw.ru
State New
Series "fs/fuse kio: post rdma work requests only after connection is established"
Headers show

Commit Message

Vasily Averin Nov. 10, 2020, 10:43 a.m.
The commit is pushed to "branch-rh7-3.10.0-1160.2.2.vz7.170.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.2.2.el7
------>
commit c9c8d2e99a62df4b3ecfa7a6fbc27c491b5bba5f
Author: Ildar Ismagilov <ildar.ismagilov@virtuozzo.com>
Date:   Tue Nov 10 13:43:59 2020 +0300

    fs/fuse kio: post rdma work requests only after connection is established
    
    Some RDMA drivers only generate completions for work requests
    that are posted after connection is established. And if connection
    is rejected our posted works will never be completed, as result we
    have a resource leak. To fix this problem we don't post work requests
    until connection is established.
    
    https://pmc.acronis.com/browse/VSTOR-38116
    
    Signed-off-by: Ildar Ismagilov <ildar.ismagilov@virtuozzo.com>
    Reviewed-by: Andrey Zaitsev <azaitsev@virtuozzo.com>
---
 fs/fuse/kio/pcs/pcs_rdma_conn.c |  4 ++++
 fs/fuse/kio/pcs/pcs_rdma_io.c   | 25 +++++++++++++------------
 fs/fuse/kio/pcs/pcs_rdma_io.h   |  1 +
 3 files changed, 18 insertions(+), 12 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/fuse/kio/pcs/pcs_rdma_conn.c b/fs/fuse/kio/pcs/pcs_rdma_conn.c
index 521089c..4db9031 100644
--- a/fs/fuse/kio/pcs/pcs_rdma_conn.c
+++ b/fs/fuse/kio/pcs/pcs_rdma_conn.c
@@ -80,6 +80,10 @@  static int pcs_rdma_cm_event_handler(struct rdma_cm_id *cmid,
 			break;
 		case RDMA_CM_EVENT_ESTABLISHED:
 			cmid->context = &rc->rio->id;
+			if (pcs_rdma_established(rc->rio)) {
+				TRACE("pcs_rdma_established failed, rio: 0x%p\n", rc->rio);
+				rc->cm_event = RDMA_CM_EVENT_REJECTED;
+			}
 			complete(&rc->cm_done);
 			break;
 		case RDMA_CM_EVENT_REJECTED:
diff --git a/fs/fuse/kio/pcs/pcs_rdma_io.c b/fs/fuse/kio/pcs/pcs_rdma_io.c
index dc55a9c..5955716 100644
--- a/fs/fuse/kio/pcs/pcs_rdma_io.c
+++ b/fs/fuse/kio/pcs/pcs_rdma_io.c
@@ -1183,7 +1183,6 @@  struct pcs_rdmaio* pcs_rdma_create(int hdr_size, struct rdma_cm_id *cmid,
 				   int queue_depth, struct pcs_rpc *ep)
 {
 	struct pcs_rdmaio *rio;
-	struct rio_rx *rx;
 	struct ib_cq_init_attr cq_attr = {};
 	struct ib_qp_init_attr qp_attr = {};
 	int recv_queue_depth = queue_depth * 2 + 2;
@@ -1304,21 +1303,10 @@  struct pcs_rdmaio* pcs_rdma_create(int hdr_size, struct rdma_cm_id *cmid,
 		goto free_cq;
 	}
 
-	for (rx = rio->rx_descs; rx - rio->rx_descs < recv_queue_depth; rx++)
-		if (rio_rx_post(rio, rx, RIO_MSG_SIZE)) {
-			TRACE("rio_rx_post failed: rio: 0x%p\n", rio);
-			break;
-		}
-
-	if (rio->n_rx_posted != recv_queue_depth)
-		goto free_qp;
-
 	TRACE("rio: 0x%p, dev: 0x%p, queue_depth: %d\n", rio, rio->dev, queue_depth);
 
 	return rio;
 
-free_qp:
-	rdma_destroy_qp(rio->cmid);
 free_cq:
 	ib_destroy_cq(rio->cq);
 free_dev:
@@ -1333,6 +1321,19 @@  free_rio:
 	return NULL;
 }
 
+int pcs_rdma_established(struct pcs_rdmaio *rio)
+{
+	struct rio_rx *rx;
+
+	for (rx = rio->rx_descs; rx - rio->rx_descs < rio->recv_queue_depth; rx++)
+		if (rio_rx_post(rio, rx, RIO_MSG_SIZE)) {
+			TRACE("rio_rx_post failed: rio: 0x%p\n", rio);
+			break;
+		}
+
+	return rio->n_rx_posted == rio->recv_queue_depth ? 0 : -EINVAL;
+}
+
 static void rio_cleanup(struct pcs_rdmaio *rio)
 {
 	rio_perform_tx_jobs(rio);
diff --git a/fs/fuse/kio/pcs/pcs_rdma_io.h b/fs/fuse/kio/pcs/pcs_rdma_io.h
index b411098e..69d817d 100644
--- a/fs/fuse/kio/pcs/pcs_rdma_io.h
+++ b/fs/fuse/kio/pcs/pcs_rdma_io.h
@@ -106,6 +106,7 @@  struct pcs_rdmaio
 
 struct pcs_rdmaio* pcs_rdma_create(int hdr_size, struct rdma_cm_id *cmid,
 		int queue_depth, struct pcs_rpc *ep);
+int pcs_rdma_established(struct pcs_rdmaio *rio);
 void pcs_rdma_destroy(struct pcs_rdmaio *rio);
 void pcs_rdma_ioconn_destruct(struct pcs_ioconn *ioconn);