Commit 73598a0c authored by NeilBrown's avatar NeilBrown Committed by Chuck Lever

nfsd: don't allocate the versions array.

Instead of using kmalloc to allocate an array for storing active version
info, just declare an array to the max size - it is only 5 or so.
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent c9f10f81
......@@ -10,7 +10,7 @@
#define NFSCACHE_H
#include <linux/sunrpc/svc.h>
#include "netns.h"
#include "nfsd.h"
/*
* Representation of a reply cache entry.
......
......@@ -152,8 +152,8 @@ struct nfsd_net {
/*
* Version information
*/
bool *nfsd_versions;
bool *nfsd4_minorversions;
bool nfsd_versions[NFSD_MAXVERS + 1];
bool nfsd4_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1];
/*
* Duplicate reply cache
......@@ -219,8 +219,6 @@ struct nfsd_net {
#define nfsd_netns_ready(nn) ((nn)->sessionid_hashtbl)
extern bool nfsd_support_version(int vers);
extern void nfsd_netns_free_versions(struct nfsd_net *nn);
extern unsigned int nfsd_net_id;
void nfsd_copy_write_verifier(__be32 verf[2], struct nfsd_net *nn);
......
......@@ -2231,8 +2231,9 @@ int nfsd_nl_pool_mode_get_doit(struct sk_buff *skb, struct genl_info *info)
*/
static __net_init int nfsd_net_init(struct net *net)
{
int retval;
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
int retval;
int i;
retval = nfsd_export_init(net);
if (retval)
......@@ -2246,8 +2247,10 @@ static __net_init int nfsd_net_init(struct net *net)
goto out_repcache_error;
memset(&nn->nfsd_svcstats, 0, sizeof(nn->nfsd_svcstats));
nn->nfsd_svcstats.program = &nfsd_program;
nn->nfsd_versions = NULL;
nn->nfsd4_minorversions = NULL;
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++)
nn->nfsd4_minorversions[i] = nfsd_support_version(4);
nn->nfsd_info.mutex = &nfsd_mutex;
nn->nfsd_serv = NULL;
nfsd4_init_leases_net(nn);
......@@ -2278,7 +2281,6 @@ static __net_exit void nfsd_net_exit(struct net *net)
percpu_counter_destroy_many(nn->counter, NFSD_STATS_COUNTERS_NUM);
nfsd_idmap_shutdown(net);
nfsd_export_shutdown(net);
nfsd_netns_free_versions(nn);
}
static struct pernet_operations nfsd_net_ops = {
......
......@@ -23,9 +23,7 @@
#include <uapi/linux/nfsd/debug.h>
#include "netns.h"
#include "export.h"
#include "stats.h"
#undef ifdebug
#ifdef CONFIG_SUNRPC_DEBUG
......@@ -37,7 +35,14 @@
/*
* nfsd version
*/
#define NFSD_MINVERS 2
#define NFSD_MAXVERS 4
#define NFSD_SUPPORTED_MINOR_VERSION 2
bool nfsd_support_version(int vers);
#include "netns.h"
#include "stats.h"
/*
* Maximum blocksizes supported by daemon under various circumstances.
*/
......
......@@ -106,7 +106,7 @@ static struct svc_program nfsd_acl_program = {
#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
static const struct svc_version *nfsd_version[] = {
static const struct svc_version *nfsd_version[NFSD_MAXVERS+1] = {
#if defined(CONFIG_NFSD_V2)
[2] = &nfsd_version2,
#endif
......@@ -116,15 +116,12 @@ static const struct svc_version *nfsd_version[] = {
#endif
};
#define NFSD_MINVERS 2
#define NFSD_NRVERS ARRAY_SIZE(nfsd_version)
struct svc_program nfsd_program = {
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
.pg_next = &nfsd_acl_program,
#endif
.pg_prog = NFS_PROGRAM, /* program number */
.pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
.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 */
......@@ -135,78 +132,24 @@ struct svc_program nfsd_program = {
bool nfsd_support_version(int vers)
{
if (vers >= NFSD_MINVERS && vers < NFSD_NRVERS)
if (vers >= NFSD_MINVERS && vers <= NFSD_MAXVERS)
return nfsd_version[vers] != NULL;
return false;
}
static bool *
nfsd_alloc_versions(void)
{
bool *vers = kmalloc_array(NFSD_NRVERS, sizeof(bool), GFP_KERNEL);
unsigned i;
if (vers) {
/* All compiled versions are enabled by default */
for (i = 0; i < NFSD_NRVERS; i++)
vers[i] = nfsd_support_version(i);
}
return vers;
}
static bool *
nfsd_alloc_minorversions(void)
{
bool *vers = kmalloc_array(NFSD_SUPPORTED_MINOR_VERSION + 1,
sizeof(bool), GFP_KERNEL);
unsigned i;
if (vers) {
/* All minor versions are enabled by default */
for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++)
vers[i] = nfsd_support_version(4);
}
return vers;
}
void
nfsd_netns_free_versions(struct nfsd_net *nn)
{
kfree(nn->nfsd_versions);
kfree(nn->nfsd4_minorversions);
nn->nfsd_versions = NULL;
nn->nfsd4_minorversions = NULL;
}
static void
nfsd_netns_init_versions(struct nfsd_net *nn)
{
if (!nn->nfsd_versions) {
nn->nfsd_versions = nfsd_alloc_versions();
nn->nfsd4_minorversions = nfsd_alloc_minorversions();
if (!nn->nfsd_versions || !nn->nfsd4_minorversions)
nfsd_netns_free_versions(nn);
}
}
int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change)
{
if (vers < NFSD_MINVERS || vers >= NFSD_NRVERS)
if (vers < NFSD_MINVERS || vers > NFSD_MAXVERS)
return 0;
switch(change) {
case NFSD_SET:
if (nn->nfsd_versions)
nn->nfsd_versions[vers] = nfsd_support_version(vers);
nn->nfsd_versions[vers] = nfsd_support_version(vers);
break;
case NFSD_CLEAR:
nfsd_netns_init_versions(nn);
if (nn->nfsd_versions)
nn->nfsd_versions[vers] = false;
nn->nfsd_versions[vers] = false;
break;
case NFSD_TEST:
if (nn->nfsd_versions)
return nn->nfsd_versions[vers];
fallthrough;
return nn->nfsd_versions[vers];
case NFSD_AVAIL:
return nfsd_support_version(vers);
}
......@@ -233,23 +176,16 @@ int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change
switch(change) {
case NFSD_SET:
if (nn->nfsd4_minorversions) {
nfsd_vers(nn, 4, NFSD_SET);
nn->nfsd4_minorversions[minorversion] =
nfsd_vers(nn, 4, NFSD_TEST);
}
nfsd_vers(nn, 4, NFSD_SET);
nn->nfsd4_minorversions[minorversion] =
nfsd_vers(nn, 4, NFSD_TEST);
break;
case NFSD_CLEAR:
nfsd_netns_init_versions(nn);
if (nn->nfsd4_minorversions) {
nn->nfsd4_minorversions[minorversion] = false;
nfsd_adjust_nfsd_versions4(nn);
}
nn->nfsd4_minorversions[minorversion] = false;
nfsd_adjust_nfsd_versions4(nn);
break;
case NFSD_TEST:
if (nn->nfsd4_minorversions)
return nn->nfsd4_minorversions[minorversion];
return nfsd_vers(nn, 4, NFSD_TEST);
return nn->nfsd4_minorversions[minorversion];
case NFSD_AVAIL:
return minorversion <= NFSD_SUPPORTED_MINOR_VERSION &&
nfsd_vers(nn, 4, NFSD_AVAIL);
......@@ -568,11 +504,11 @@ void nfsd_reset_versions(struct nfsd_net *nn)
{
int i;
for (i = 0; i < NFSD_NRVERS; i++)
for (i = 0; i <= NFSD_MAXVERS; i++)
if (nfsd_vers(nn, i, NFSD_TEST))
return;
for (i = 0; i < NFSD_NRVERS; i++)
for (i = 0; i <= NFSD_MAXVERS; i++)
if (i != 4)
nfsd_vers(nn, i, NFSD_SET);
else {
......@@ -905,17 +841,17 @@ nfsd_init_request(struct svc_rqst *rqstp,
if (likely(nfsd_vers(nn, rqstp->rq_vers, NFSD_TEST)))
return svc_generic_init_request(rqstp, progp, ret);
ret->mismatch.lovers = NFSD_NRVERS;
for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) {
ret->mismatch.lovers = NFSD_MAXVERS + 1;
for (i = NFSD_MINVERS; i <= NFSD_MAXVERS; i++) {
if (nfsd_vers(nn, i, NFSD_TEST)) {
ret->mismatch.lovers = i;
break;
}
}
if (ret->mismatch.lovers == NFSD_NRVERS)
if (ret->mismatch.lovers > NFSD_MAXVERS)
return rpc_prog_unavail;
ret->mismatch.hivers = NFSD_MINVERS;
for (i = NFSD_NRVERS - 1; i >= NFSD_MINVERS; i--) {
for (i = NFSD_MAXVERS; i >= NFSD_MINVERS; i--) {
if (nfsd_vers(nn, i, NFSD_TEST)) {
ret->mismatch.hivers = i;
break;
......
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