aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/Kconfig13
-rw-r--r--fs/nfs/client.c12
-rw-r--r--fs/nfs/internal.h7
-rw-r--r--fs/nfs/mount_clnt.c7
-rw-r--r--fs/nfs/super.c34
5 files changed, 65 insertions, 8 deletions
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig
index 5f93cfacb3d1..73135eb5d0ae 100644
--- a/fs/nfs/Kconfig
+++ b/fs/nfs/Kconfig
@@ -39,6 +39,19 @@ config NFS_V2
If unsure, say Y.
+config NFS_DEF_FILE_IO_SIZE
+ int "Default size for NFS I/O read and write at runtime"
+ depends on NFS_FS
+ default "4096"
+ help
+ To change the default rsize and wsize supported by the NFS client,
+ adjust NFS_DEF_FILE_IO_SIZE. 64KB is a typical maximum, but some
+ servers can support a megabyte or more. The default is left at 4096
+ bytes, which is reasonable for NFS over UDP, however, for some
+ systems, setting a smaller value like 1024 can work around
+ limitations in the driver or hardware and result in overall
+ improved performance.
+
config NFS_V3
tristate "NFS client support for NFS version 3"
depends on NFS_FS
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index b9129e2befea..d59f42ceb53d 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -9,7 +9,6 @@
* 2 of the License, or (at your option) any later version.
*/
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
@@ -70,7 +69,7 @@ static const struct rpc_version *nfs_version[5] = {
[4] = NULL,
};
-const struct rpc_program nfs_program = {
+struct rpc_program nfs_program = {
.name = "nfs",
.number = NFS_PROGRAM,
.nrvers = ARRAY_SIZE(nfs_version),
@@ -162,6 +161,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
goto error_dealloc;
clp->rpc_ops = clp->cl_nfs_mod->rpc_ops;
+ clp->nfs_prog = cl_init->nfs_prog;
refcount_set(&clp->cl_count, 1);
clp->cl_cons_state = NFS_CS_INITING;
@@ -317,6 +317,9 @@ again:
/* Match nfsv4 minorversion */
if (clp->cl_minorversion != data->minorversion)
continue;
+ if (clp->nfs_prog != data->nfs_prog)
+ continue;
+
/* Match the full socket address */
if (!rpc_cmp_addr_port(sap, clap))
/* Match all xprt_switch full socket addresses */
@@ -520,6 +523,10 @@ int nfs_create_rpc_client(struct nfs_client *clp,
if (!IS_ERR(clp->cl_rpcclient))
return 0;
+ if (clp->nfs_prog)
+ nfs_program.number = clp->nfs_prog;
+ else
+ nfs_program.number = NFS_PROGRAM;
clnt = rpc_create(&args);
if (IS_ERR(clnt)) {
dprintk("%s: cannot create RPC client. Error = %ld\n",
@@ -657,6 +664,7 @@ static int nfs_init_server(struct nfs_server *server,
.proto = data->nfs_server.protocol,
.net = data->net,
.timeparms = &timeparms,
+ .nfs_prog = data->nfs_prog,
};
struct nfs_client *clp;
int error;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 8357ff69962f..a97b081ab843 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -83,6 +83,7 @@ struct nfs_client_initdata {
u32 minorversion;
struct net *net;
const struct rpc_timeout *timeparms;
+ int nfs_prog;
};
/*
@@ -94,6 +95,8 @@ struct nfs_parsed_mount_data {
unsigned int timeo, retrans;
unsigned int acregmin, acregmax,
acdirmin, acdirmax;
+ int nfs_prog;
+ int mount_prog;
unsigned int namlen;
unsigned int options;
unsigned int bsize;
@@ -150,11 +153,11 @@ struct nfs_mount_info {
struct nfs_fh *mntfh;
};
-extern int nfs_mount(struct nfs_mount_request *info);
+extern int nfs_mount(struct nfs_mount_request *info, int prog);
extern void nfs_umount(const struct nfs_mount_request *info);
/* client.c */
-extern const struct rpc_program nfs_program;
+extern struct rpc_program nfs_program;
extern void nfs_clients_init(struct net *net);
extern struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *);
int nfs_create_rpc_client(struct nfs_client *, const struct nfs_client_initdata *, rpc_authflavor_t);
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index d979ff4fee7e..7035dc1797c2 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -66,7 +66,7 @@ enum {
MOUNTPROC3_EXPORT = 5,
};
-static const struct rpc_program mnt_program;
+static struct rpc_program mnt_program;
/*
* Defined by OpenGroup XNFS Version 3W, chapter 8
@@ -143,7 +143,7 @@ struct mnt_fhstatus {
* with the list from the server or a faked-up list if the server didn't
* provide one.
*/
-int nfs_mount(struct nfs_mount_request *info)
+int nfs_mount(struct nfs_mount_request *info, int m_prog)
{
struct mountres result = {
.fh = info->fh,
@@ -177,6 +177,7 @@ int nfs_mount(struct nfs_mount_request *info)
if (info->noresvport)
args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
+ mnt_program.number = m_prog;
mnt_clnt = rpc_create(&args);
if (IS_ERR(mnt_clnt))
goto out_clnt_err;
@@ -530,7 +531,7 @@ static const struct rpc_version *mnt_version[] = {
static struct rpc_stat mnt_stats;
-static const struct rpc_program mnt_program = {
+static struct rpc_program mnt_program = {
.name = "mount",
.number = NFS_MNT_PROGRAM,
.nrvers = ARRAY_SIZE(mnt_version),
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 5e470e233c83..6be98319ee98 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -102,6 +102,8 @@ enum {
Opt_mountport,
Opt_mountvers,
Opt_minorversion,
+ Opt_mountprog,
+ Opt_nfsprog,
/* Mount options that take string arguments */
Opt_nfsvers,
@@ -167,6 +169,8 @@ static const match_table_t nfs_mount_option_tokens = {
{ Opt_mountport, "mountport=%s" },
{ Opt_mountvers, "mountvers=%s" },
{ Opt_minorversion, "minorversion=%s" },
+ { Opt_mountprog, "mountprog=%s" },
+ { Opt_nfsprog, "nfsprog=%s" },
{ Opt_nfsvers, "nfsvers=%s" },
{ Opt_nfsvers, "vers=%s" },
@@ -922,6 +926,8 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void)
data->acregmax = NFS_DEF_ACREGMAX;
data->acdirmin = NFS_DEF_ACDIRMIN;
data->acdirmax = NFS_DEF_ACDIRMAX;
+ data->nfs_prog = NFS_PROGRAM;
+ data->mount_prog = NFS_MNT_PROGRAM;
data->mount_server.port = NFS_UNSPEC_PORT;
data->nfs_server.port = NFS_UNSPEC_PORT;
data->nfs_server.protocol = XPRT_TRANSPORT_TCP;
@@ -1389,6 +1395,26 @@ static int nfs_parse_mount_options(char *raw,
goto out_invalid_value;
mnt->acdirmax = option;
break;
+ case Opt_mountprog:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ rc = kstrtoul(string, 10, &option);
+ kfree(string);
+ if (rc != 0)
+ goto out_invalid_value;
+ mnt->mount_prog = option;
+ break;
+ case Opt_nfsprog:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ rc = kstrtoul(string, 10, &option);
+ kfree(string);
+ if (rc != 0)
+ goto out_invalid_value;
+ mnt->nfs_prog = option;
+ break;
case Opt_actimeo:
if (nfs_get_option_ul(args, &option))
goto out_invalid_value;
@@ -1789,7 +1815,7 @@ static int nfs_request_mount(struct nfs_parsed_mount_data *args,
* Now ask the mount server to map our export path
* to a file handle.
*/
- status = nfs_mount(&request);
+ status = nfs_mount(&request,args->mount_prog);
if (status != 0) {
dfprintk(MOUNT, "NFS: unable to mount server %s, error %d\n",
request.hostname, status);
@@ -2097,6 +2123,9 @@ static int nfs23_validate_mount_data(void *options,
}
break;
+ case 7:
+ args->nfs_prog = (data->version >= 7) ? data->nfs_prog : NFS_PROGRAM;
+ break;
default:
return NFS_TEXT_DATA;
}
@@ -2159,6 +2188,7 @@ static int nfs_validate_text_mount_data(void *options,
int max_namelen = PAGE_SIZE;
int max_pathlen = NFS_MAXPATHLEN;
struct sockaddr *sap = (struct sockaddr *)&args->nfs_server.address;
+ args->nfs_prog = NFS_PROGRAM;
if (nfs_parse_mount_options((char *)options, args) == 0)
return -EINVAL;
@@ -2778,6 +2808,8 @@ static int nfs4_validate_mount_data(void *options,
args->version = 4;
+ args->nfs_prog = NFS_PROGRAM;
+
switch (data->version) {
case 1:
if (data->host_addrlen > sizeof(args->nfs_server.address))