[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