SUNRPC: replace program list with program array
A service created with svc_create_pooled() can be given a linked list of programs and all of these will be served. Using a linked list makes it cumbersome when there are several programs that can be optionally selected with CONFIG settings. After this patch is applied, API consumers must use only svc_create_pooled() when creating an RPC service that listens for more than one RPC program. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Mike Snitzer <snitzer@kernel.org> Acked-by: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
This commit is contained in:
parent
199f212874
commit
86ab08beb3
@ -2246,7 +2246,7 @@ static __net_init int nfsd_net_init(struct net *net)
|
||||
if (retval)
|
||||
goto out_repcache_error;
|
||||
memset(&nn->nfsd_svcstats, 0, sizeof(nn->nfsd_svcstats));
|
||||
nn->nfsd_svcstats.program = &nfsd_program;
|
||||
nn->nfsd_svcstats.program = &nfsd_programs[0];
|
||||
for (i = 0; i < sizeof(nn->nfsd_versions); i++)
|
||||
nn->nfsd_versions[i] = nfsd_support_version(i);
|
||||
for (i = 0; i < sizeof(nn->nfsd4_minorversions); i++)
|
||||
|
@ -85,7 +85,7 @@ struct nfsd_genl_rqstp {
|
||||
u32 rq_opnum[NFSD_MAX_OPS_PER_COMPOUND];
|
||||
};
|
||||
|
||||
extern struct svc_program nfsd_program;
|
||||
extern struct svc_program nfsd_programs[];
|
||||
extern const struct svc_version nfsd_version2, nfsd_version3, nfsd_version4;
|
||||
extern struct mutex nfsd_mutex;
|
||||
extern spinlock_t nfsd_drc_lock;
|
||||
|
@ -35,7 +35,6 @@
|
||||
#define NFSDDBG_FACILITY NFSDDBG_SVC
|
||||
|
||||
atomic_t nfsd_th_cnt = ATOMIC_INIT(0);
|
||||
extern struct svc_program nfsd_program;
|
||||
static int nfsd(void *vrqstp);
|
||||
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
|
||||
static int nfsd_acl_rpcbind_set(struct net *,
|
||||
@ -90,20 +89,9 @@ static const struct svc_version *nfsd_acl_version[] = {
|
||||
# endif
|
||||
};
|
||||
|
||||
#define NFSD_ACL_MINVERS 2
|
||||
#define NFSD_ACL_MINVERS 2
|
||||
#define NFSD_ACL_NRVERS ARRAY_SIZE(nfsd_acl_version)
|
||||
|
||||
static struct svc_program nfsd_acl_program = {
|
||||
.pg_prog = NFS_ACL_PROGRAM,
|
||||
.pg_nvers = NFSD_ACL_NRVERS,
|
||||
.pg_vers = nfsd_acl_version,
|
||||
.pg_name = "nfsacl",
|
||||
.pg_class = "nfsd",
|
||||
.pg_authenticate = &svc_set_client,
|
||||
.pg_init_request = nfsd_acl_init_request,
|
||||
.pg_rpcbind_set = nfsd_acl_rpcbind_set,
|
||||
};
|
||||
|
||||
#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
|
||||
|
||||
static const struct svc_version *nfsd_version[NFSD_MAXVERS+1] = {
|
||||
@ -116,18 +104,29 @@ static const struct svc_version *nfsd_version[NFSD_MAXVERS+1] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
struct svc_program nfsd_program = {
|
||||
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
|
||||
.pg_next = &nfsd_acl_program,
|
||||
#endif
|
||||
struct svc_program nfsd_programs[] = {
|
||||
{
|
||||
.pg_prog = NFS_PROGRAM, /* program number */
|
||||
.pg_nvers = NFSD_MAXVERS+1, /* nr of entries in nfsd_version */
|
||||
.pg_vers = nfsd_version, /* version table */
|
||||
.pg_name = "nfsd", /* program name */
|
||||
.pg_class = "nfsd", /* authentication class */
|
||||
.pg_authenticate = &svc_set_client, /* export authentication */
|
||||
.pg_authenticate = svc_set_client, /* export authentication */
|
||||
.pg_init_request = nfsd_init_request,
|
||||
.pg_rpcbind_set = nfsd_rpcbind_set,
|
||||
},
|
||||
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
|
||||
{
|
||||
.pg_prog = NFS_ACL_PROGRAM,
|
||||
.pg_nvers = NFSD_ACL_NRVERS,
|
||||
.pg_vers = nfsd_acl_version,
|
||||
.pg_name = "nfsacl",
|
||||
.pg_class = "nfsd",
|
||||
.pg_authenticate = svc_set_client,
|
||||
.pg_init_request = nfsd_acl_init_request,
|
||||
.pg_rpcbind_set = nfsd_acl_rpcbind_set,
|
||||
},
|
||||
#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
|
||||
};
|
||||
|
||||
bool nfsd_support_version(int vers)
|
||||
@ -641,7 +640,8 @@ int nfsd_create_serv(struct net *net)
|
||||
if (nfsd_max_blksize == 0)
|
||||
nfsd_max_blksize = nfsd_get_default_max_blksize();
|
||||
nfsd_reset_versions(nn);
|
||||
serv = svc_create_pooled(&nfsd_program, &nn->nfsd_svcstats,
|
||||
serv = svc_create_pooled(nfsd_programs, ARRAY_SIZE(nfsd_programs),
|
||||
&nn->nfsd_svcstats,
|
||||
nfsd_max_blksize, nfsd);
|
||||
if (serv == NULL)
|
||||
return -ENOMEM;
|
||||
|
@ -67,9 +67,10 @@ enum {
|
||||
* We currently do not support more than one RPC program per daemon.
|
||||
*/
|
||||
struct svc_serv {
|
||||
struct svc_program * sv_program; /* RPC program */
|
||||
struct svc_program * sv_programs; /* RPC programs */
|
||||
struct svc_stat * sv_stats; /* RPC statistics */
|
||||
spinlock_t sv_lock;
|
||||
unsigned int sv_nprogs; /* Number of sv_programs */
|
||||
unsigned int sv_nrthreads; /* # of server threads */
|
||||
unsigned int sv_maxconn; /* max connections allowed or
|
||||
* '0' causing max to be based
|
||||
@ -360,10 +361,9 @@ struct svc_process_info {
|
||||
};
|
||||
|
||||
/*
|
||||
* List of RPC programs on the same transport endpoint
|
||||
* RPC program - an array of these can use the same transport endpoint
|
||||
*/
|
||||
struct svc_program {
|
||||
struct svc_program * pg_next; /* other programs (same xprt) */
|
||||
u32 pg_prog; /* program number */
|
||||
unsigned int pg_lovers; /* lowest version */
|
||||
unsigned int pg_hivers; /* highest version */
|
||||
@ -441,6 +441,7 @@ bool svc_rqst_replace_page(struct svc_rqst *rqstp,
|
||||
void svc_rqst_release_pages(struct svc_rqst *rqstp);
|
||||
void svc_exit_thread(struct svc_rqst *);
|
||||
struct svc_serv * svc_create_pooled(struct svc_program *prog,
|
||||
unsigned int nprog,
|
||||
struct svc_stat *stats,
|
||||
unsigned int bufsize,
|
||||
int (*threadfn)(void *data));
|
||||
|
@ -440,10 +440,11 @@ EXPORT_SYMBOL_GPL(svc_rpcb_cleanup);
|
||||
|
||||
static int svc_uses_rpcbind(struct svc_serv *serv)
|
||||
{
|
||||
struct svc_program *progp;
|
||||
unsigned int i;
|
||||
unsigned int p, i;
|
||||
|
||||
for (p = 0; p < serv->sv_nprogs; p++) {
|
||||
struct svc_program *progp = &serv->sv_programs[p];
|
||||
|
||||
for (progp = serv->sv_program; progp; progp = progp->pg_next) {
|
||||
for (i = 0; i < progp->pg_nvers; i++) {
|
||||
if (progp->pg_vers[i] == NULL)
|
||||
continue;
|
||||
@ -480,7 +481,7 @@ __svc_init_bc(struct svc_serv *serv)
|
||||
* Create an RPC service
|
||||
*/
|
||||
static struct svc_serv *
|
||||
__svc_create(struct svc_program *prog, struct svc_stat *stats,
|
||||
__svc_create(struct svc_program *prog, int nprogs, struct svc_stat *stats,
|
||||
unsigned int bufsize, int npools, int (*threadfn)(void *data))
|
||||
{
|
||||
struct svc_serv *serv;
|
||||
@ -491,7 +492,8 @@ __svc_create(struct svc_program *prog, struct svc_stat *stats,
|
||||
if (!(serv = kzalloc(sizeof(*serv), GFP_KERNEL)))
|
||||
return NULL;
|
||||
serv->sv_name = prog->pg_name;
|
||||
serv->sv_program = prog;
|
||||
serv->sv_programs = prog;
|
||||
serv->sv_nprogs = nprogs;
|
||||
serv->sv_stats = stats;
|
||||
if (bufsize > RPCSVC_MAXPAYLOAD)
|
||||
bufsize = RPCSVC_MAXPAYLOAD;
|
||||
@ -499,17 +501,18 @@ __svc_create(struct svc_program *prog, struct svc_stat *stats,
|
||||
serv->sv_max_mesg = roundup(serv->sv_max_payload + PAGE_SIZE, PAGE_SIZE);
|
||||
serv->sv_threadfn = threadfn;
|
||||
xdrsize = 0;
|
||||
while (prog) {
|
||||
prog->pg_lovers = prog->pg_nvers-1;
|
||||
for (vers=0; vers<prog->pg_nvers ; vers++)
|
||||
if (prog->pg_vers[vers]) {
|
||||
prog->pg_hivers = vers;
|
||||
if (prog->pg_lovers > vers)
|
||||
prog->pg_lovers = vers;
|
||||
if (prog->pg_vers[vers]->vs_xdrsize > xdrsize)
|
||||
xdrsize = prog->pg_vers[vers]->vs_xdrsize;
|
||||
for (i = 0; i < nprogs; i++) {
|
||||
struct svc_program *progp = &prog[i];
|
||||
|
||||
progp->pg_lovers = progp->pg_nvers-1;
|
||||
for (vers = 0; vers < progp->pg_nvers ; vers++)
|
||||
if (progp->pg_vers[vers]) {
|
||||
progp->pg_hivers = vers;
|
||||
if (progp->pg_lovers > vers)
|
||||
progp->pg_lovers = vers;
|
||||
if (progp->pg_vers[vers]->vs_xdrsize > xdrsize)
|
||||
xdrsize = progp->pg_vers[vers]->vs_xdrsize;
|
||||
}
|
||||
prog = prog->pg_next;
|
||||
}
|
||||
serv->sv_xdrsize = xdrsize;
|
||||
INIT_LIST_HEAD(&serv->sv_tempsocks);
|
||||
@ -558,13 +561,14 @@ __svc_create(struct svc_program *prog, struct svc_stat *stats,
|
||||
struct svc_serv *svc_create(struct svc_program *prog, unsigned int bufsize,
|
||||
int (*threadfn)(void *data))
|
||||
{
|
||||
return __svc_create(prog, NULL, bufsize, 1, threadfn);
|
||||
return __svc_create(prog, 1, NULL, bufsize, 1, threadfn);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(svc_create);
|
||||
|
||||
/**
|
||||
* svc_create_pooled - Create an RPC service with pooled threads
|
||||
* @prog: the RPC program the new service will handle
|
||||
* @prog: Array of RPC programs the new service will handle
|
||||
* @nprogs: Number of programs in the array
|
||||
* @stats: the stats struct if desired
|
||||
* @bufsize: maximum message size for @prog
|
||||
* @threadfn: a function to service RPC requests for @prog
|
||||
@ -572,6 +576,7 @@ EXPORT_SYMBOL_GPL(svc_create);
|
||||
* Returns an instantiated struct svc_serv object or NULL.
|
||||
*/
|
||||
struct svc_serv *svc_create_pooled(struct svc_program *prog,
|
||||
unsigned int nprogs,
|
||||
struct svc_stat *stats,
|
||||
unsigned int bufsize,
|
||||
int (*threadfn)(void *data))
|
||||
@ -579,7 +584,7 @@ struct svc_serv *svc_create_pooled(struct svc_program *prog,
|
||||
struct svc_serv *serv;
|
||||
unsigned int npools = svc_pool_map_get();
|
||||
|
||||
serv = __svc_create(prog, stats, bufsize, npools, threadfn);
|
||||
serv = __svc_create(prog, nprogs, stats, bufsize, npools, threadfn);
|
||||
if (!serv)
|
||||
goto out_err;
|
||||
serv->sv_is_pooled = true;
|
||||
@ -602,16 +607,16 @@ svc_destroy(struct svc_serv **servp)
|
||||
|
||||
*servp = NULL;
|
||||
|
||||
dprintk("svc: svc_destroy(%s)\n", serv->sv_program->pg_name);
|
||||
dprintk("svc: svc_destroy(%s)\n", serv->sv_programs->pg_name);
|
||||
timer_shutdown_sync(&serv->sv_temptimer);
|
||||
|
||||
/*
|
||||
* Remaining transports at this point are not expected.
|
||||
*/
|
||||
WARN_ONCE(!list_empty(&serv->sv_permsocks),
|
||||
"SVC: permsocks remain for %s\n", serv->sv_program->pg_name);
|
||||
"SVC: permsocks remain for %s\n", serv->sv_programs->pg_name);
|
||||
WARN_ONCE(!list_empty(&serv->sv_tempsocks),
|
||||
"SVC: tempsocks remain for %s\n", serv->sv_program->pg_name);
|
||||
"SVC: tempsocks remain for %s\n", serv->sv_programs->pg_name);
|
||||
|
||||
cache_clean_deferred(serv);
|
||||
|
||||
@ -1148,15 +1153,16 @@ int svc_register(const struct svc_serv *serv, struct net *net,
|
||||
const int family, const unsigned short proto,
|
||||
const unsigned short port)
|
||||
{
|
||||
struct svc_program *progp;
|
||||
unsigned int i;
|
||||
unsigned int p, i;
|
||||
int error = 0;
|
||||
|
||||
WARN_ON_ONCE(proto == 0 && port == 0);
|
||||
if (proto == 0 && port == 0)
|
||||
return -EINVAL;
|
||||
|
||||
for (progp = serv->sv_program; progp; progp = progp->pg_next) {
|
||||
for (p = 0; p < serv->sv_nprogs; p++) {
|
||||
struct svc_program *progp = &serv->sv_programs[p];
|
||||
|
||||
for (i = 0; i < progp->pg_nvers; i++) {
|
||||
|
||||
error = progp->pg_rpcbind_set(net, progp, i,
|
||||
@ -1208,13 +1214,14 @@ static void __svc_unregister(struct net *net, const u32 program, const u32 versi
|
||||
static void svc_unregister(const struct svc_serv *serv, struct net *net)
|
||||
{
|
||||
struct sighand_struct *sighand;
|
||||
struct svc_program *progp;
|
||||
unsigned long flags;
|
||||
unsigned int i;
|
||||
unsigned int p, i;
|
||||
|
||||
clear_thread_flag(TIF_SIGPENDING);
|
||||
|
||||
for (progp = serv->sv_program; progp; progp = progp->pg_next) {
|
||||
for (p = 0; p < serv->sv_nprogs; p++) {
|
||||
struct svc_program *progp = &serv->sv_programs[p];
|
||||
|
||||
for (i = 0; i < progp->pg_nvers; i++) {
|
||||
if (progp->pg_vers[i] == NULL)
|
||||
continue;
|
||||
@ -1320,7 +1327,7 @@ svc_process_common(struct svc_rqst *rqstp)
|
||||
struct svc_process_info process;
|
||||
enum svc_auth_status auth_res;
|
||||
unsigned int aoffset;
|
||||
int rc;
|
||||
int pr, rc;
|
||||
__be32 *p;
|
||||
|
||||
/* Will be turned off only when NFSv4 Sessions are used */
|
||||
@ -1344,9 +1351,12 @@ svc_process_common(struct svc_rqst *rqstp)
|
||||
rqstp->rq_vers = be32_to_cpup(p++);
|
||||
rqstp->rq_proc = be32_to_cpup(p);
|
||||
|
||||
for (progp = serv->sv_program; progp; progp = progp->pg_next)
|
||||
for (pr = 0; pr < serv->sv_nprogs; pr++) {
|
||||
progp = &serv->sv_programs[pr];
|
||||
|
||||
if (rqstp->rq_prog == progp->pg_prog)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode auth data, and add verifier to reply buffer.
|
||||
|
@ -268,7 +268,7 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
|
||||
spin_unlock(&svc_xprt_class_lock);
|
||||
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,
|
||||
trace_svc_xprt_create_err(serv->sv_programs->pg_name,
|
||||
xcl->xcl_name, sap, len,
|
||||
newxprt);
|
||||
module_put(xcl->xcl_owner);
|
||||
|
@ -697,7 +697,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
|
||||
rqstp->rq_auth_stat = rpc_autherr_badcred;
|
||||
ipm = ip_map_cached_get(xprt);
|
||||
if (ipm == NULL)
|
||||
ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
|
||||
ipm = __ip_map_lookup(sn->ip_map_cache,
|
||||
rqstp->rq_server->sv_programs->pg_class,
|
||||
&sin6->sin6_addr);
|
||||
|
||||
if (ipm == NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user