[ofa-general] [PATCH] RDS: prevent oops when sending to local address

Olaf Kirch olaf.kirch at oracle.com
Mon Feb 25 08:01:07 PST 2008


Hi,

This is a bugfix for a kernel oops that Rick ran into last
Friday. I know it's a close shave - is the window for 1.3
still open?

Olaf
---------------------------------------------------
From: Olaf Kirch <olaf.kirch at oracle.com>
Subject: RDS: prevent oops when sending to local address

When a user process sends to a local IP address, RDS will
quietly use the loopback transport instead of the transport
originally bound to.

However, loopback does not support RDMA, and hence c_trans->xmit_rdma
is NULL. Trying to call xmit_rdma will give a nice and clean oops.

So we really want to check early whether the transport associated
with the connection does indeed support RDMA.

Signed-off-by: Olaf Kirch <olaf.kirch at oracle.com>
---
 net/rds/send.c |   24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

Index: ofa_kernel-1.3/net/rds/send.c
===================================================================
--- ofa_kernel-1.3.orig/net/rds/send.c
+++ ofa_kernel-1.3/net/rds/send.c
@@ -635,7 +635,8 @@ out:
 	return *queued;
 }
 
-static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm,
+static int rds_cmsg_send(struct rds_sock *rs, struct rds_connection *conn,
+					  struct rds_message *rm,
 		                          struct msghdr *msg,
 					  int *allocated_mr)
 {
@@ -649,16 +650,27 @@ static int rds_cmsg_send(struct rds_sock
 		if (cmsg->cmsg_level != SOL_RDS)
 			continue;
 
+		/* We explicitly check whether conn->c_trans supports
+		 * RDMA, because when sending to a local address, conn
+		 * will use the loopback transport which is not capable
+		 * of RDMA. Calling xmit_rdma later would oops.
+		 */
 		switch (cmsg->cmsg_type) {
 		case RDS_CMSG_RDMA_ARGS:
+			if (!conn->c_trans->xmit_rdma)
+				return -EOPNOTSUPP;
 			ret = rds_cmsg_rdma_args(rs, rm, cmsg);
 			break;
 
 		case RDS_CMSG_RDMA_DEST:
+			if (!conn->c_trans->xmit_rdma)
+				return -EOPNOTSUPP;
 			ret = rds_cmsg_rdma_dest(rs, rm, cmsg);
 			break;
 
 		case RDS_CMSG_RDMA_MAP:
+			if (!conn->c_trans->xmit_rdma)
+				return -EOPNOTSUPP;
 			ret = rds_cmsg_rdma_map(rs, rm, cmsg);
 			if (!ret)
 				*allocated_mr = 1;
@@ -727,11 +739,6 @@ int rds_sendmsg(struct kiocb *iocb, stru
 
 	rm->m_daddr = daddr;
 
-	/* Parse any control messages the user may have included. */
-	ret = rds_cmsg_send(rs, rm, msg, &allocated_mr);
-	if (ret)
-		goto out;
-
 	/* rds_conn_create has a spinlock that runs with IRQ off.
 	 * Caching the conn in the socket helps a lot. */
 	if ((conn = rs->rs_conn) == NULL || conn->c_faddr != daddr) {
@@ -745,6 +752,11 @@ int rds_sendmsg(struct kiocb *iocb, stru
 		rs->rs_conn = conn;
 	}
 
+	/* Parse any control messages the user may have included. */
+	ret = rds_cmsg_send(rs, conn, rm, msg, &allocated_mr);
+	if (ret)
+		goto out;
+
 	/* If the connection is down, trigger a connect. We may
 	 * have scheduled a delayed reconnect however - in this case
 	 * we should not interfere.

-- 
Olaf Kirch  |  --- o --- Nous sommes du soleil we love when we play
okir at lst.de |    / | \   sol.dhoop.naytheet.ah kin.ir.samse.qurax



More information about the general mailing list