mirror of https://gitee.com/openkylin/linux.git
nfsd: Allow containers to set supported nfs versions
Support use of the --nfs-version/--no-nfs-version arguments to rpc.nfsd in containers. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
parent
029be5d033
commit
e333f3bbef
|
@ -134,10 +134,18 @@ struct nfsd_net {
|
||||||
u32 s2s_cp_cl_id;
|
u32 s2s_cp_cl_id;
|
||||||
struct idr s2s_cp_stateids;
|
struct idr s2s_cp_stateids;
|
||||||
spinlock_t s2s_cp_lock;
|
spinlock_t s2s_cp_lock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Version information
|
||||||
|
*/
|
||||||
|
bool *nfsd_versions;
|
||||||
|
bool *nfsd4_minorversions;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Simple check to find out if a given net was properly initialized */
|
/* Simple check to find out if a given net was properly initialized */
|
||||||
#define nfsd_netns_ready(nn) ((nn)->sessionid_hashtbl)
|
#define nfsd_netns_ready(nn) ((nn)->sessionid_hashtbl)
|
||||||
|
|
||||||
|
extern void nfsd_netns_free_versions(struct nfsd_net *nn);
|
||||||
|
|
||||||
extern unsigned int nfsd_net_id;
|
extern unsigned int nfsd_net_id;
|
||||||
#endif /* __NFSD_NETNS_H__ */
|
#endif /* __NFSD_NETNS_H__ */
|
||||||
|
|
|
@ -1926,6 +1926,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
|
||||||
struct nfsd4_compound_state *cstate = &resp->cstate;
|
struct nfsd4_compound_state *cstate = &resp->cstate;
|
||||||
struct svc_fh *current_fh = &cstate->current_fh;
|
struct svc_fh *current_fh = &cstate->current_fh;
|
||||||
struct svc_fh *save_fh = &cstate->save_fh;
|
struct svc_fh *save_fh = &cstate->save_fh;
|
||||||
|
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
||||||
__be32 status;
|
__be32 status;
|
||||||
|
|
||||||
svcxdr_init_encode(rqstp, resp);
|
svcxdr_init_encode(rqstp, resp);
|
||||||
|
@ -1948,7 +1949,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
|
||||||
* According to RFC3010, this takes precedence over all other errors.
|
* According to RFC3010, this takes precedence over all other errors.
|
||||||
*/
|
*/
|
||||||
status = nfserr_minor_vers_mismatch;
|
status = nfserr_minor_vers_mismatch;
|
||||||
if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0)
|
if (nfsd_minorversion(nn, args->minorversion, NFSD_TEST) <= 0)
|
||||||
goto out;
|
goto out;
|
||||||
status = nfserr_resource;
|
status = nfserr_resource;
|
||||||
if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
|
if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
|
||||||
|
|
|
@ -537,14 +537,14 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
nfsd_print_version_support(char *buf, int remaining, const char *sep,
|
nfsd_print_version_support(struct nfsd_net *nn, char *buf, int remaining,
|
||||||
unsigned vers, int minor)
|
const char *sep, unsigned vers, int minor)
|
||||||
{
|
{
|
||||||
const char *format = minor < 0 ? "%s%c%u" : "%s%c%u.%u";
|
const char *format = minor < 0 ? "%s%c%u" : "%s%c%u.%u";
|
||||||
bool supported = !!nfsd_vers(vers, NFSD_TEST);
|
bool supported = !!nfsd_vers(nn, vers, NFSD_TEST);
|
||||||
|
|
||||||
if (vers == 4 && minor >= 0 &&
|
if (vers == 4 && minor >= 0 &&
|
||||||
!nfsd_minorversion(minor, NFSD_TEST))
|
!nfsd_minorversion(nn, minor, NFSD_TEST))
|
||||||
supported = false;
|
supported = false;
|
||||||
if (minor == 0 && supported)
|
if (minor == 0 && supported)
|
||||||
/*
|
/*
|
||||||
|
@ -599,20 +599,20 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
|
||||||
switch(num) {
|
switch(num) {
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
nfsd_vers(num, cmd);
|
nfsd_vers(nn, num, cmd);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if (*minorp == '.') {
|
if (*minorp == '.') {
|
||||||
if (nfsd_minorversion(minor, cmd) < 0)
|
if (nfsd_minorversion(nn, minor, cmd) < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else if ((cmd == NFSD_SET) != nfsd_vers(num, NFSD_TEST)) {
|
} else if ((cmd == NFSD_SET) != nfsd_vers(nn, num, NFSD_TEST)) {
|
||||||
/*
|
/*
|
||||||
* Either we have +4 and no minors are enabled,
|
* Either we have +4 and no minors are enabled,
|
||||||
* or we have -4 and at least one minor is enabled.
|
* or we have -4 and at least one minor is enabled.
|
||||||
* In either case, propagate 'cmd' to all minors.
|
* In either case, propagate 'cmd' to all minors.
|
||||||
*/
|
*/
|
||||||
minor = 0;
|
minor = 0;
|
||||||
while (nfsd_minorversion(minor, cmd) >= 0)
|
while (nfsd_minorversion(nn, minor, cmd) >= 0)
|
||||||
minor++;
|
minor++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -624,7 +624,7 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
|
||||||
/* If all get turned off, turn them back on, as
|
/* If all get turned off, turn them back on, as
|
||||||
* having no versions is BAD
|
* having no versions is BAD
|
||||||
*/
|
*/
|
||||||
nfsd_reset_versions();
|
nfsd_reset_versions(nn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now write current state into reply buffer */
|
/* Now write current state into reply buffer */
|
||||||
|
@ -633,12 +633,12 @@ static ssize_t __write_versions(struct file *file, char *buf, size_t size)
|
||||||
remaining = SIMPLE_TRANSACTION_LIMIT;
|
remaining = SIMPLE_TRANSACTION_LIMIT;
|
||||||
for (num=2 ; num <= 4 ; num++) {
|
for (num=2 ; num <= 4 ; num++) {
|
||||||
int minor;
|
int minor;
|
||||||
if (!nfsd_vers(num, NFSD_AVAIL))
|
if (!nfsd_vers(nn, num, NFSD_AVAIL))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
minor = -1;
|
minor = -1;
|
||||||
do {
|
do {
|
||||||
len = nfsd_print_version_support(buf, remaining,
|
len = nfsd_print_version_support(nn, buf, remaining,
|
||||||
sep, num, minor);
|
sep, num, minor);
|
||||||
if (len >= remaining)
|
if (len >= remaining)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1239,6 +1239,8 @@ static __net_init int nfsd_init_net(struct net *net)
|
||||||
retval = nfsd_idmap_init(net);
|
retval = nfsd_idmap_init(net);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto out_idmap_error;
|
goto out_idmap_error;
|
||||||
|
nn->nfsd_versions = NULL;
|
||||||
|
nn->nfsd4_minorversions = NULL;
|
||||||
nn->nfsd4_lease = 90; /* default lease time */
|
nn->nfsd4_lease = 90; /* default lease time */
|
||||||
nn->nfsd4_grace = 90;
|
nn->nfsd4_grace = 90;
|
||||||
nn->somebody_reclaimed = false;
|
nn->somebody_reclaimed = false;
|
||||||
|
@ -1261,6 +1263,7 @@ static __net_exit void nfsd_exit_net(struct net *net)
|
||||||
{
|
{
|
||||||
nfsd_idmap_shutdown(net);
|
nfsd_idmap_shutdown(net);
|
||||||
nfsd_export_shutdown(net);
|
nfsd_export_shutdown(net);
|
||||||
|
nfsd_netns_free_versions(net_generic(net, nfsd_net_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pernet_operations nfsd_net_ops = {
|
static struct pernet_operations nfsd_net_ops = {
|
||||||
|
|
|
@ -98,10 +98,12 @@ extern const struct svc_version nfsd_acl_version3;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct nfsd_net;
|
||||||
|
|
||||||
enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
|
enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
|
||||||
int nfsd_vers(int vers, enum vers_op change);
|
int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change);
|
||||||
int nfsd_minorversion(u32 minorversion, enum vers_op change);
|
int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change);
|
||||||
void nfsd_reset_versions(void);
|
void nfsd_reset_versions(struct nfsd_net *nn);
|
||||||
int nfsd_create_serv(struct net *net);
|
int nfsd_create_serv(struct net *net);
|
||||||
|
|
||||||
extern int nfsd_max_blksize;
|
extern int nfsd_max_blksize;
|
||||||
|
|
214
fs/nfsd/nfssvc.c
214
fs/nfsd/nfssvc.c
|
@ -38,12 +38,18 @@ static int nfsd_acl_rpcbind_set(struct net *,
|
||||||
u32, int,
|
u32, int,
|
||||||
unsigned short,
|
unsigned short,
|
||||||
unsigned short);
|
unsigned short);
|
||||||
|
static __be32 nfsd_acl_init_request(struct svc_rqst *,
|
||||||
|
const struct svc_program *,
|
||||||
|
struct svc_process_info *);
|
||||||
#endif
|
#endif
|
||||||
static int nfsd_rpcbind_set(struct net *,
|
static int nfsd_rpcbind_set(struct net *,
|
||||||
const struct svc_program *,
|
const struct svc_program *,
|
||||||
u32, int,
|
u32, int,
|
||||||
unsigned short,
|
unsigned short,
|
||||||
unsigned short);
|
unsigned short);
|
||||||
|
static __be32 nfsd_init_request(struct svc_rqst *,
|
||||||
|
const struct svc_program *,
|
||||||
|
struct svc_process_info *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members
|
* nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members
|
||||||
|
@ -98,7 +104,7 @@ static struct svc_program nfsd_acl_program = {
|
||||||
.pg_class = "nfsd",
|
.pg_class = "nfsd",
|
||||||
.pg_stats = &nfsd_acl_svcstats,
|
.pg_stats = &nfsd_acl_svcstats,
|
||||||
.pg_authenticate = &svc_set_client,
|
.pg_authenticate = &svc_set_client,
|
||||||
.pg_init_request = svc_generic_init_request,
|
.pg_init_request = nfsd_acl_init_request,
|
||||||
.pg_rpcbind_set = nfsd_acl_rpcbind_set,
|
.pg_rpcbind_set = nfsd_acl_rpcbind_set,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,7 +125,6 @@ static const struct svc_version *nfsd_version[] = {
|
||||||
|
|
||||||
#define NFSD_MINVERS 2
|
#define NFSD_MINVERS 2
|
||||||
#define NFSD_NRVERS ARRAY_SIZE(nfsd_version)
|
#define NFSD_NRVERS ARRAY_SIZE(nfsd_version)
|
||||||
static const struct svc_version *nfsd_versions[NFSD_NRVERS];
|
|
||||||
|
|
||||||
struct svc_program nfsd_program = {
|
struct svc_program nfsd_program = {
|
||||||
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
|
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
|
||||||
|
@ -127,78 +132,136 @@ struct svc_program nfsd_program = {
|
||||||
#endif
|
#endif
|
||||||
.pg_prog = NFS_PROGRAM, /* program number */
|
.pg_prog = NFS_PROGRAM, /* program number */
|
||||||
.pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
|
.pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
|
||||||
.pg_vers = nfsd_versions, /* version table */
|
.pg_vers = nfsd_version, /* version table */
|
||||||
.pg_name = "nfsd", /* program name */
|
.pg_name = "nfsd", /* program name */
|
||||||
.pg_class = "nfsd", /* authentication class */
|
.pg_class = "nfsd", /* authentication class */
|
||||||
.pg_stats = &nfsd_svcstats, /* version table */
|
.pg_stats = &nfsd_svcstats, /* version table */
|
||||||
.pg_authenticate = &svc_set_client, /* export authentication */
|
.pg_authenticate = &svc_set_client, /* export authentication */
|
||||||
.pg_init_request = svc_generic_init_request,
|
.pg_init_request = nfsd_init_request,
|
||||||
.pg_rpcbind_set = nfsd_rpcbind_set,
|
.pg_rpcbind_set = nfsd_rpcbind_set,
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool nfsd_supported_minorversions[NFSD_SUPPORTED_MINOR_VERSION + 1] = {
|
static bool
|
||||||
[0] = 1,
|
nfsd_support_version(int vers)
|
||||||
[1] = 1,
|
{
|
||||||
[2] = 1,
|
if (vers >= NFSD_MINVERS && vers < NFSD_NRVERS)
|
||||||
};
|
return nfsd_version[vers] != NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int nfsd_vers(int vers, enum vers_op change)
|
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_NRVERS)
|
||||||
return 0;
|
return 0;
|
||||||
switch(change) {
|
switch(change) {
|
||||||
case NFSD_SET:
|
case NFSD_SET:
|
||||||
nfsd_versions[vers] = nfsd_version[vers];
|
if (nn->nfsd_versions)
|
||||||
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
|
nn->nfsd_versions[vers] = nfsd_support_version(vers);
|
||||||
if (vers < NFSD_ACL_NRVERS)
|
|
||||||
nfsd_acl_versions[vers] = nfsd_acl_version[vers];
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case NFSD_CLEAR:
|
case NFSD_CLEAR:
|
||||||
nfsd_versions[vers] = NULL;
|
nfsd_netns_init_versions(nn);
|
||||||
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
|
if (nn->nfsd_versions)
|
||||||
if (vers < NFSD_ACL_NRVERS)
|
nn->nfsd_versions[vers] = false;
|
||||||
nfsd_acl_versions[vers] = NULL;
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case NFSD_TEST:
|
case NFSD_TEST:
|
||||||
return nfsd_versions[vers] != NULL;
|
if (nn->nfsd_versions)
|
||||||
|
return nn->nfsd_versions[vers];
|
||||||
|
/* Fallthrough */
|
||||||
case NFSD_AVAIL:
|
case NFSD_AVAIL:
|
||||||
return nfsd_version[vers] != NULL;
|
return nfsd_support_version(vers);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nfsd_adjust_nfsd_versions4(void)
|
nfsd_adjust_nfsd_versions4(struct nfsd_net *nn)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++) {
|
for (i = 0; i <= NFSD_SUPPORTED_MINOR_VERSION; i++) {
|
||||||
if (nfsd_supported_minorversions[i])
|
if (nn->nfsd4_minorversions[i])
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nfsd_vers(4, NFSD_CLEAR);
|
nfsd_vers(nn, 4, NFSD_CLEAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nfsd_minorversion(u32 minorversion, enum vers_op change)
|
int nfsd_minorversion(struct nfsd_net *nn, u32 minorversion, enum vers_op change)
|
||||||
{
|
{
|
||||||
if (minorversion > NFSD_SUPPORTED_MINOR_VERSION &&
|
if (minorversion > NFSD_SUPPORTED_MINOR_VERSION &&
|
||||||
change != NFSD_AVAIL)
|
change != NFSD_AVAIL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
switch(change) {
|
switch(change) {
|
||||||
case NFSD_SET:
|
case NFSD_SET:
|
||||||
nfsd_supported_minorversions[minorversion] = true;
|
if (nn->nfsd4_minorversions) {
|
||||||
nfsd_vers(4, NFSD_SET);
|
nfsd_vers(nn, 4, NFSD_SET);
|
||||||
|
nn->nfsd4_minorversions[minorversion] =
|
||||||
|
nfsd_vers(nn, 4, NFSD_TEST);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case NFSD_CLEAR:
|
case NFSD_CLEAR:
|
||||||
nfsd_supported_minorversions[minorversion] = false;
|
nfsd_netns_init_versions(nn);
|
||||||
nfsd_adjust_nfsd_versions4();
|
if (nn->nfsd4_minorversions) {
|
||||||
|
nn->nfsd4_minorversions[minorversion] = false;
|
||||||
|
nfsd_adjust_nfsd_versions4(nn);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case NFSD_TEST:
|
case NFSD_TEST:
|
||||||
return nfsd_supported_minorversions[minorversion];
|
if (nn->nfsd4_minorversions)
|
||||||
|
return nn->nfsd4_minorversions[minorversion];
|
||||||
|
return nfsd_vers(nn, 4, NFSD_TEST);
|
||||||
case NFSD_AVAIL:
|
case NFSD_AVAIL:
|
||||||
return minorversion <= NFSD_SUPPORTED_MINOR_VERSION;
|
return minorversion <= NFSD_SUPPORTED_MINOR_VERSION &&
|
||||||
|
nfsd_vers(nn, 4, NFSD_AVAIL);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -280,13 +343,9 @@ static void nfsd_shutdown_generic(void)
|
||||||
nfsd_racache_shutdown();
|
nfsd_racache_shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool nfsd_needs_lockd(void)
|
static bool nfsd_needs_lockd(struct nfsd_net *nn)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_NFSD_V3)
|
return nfsd_vers(nn, 2, NFSD_TEST) || nfsd_vers(nn, 3, NFSD_TEST);
|
||||||
return (nfsd_versions[2] != NULL) || (nfsd_versions[3] != NULL);
|
|
||||||
#else
|
|
||||||
return (nfsd_versions[2] != NULL);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nfsd_startup_net(int nrservs, struct net *net)
|
static int nfsd_startup_net(int nrservs, struct net *net)
|
||||||
|
@ -304,7 +363,7 @@ static int nfsd_startup_net(int nrservs, struct net *net)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_socks;
|
goto out_socks;
|
||||||
|
|
||||||
if (nfsd_needs_lockd() && !nn->lockd_up) {
|
if (nfsd_needs_lockd(nn) && !nn->lockd_up) {
|
||||||
ret = lockd_up(net);
|
ret = lockd_up(net);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_socks;
|
goto out_socks;
|
||||||
|
@ -437,20 +496,20 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
|
||||||
nfsd_export_flush(net);
|
nfsd_export_flush(net);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nfsd_reset_versions(void)
|
void nfsd_reset_versions(struct nfsd_net *nn)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < NFSD_NRVERS; i++)
|
for (i = 0; i < NFSD_NRVERS; i++)
|
||||||
if (nfsd_vers(i, NFSD_TEST))
|
if (nfsd_vers(nn, i, NFSD_TEST))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < NFSD_NRVERS; i++)
|
for (i = 0; i < NFSD_NRVERS; i++)
|
||||||
if (i != 4)
|
if (i != 4)
|
||||||
nfsd_vers(i, NFSD_SET);
|
nfsd_vers(nn, i, NFSD_SET);
|
||||||
else {
|
else {
|
||||||
int minor = 0;
|
int minor = 0;
|
||||||
while (nfsd_minorversion(minor, NFSD_SET) >= 0)
|
while (nfsd_minorversion(nn, minor, NFSD_SET) >= 0)
|
||||||
minor++;
|
minor++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -518,7 +577,7 @@ int nfsd_create_serv(struct net *net)
|
||||||
}
|
}
|
||||||
if (nfsd_max_blksize == 0)
|
if (nfsd_max_blksize == 0)
|
||||||
nfsd_max_blksize = nfsd_get_default_max_blksize();
|
nfsd_max_blksize = nfsd_get_default_max_blksize();
|
||||||
nfsd_reset_versions();
|
nfsd_reset_versions(nn);
|
||||||
nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
|
nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
|
||||||
&nfsd_thread_sv_ops);
|
&nfsd_thread_sv_ops);
|
||||||
if (nn->nfsd_serv == NULL)
|
if (nn->nfsd_serv == NULL)
|
||||||
|
@ -697,11 +756,44 @@ nfsd_acl_rpcbind_set(struct net *net, const struct svc_program *progp,
|
||||||
unsigned short port)
|
unsigned short port)
|
||||||
{
|
{
|
||||||
if (!nfsd_support_acl_version(version) ||
|
if (!nfsd_support_acl_version(version) ||
|
||||||
!nfsd_vers(version, NFSD_TEST))
|
!nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST))
|
||||||
return 0;
|
return 0;
|
||||||
return svc_generic_rpcbind_set(net, progp, version, family,
|
return svc_generic_rpcbind_set(net, progp, version, family,
|
||||||
proto, port);
|
proto, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __be32
|
||||||
|
nfsd_acl_init_request(struct svc_rqst *rqstp,
|
||||||
|
const struct svc_program *progp,
|
||||||
|
struct svc_process_info *ret)
|
||||||
|
{
|
||||||
|
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (likely(nfsd_support_acl_version(rqstp->rq_vers) &&
|
||||||
|
nfsd_vers(nn, rqstp->rq_vers, NFSD_TEST)))
|
||||||
|
return svc_generic_init_request(rqstp, progp, ret);
|
||||||
|
|
||||||
|
ret->mismatch.lovers = NFSD_ACL_NRVERS;
|
||||||
|
for (i = NFSD_ACL_MINVERS; i < NFSD_ACL_NRVERS; i++) {
|
||||||
|
if (nfsd_support_acl_version(rqstp->rq_vers) &&
|
||||||
|
nfsd_vers(nn, i, NFSD_TEST)) {
|
||||||
|
ret->mismatch.lovers = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret->mismatch.lovers == NFSD_ACL_NRVERS)
|
||||||
|
return rpc_prog_unavail;
|
||||||
|
ret->mismatch.hivers = NFSD_ACL_MINVERS;
|
||||||
|
for (i = NFSD_ACL_NRVERS - 1; i >= NFSD_ACL_MINVERS; i--) {
|
||||||
|
if (nfsd_support_acl_version(rqstp->rq_vers) &&
|
||||||
|
nfsd_vers(nn, i, NFSD_TEST)) {
|
||||||
|
ret->mismatch.hivers = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rpc_prog_mismatch;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -709,12 +801,42 @@ nfsd_rpcbind_set(struct net *net, const struct svc_program *progp,
|
||||||
u32 version, int family, unsigned short proto,
|
u32 version, int family, unsigned short proto,
|
||||||
unsigned short port)
|
unsigned short port)
|
||||||
{
|
{
|
||||||
if (!nfsd_vers(version, NFSD_TEST))
|
if (!nfsd_vers(net_generic(net, nfsd_net_id), version, NFSD_TEST))
|
||||||
return 0;
|
return 0;
|
||||||
return svc_generic_rpcbind_set(net, progp, version, family,
|
return svc_generic_rpcbind_set(net, progp, version, family,
|
||||||
proto, port);
|
proto, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __be32
|
||||||
|
nfsd_init_request(struct svc_rqst *rqstp,
|
||||||
|
const struct svc_program *progp,
|
||||||
|
struct svc_process_info *ret)
|
||||||
|
{
|
||||||
|
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
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++) {
|
||||||
|
if (nfsd_vers(nn, i, NFSD_TEST)) {
|
||||||
|
ret->mismatch.lovers = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret->mismatch.lovers == NFSD_NRVERS)
|
||||||
|
return rpc_prog_unavail;
|
||||||
|
ret->mismatch.hivers = NFSD_MINVERS;
|
||||||
|
for (i = NFSD_NRVERS - 1; i >= NFSD_MINVERS; i--) {
|
||||||
|
if (nfsd_vers(nn, i, NFSD_TEST)) {
|
||||||
|
ret->mismatch.hivers = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rpc_prog_mismatch;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the NFS server kernel thread
|
* This is the NFS server kernel thread
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue