Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d97dac54 authored by Sowmini Varadhan's avatar Sowmini Varadhan Committed by David S. Miller
Browse files

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: default avatarSowmini Varadhan <sowmini.varadhan@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a28c257c
Loading
Loading
Loading
Loading
+27 −0
Original line number Original line Diff line number Diff line
@@ -270,6 +270,28 @@ static int rds_cong_monitor(struct rds_sock *rs, char __user *optval,
	return ret;
	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,
static int rds_setsockopt(struct socket *sock, int level, int optname,
			  char __user *optval, unsigned int optlen)
			  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:
	case RDS_CONG_MONITOR:
		ret = rds_cong_monitor(rs, optval, optlen);
		ret = rds_cong_monitor(rs, optval, optlen);
		break;
		break;
	case SO_RDS_TRANSPORT:
		lock_sock(sock->sk);
		ret = rds_set_transport(rs, optval, optlen);
		release_sock(sock->sk);
		break;
	default:
	default:
		ret = -ENOPROTOOPT;
		ret = -ENOPROTOOPT;
	}
	}
+4 −0
Original line number Original line Diff line number Diff line
@@ -181,6 +181,10 @@ int rds_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
	if (ret)
	if (ret)
		goto out;
		goto out;


	if (rs->rs_transport) { /* previously bound */
		ret = 0;
		goto out;
	}
	trans = rds_trans_get_preferred(sin->sin_addr.s_addr);
	trans = rds_trans_get_preferred(sin->sin_addr.s_addr);
	if (!trans) {
	if (!trans) {
		ret = -EADDRNOTAVAIL;
		ret = -EADDRNOTAVAIL;
+1 −0
Original line number Original line Diff line number Diff line
@@ -798,6 +798,7 @@ struct rds_transport *rds_trans_get_preferred(__be32 addr);
void rds_trans_put(struct rds_transport *trans);
void rds_trans_put(struct rds_transport *trans);
unsigned int rds_trans_stats_info_copy(struct rds_info_iterator *iter,
unsigned int rds_trans_stats_info_copy(struct rds_info_iterator *iter,
				       unsigned int avail);
				       unsigned int avail);
struct rds_transport *rds_trans_get(int t_type);
int rds_trans_init(void);
int rds_trans_init(void);
void rds_trans_exit(void);
void rds_trans_exit(void);


+21 −0
Original line number Original line Diff line number Diff line
@@ -101,6 +101,27 @@ struct rds_transport *rds_trans_get_preferred(__be32 addr)
	return ret;
	return ret;
}
}


struct rds_transport *rds_trans_get(int t_type)
{
	struct rds_transport *ret = NULL;
	struct rds_transport *trans;
	unsigned int i;

	down_read(&rds_trans_sem);
	for (i = 0; i < RDS_TRANS_COUNT; i++) {
		trans = transports[i];

		if (trans && trans->t_type == t_type &&
		    (!trans->t_owner || try_module_get(trans->t_owner))) {
			ret = trans;
			break;
		}
	}
	up_read(&rds_trans_sem);

	return ret;
}

/*
/*
 * This returns the number of stats entries in the snapshot and only
 * This returns the number of stats entries in the snapshot and only
 * copies them using the iter if there is enough space for them.  The
 * copies them using the iter if there is enough space for them.  The