Browse Source

Merge branch 'smc-fixes'

Ursula Braun says:

====================
net/smc: fixes 2018/05/03

here are smc fixes for 2 problems:
 * receive buffers in SMC must be registered. If registration fails
   these buffers must not be kept within the link group for reuse.
   Patch 1 is a preparational patch; patch 2 contains the fix.
 * sendpage: do not hold the sock lock when calling kernel_sendpage()
             or sock_no_sendpage()
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
David S. Miller 7 years ago
parent
commit
31140b47fe
3 changed files with 42 additions and 26 deletions
  1. 21 22
      net/smc/af_smc.c
  2. 19 3
      net/smc/smc_core.c
  3. 2 1
      net/smc/smc_core.h

+ 21 - 22
net/smc/af_smc.c

@@ -292,6 +292,17 @@ static void smc_copy_sock_settings_to_smc(struct smc_sock *smc)
 	smc_copy_sock_settings(&smc->sk, smc->clcsock->sk, SK_FLAGS_CLC_TO_SMC);
 	smc_copy_sock_settings(&smc->sk, smc->clcsock->sk, SK_FLAGS_CLC_TO_SMC);
 }
 }
 
 
+/* register a new rmb */
+static int smc_reg_rmb(struct smc_link *link, struct smc_buf_desc *rmb_desc)
+{
+	/* register memory region for new rmb */
+	if (smc_wr_reg_send(link, rmb_desc->mr_rx[SMC_SINGLE_LINK])) {
+		rmb_desc->regerr = 1;
+		return -EFAULT;
+	}
+	return 0;
+}
+
 static int smc_clnt_conf_first_link(struct smc_sock *smc)
 static int smc_clnt_conf_first_link(struct smc_sock *smc)
 {
 {
 	struct smc_link_group *lgr = smc->conn.lgr;
 	struct smc_link_group *lgr = smc->conn.lgr;
@@ -321,9 +332,7 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc)
 
 
 	smc_wr_remember_qp_attr(link);
 	smc_wr_remember_qp_attr(link);
 
 
-	rc = smc_wr_reg_send(link,
-			     smc->conn.rmb_desc->mr_rx[SMC_SINGLE_LINK]);
-	if (rc)
+	if (smc_reg_rmb(link, smc->conn.rmb_desc))
 		return SMC_CLC_DECL_INTERR;
 		return SMC_CLC_DECL_INTERR;
 
 
 	/* send CONFIRM LINK response over RoCE fabric */
 	/* send CONFIRM LINK response over RoCE fabric */
@@ -473,13 +482,8 @@ static int smc_connect_rdma(struct smc_sock *smc)
 			goto decline_rdma_unlock;
 			goto decline_rdma_unlock;
 		}
 		}
 	} else {
 	} else {
-		struct smc_buf_desc *buf_desc = smc->conn.rmb_desc;
-
-		if (!buf_desc->reused) {
-			/* register memory region for new rmb */
-			rc = smc_wr_reg_send(link,
-					     buf_desc->mr_rx[SMC_SINGLE_LINK]);
-			if (rc) {
+		if (!smc->conn.rmb_desc->reused) {
+			if (smc_reg_rmb(link, smc->conn.rmb_desc)) {
 				reason_code = SMC_CLC_DECL_INTERR;
 				reason_code = SMC_CLC_DECL_INTERR;
 				goto decline_rdma_unlock;
 				goto decline_rdma_unlock;
 			}
 			}
@@ -719,9 +723,7 @@ static int smc_serv_conf_first_link(struct smc_sock *smc)
 
 
 	link = &lgr->lnk[SMC_SINGLE_LINK];
 	link = &lgr->lnk[SMC_SINGLE_LINK];
 
 
-	rc = smc_wr_reg_send(link,
-			     smc->conn.rmb_desc->mr_rx[SMC_SINGLE_LINK]);
-	if (rc)
+	if (smc_reg_rmb(link, smc->conn.rmb_desc))
 		return SMC_CLC_DECL_INTERR;
 		return SMC_CLC_DECL_INTERR;
 
 
 	/* send CONFIRM LINK request to client over the RoCE fabric */
 	/* send CONFIRM LINK request to client over the RoCE fabric */
@@ -854,13 +856,8 @@ static void smc_listen_work(struct work_struct *work)
 	smc_rx_init(new_smc);
 	smc_rx_init(new_smc);
 
 
 	if (local_contact != SMC_FIRST_CONTACT) {
 	if (local_contact != SMC_FIRST_CONTACT) {
-		struct smc_buf_desc *buf_desc = new_smc->conn.rmb_desc;
-
-		if (!buf_desc->reused) {
-			/* register memory region for new rmb */
-			rc = smc_wr_reg_send(link,
-					     buf_desc->mr_rx[SMC_SINGLE_LINK]);
-			if (rc) {
+		if (!new_smc->conn.rmb_desc->reused) {
+			if (smc_reg_rmb(link, new_smc->conn.rmb_desc)) {
 				reason_code = SMC_CLC_DECL_INTERR;
 				reason_code = SMC_CLC_DECL_INTERR;
 				goto decline_rdma_unlock;
 				goto decline_rdma_unlock;
 			}
 			}
@@ -1318,8 +1315,11 @@ static ssize_t smc_sendpage(struct socket *sock, struct page *page,
 
 
 	smc = smc_sk(sk);
 	smc = smc_sk(sk);
 	lock_sock(sk);
 	lock_sock(sk);
-	if (sk->sk_state != SMC_ACTIVE)
+	if (sk->sk_state != SMC_ACTIVE) {
+		release_sock(sk);
 		goto out;
 		goto out;
+	}
+	release_sock(sk);
 	if (smc->use_fallback)
 	if (smc->use_fallback)
 		rc = kernel_sendpage(smc->clcsock, page, offset,
 		rc = kernel_sendpage(smc->clcsock, page, offset,
 				     size, flags);
 				     size, flags);
@@ -1327,7 +1327,6 @@ static ssize_t smc_sendpage(struct socket *sock, struct page *page,
 		rc = sock_no_sendpage(sock, page, offset, size, flags);
 		rc = sock_no_sendpage(sock, page, offset, size, flags);
 
 
 out:
 out:
-	release_sock(sk);
 	return rc;
 	return rc;
 }
 }
 
 

+ 19 - 3
net/smc/smc_core.c

@@ -32,6 +32,9 @@
 
 
 static u32 smc_lgr_num;			/* unique link group number */
 static u32 smc_lgr_num;			/* unique link group number */
 
 
+static void smc_buf_free(struct smc_buf_desc *buf_desc, struct smc_link *lnk,
+			 bool is_rmb);
+
 static void smc_lgr_schedule_free_work(struct smc_link_group *lgr)
 static void smc_lgr_schedule_free_work(struct smc_link_group *lgr)
 {
 {
 	/* client link group creation always follows the server link group
 	/* client link group creation always follows the server link group
@@ -234,9 +237,22 @@ static void smc_buf_unuse(struct smc_connection *conn)
 		conn->sndbuf_size = 0;
 		conn->sndbuf_size = 0;
 	}
 	}
 	if (conn->rmb_desc) {
 	if (conn->rmb_desc) {
-		conn->rmb_desc->reused = true;
-		conn->rmb_desc->used = 0;
-		conn->rmbe_size = 0;
+		if (!conn->rmb_desc->regerr) {
+			conn->rmb_desc->reused = 1;
+			conn->rmb_desc->used = 0;
+			conn->rmbe_size = 0;
+		} else {
+			/* buf registration failed, reuse not possible */
+			struct smc_link_group *lgr = conn->lgr;
+			struct smc_link *lnk;
+
+			write_lock_bh(&lgr->rmbs_lock);
+			list_del(&conn->rmb_desc->list);
+			write_unlock_bh(&lgr->rmbs_lock);
+
+			lnk = &lgr->lnk[SMC_SINGLE_LINK];
+			smc_buf_free(conn->rmb_desc, lnk, true);
+		}
 	}
 	}
 }
 }
 
 

+ 2 - 1
net/smc/smc_core.h

@@ -123,7 +123,8 @@ struct smc_buf_desc {
 						 */
 						 */
 	u32			order;		/* allocation order */
 	u32			order;		/* allocation order */
 	u32			used;		/* currently used / unused */
 	u32			used;		/* currently used / unused */
-	bool			reused;		/* new created / reused */
+	u8			reused	: 1;	/* new created / reused */
+	u8			regerr	: 1;	/* err during registration */
 };
 };
 
 
 struct smc_rtoken {				/* address/key of remote RMB */
 struct smc_rtoken {				/* address/key of remote RMB */