Commit a79ec2ae authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Chuck Lever
Browse files

SUNRPC: introduce svc_xprt_create_from_sa utility routine



Add svc_xprt_create_from_sa utility routine and refactor
svc_xprt_create() codebase in order to introduce the capability to
create a svc port from socket address.

Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Tested-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 5a939bea
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -135,6 +135,9 @@ int svc_reg_xprt_class(struct svc_xprt_class *);
void	svc_unreg_xprt_class(struct svc_xprt_class *);
void	svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *,
		      struct svc_serv *);
int	svc_xprt_create_from_sa(struct svc_serv *serv, const char *xprt_name,
				struct net *net, struct sockaddr *sap,
				int flags, const struct cred *cred);
int	svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
			struct net *net, const int family,
			const unsigned short port, int flags,
+75 −58
Original line number Diff line number Diff line
@@ -211,51 +211,6 @@ void svc_xprt_init(struct net *net, struct svc_xprt_class *xcl,
}
EXPORT_SYMBOL_GPL(svc_xprt_init);

static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,
					 struct svc_serv *serv,
					 struct net *net,
					 const int family,
					 const unsigned short port,
					 int flags)
{
	struct sockaddr_in sin = {
		.sin_family		= AF_INET,
		.sin_addr.s_addr	= htonl(INADDR_ANY),
		.sin_port		= htons(port),
	};
#if IS_ENABLED(CONFIG_IPV6)
	struct sockaddr_in6 sin6 = {
		.sin6_family		= AF_INET6,
		.sin6_addr		= IN6ADDR_ANY_INIT,
		.sin6_port		= htons(port),
	};
#endif
	struct svc_xprt *xprt;
	struct sockaddr *sap;
	size_t len;

	switch (family) {
	case PF_INET:
		sap = (struct sockaddr *)&sin;
		len = sizeof(sin);
		break;
#if IS_ENABLED(CONFIG_IPV6)
	case PF_INET6:
		sap = (struct sockaddr *)&sin6;
		len = sizeof(sin6);
		break;
#endif
	default:
		return ERR_PTR(-EAFNOSUPPORT);
	}

	xprt = xcl->xcl_ops->xpo_create(serv, net, sap, len, flags);
	if (IS_ERR(xprt))
		trace_svc_xprt_create_err(serv->sv_program->pg_name,
					  xcl->xcl_name, sap, len, xprt);
	return xprt;
}

/**
 * svc_xprt_received - start next receiver thread
 * @xprt: controlling transport
@@ -294,9 +249,8 @@ void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new)
}

static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
			    struct net *net, const int family,
			    const unsigned short port, int flags,
			    const struct cred *cred)
			    struct net *net, struct sockaddr *sap,
			    size_t len, int flags, const struct cred *cred)
{
	struct svc_xprt_class *xcl;

@@ -312,8 +266,11 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
			goto err;

		spin_unlock(&svc_xprt_class_lock);
		newxprt = __svc_xpo_create(xcl, serv, net, family, port, flags);
		newxprt = xcl->xcl_ops->xpo_create(serv, net, sap, len, flags);
		if (IS_ERR(newxprt)) {
			trace_svc_xprt_create_err(serv->sv_program->pg_name,
						  xcl->xcl_name, sap, len,
						  newxprt);
			module_put(xcl->xcl_owner);
			return PTR_ERR(newxprt);
		}
@@ -329,6 +286,48 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
	return -EPROTONOSUPPORT;
}

/**
 * svc_xprt_create_from_sa - Add a new listener to @serv from socket address
 * @serv: target RPC service
 * @xprt_name: transport class name
 * @net: network namespace
 * @sap: socket address pointer
 * @flags: SVC_SOCK flags
 * @cred: credential to bind to this transport
 *
 * Return local xprt port on success or %-EPROTONOSUPPORT on failure
 */
int svc_xprt_create_from_sa(struct svc_serv *serv, const char *xprt_name,
			    struct net *net, struct sockaddr *sap,
			    int flags, const struct cred *cred)
{
	size_t len;
	int err;

	switch (sap->sa_family) {
	case AF_INET:
		len = sizeof(struct sockaddr_in);
		break;
#if IS_ENABLED(CONFIG_IPV6)
	case AF_INET6:
		len = sizeof(struct sockaddr_in6);
		break;
#endif
	default:
		return -EAFNOSUPPORT;
	}

	err = _svc_xprt_create(serv, xprt_name, net, sap, len, flags, cred);
	if (err == -EPROTONOSUPPORT) {
		request_module("svc%s", xprt_name);
		err = _svc_xprt_create(serv, xprt_name, net, sap, len, flags,
				       cred);
	}

	return err;
}
EXPORT_SYMBOL_GPL(svc_xprt_create_from_sa);

/**
 * svc_xprt_create - Add a new listener to @serv
 * @serv: target RPC service
@@ -339,23 +338,41 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
 * @flags: SVC_SOCK flags
 * @cred: credential to bind to this transport
 *
 * Return values:
 *   %0: New listener added successfully
 *   %-EPROTONOSUPPORT: Requested transport type not supported
 * Return local xprt port on success or %-EPROTONOSUPPORT on failure
 */
int svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
		    struct net *net, const int family,
		    const unsigned short port, int flags,
		    const struct cred *cred)
{
	int err;
	struct sockaddr_in sin = {
		.sin_family		= AF_INET,
		.sin_addr.s_addr	= htonl(INADDR_ANY),
		.sin_port		= htons(port),
	};
#if IS_ENABLED(CONFIG_IPV6)
	struct sockaddr_in6 sin6 = {
		.sin6_family		= AF_INET6,
		.sin6_addr		= IN6ADDR_ANY_INIT,
		.sin6_port		= htons(port),
	};
#endif
	struct sockaddr *sap;

	err = _svc_xprt_create(serv, xprt_name, net, family, port, flags, cred);
	if (err == -EPROTONOSUPPORT) {
		request_module("svc%s", xprt_name);
		err = _svc_xprt_create(serv, xprt_name, net, family, port, flags, cred);
	switch (family) {
	case PF_INET:
		sap = (struct sockaddr *)&sin;
		break;
#if IS_ENABLED(CONFIG_IPV6)
	case PF_INET6:
		sap = (struct sockaddr *)&sin6;
		break;
#endif
	default:
		return -EAFNOSUPPORT;
	}
	return err;

	return svc_xprt_create_from_sa(serv, xprt_name, net, sap, flags, cred);
}
EXPORT_SYMBOL_GPL(svc_xprt_create);