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>
Šī revīzija ir iekļauta:
Sowmini Varadhan
2015-05-29 17:28:08 -04:00
revīziju iesūtīja David S. Miller
vecāks a28c257c9e
revīzija d97dac54bf
4 mainīti faili ar 53 papildinājumiem un 0 dzēšanām

Parādīt failu

@@ -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;
}