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

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
...@@ -135,6 +135,9 @@ int svc_reg_xprt_class(struct svc_xprt_class *); ...@@ -135,6 +135,9 @@ int svc_reg_xprt_class(struct svc_xprt_class *);
void svc_unreg_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 *, void svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *,
struct svc_serv *); 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, int svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
struct net *net, const int family, struct net *net, const int family,
const unsigned short port, int flags, const unsigned short port, int flags,
......
...@@ -211,51 +211,6 @@ void svc_xprt_init(struct net *net, struct svc_xprt_class *xcl, ...@@ -211,51 +211,6 @@ void svc_xprt_init(struct net *net, struct svc_xprt_class *xcl,
} }
EXPORT_SYMBOL_GPL(svc_xprt_init); 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 * svc_xprt_received - start next receiver thread
* @xprt: controlling transport * @xprt: controlling transport
...@@ -294,9 +249,8 @@ void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new) ...@@ -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, static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
struct net *net, const int family, struct net *net, struct sockaddr *sap,
const unsigned short port, int flags, size_t len, int flags, const struct cred *cred)
const struct cred *cred)
{ {
struct svc_xprt_class *xcl; struct svc_xprt_class *xcl;
...@@ -312,8 +266,11 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name, ...@@ -312,8 +266,11 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
goto err; goto err;
spin_unlock(&svc_xprt_class_lock); 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)) { 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); module_put(xcl->xcl_owner);
return PTR_ERR(newxprt); return PTR_ERR(newxprt);
} }
...@@ -329,6 +286,48 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name, ...@@ -329,6 +286,48 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
return -EPROTONOSUPPORT; 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 * svc_xprt_create - Add a new listener to @serv
* @serv: target RPC service * @serv: target RPC service
...@@ -339,23 +338,41 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name, ...@@ -339,23 +338,41 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
* @flags: SVC_SOCK flags * @flags: SVC_SOCK flags
* @cred: credential to bind to this transport * @cred: credential to bind to this transport
* *
* Return values: * Return local xprt port on success or %-EPROTONOSUPPORT on failure
* %0: New listener added successfully
* %-EPROTONOSUPPORT: Requested transport type not supported
*/ */
int svc_xprt_create(struct svc_serv *serv, const char *xprt_name, int svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
struct net *net, const int family, struct net *net, const int family,
const unsigned short port, int flags, const unsigned short port, int flags,
const struct cred *cred) 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); switch (family) {
if (err == -EPROTONOSUPPORT) { case PF_INET:
request_module("svc%s", xprt_name); sap = (struct sockaddr *)&sin;
err = _svc_xprt_create(serv, xprt_name, net, family, port, flags, cred); 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); EXPORT_SYMBOL_GPL(svc_xprt_create);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment