diff options
author | 2015-05-29 17:28:08 -0400 | |
---|---|---|
committer | 2015-05-31 21:47:23 -0700 | |
commit | d97dac54bf83b2a3df85fba37595e355627e0f2b (patch) | |
tree | 7a28dad3c812ffa56b8001ee1759c6493a30d3e0 /net/rds/af_rds.c | |
parent | net/rds: Declare SO_RDS_TRANSPORT and RDS_TRANS_* constants in uapi/linux/rds.h (diff) | |
download | linux-d97dac54bf83b2a3df85fba37595e355627e0f2b.tar.gz linux-d97dac54bf83b2a3df85fba37595e355627e0f2b.tar.bz2 linux-d97dac54bf83b2a3df85fba37595e355627e0f2b.zip |
net/rds: Add setsockopt support for SO_RDS_TRANSPORT
An application may deterministically attach the underlying transport for
a PF_RDS socket by invoking setsockopt(2) with the SO_RDS_TRANSPORT
option at the SOL_RDS level. The integer argument to setsockopt must be
one of the RDS_TRANS_* transport types, e.g., RDS_TRANS_TCP. The option
must be specified before invoking bind(2) on the socket, and may only
be used once on the socket. An attempt to set the option on a bound
socket, or to invoke the option after a successful SO_RDS_TRANSPORT
attachment, will return EOPNOTSUPP.
Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/rds/af_rds.c')
-rw-r--r-- | net/rds/af_rds.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index 3d83641f2861..04877441fb01 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c @@ -270,6 +270,28 @@ static int rds_cong_monitor(struct rds_sock *rs, char __user *optval, return ret; } +static int rds_set_transport(struct rds_sock *rs, char __user *optval, + int optlen) +{ + int t_type; + + if (rs->rs_transport) + return -EOPNOTSUPP; /* previously attached to transport */ + + if (optlen != sizeof(int)) + return -EINVAL; + + if (copy_from_user(&t_type, (int __user *)optval, sizeof(t_type))) + return -EFAULT; + + if (t_type < 0 || t_type >= RDS_TRANS_COUNT) + return -EINVAL; + + rs->rs_transport = rds_trans_get(t_type); + + return rs->rs_transport ? 0 : -ENOPROTOOPT; +} + static int rds_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) { @@ -300,6 +322,11 @@ static int rds_setsockopt(struct socket *sock, int level, int optname, case RDS_CONG_MONITOR: ret = rds_cong_monitor(rs, optval, optlen); break; + case SO_RDS_TRANSPORT: + lock_sock(sock->sk); + ret = rds_set_transport(rs, optval, optlen); + release_sock(sock->sk); + break; default: ret = -ENOPROTOOPT; } |