Commit 89652617 authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust

NFS: Introduce "migration" mount option

Currently, the Linux client uses a unique nfs_client_id4.id string
when identifying itself to distinct NFS servers.

To support transparent state migration, the Linux client will have to
use the same nfs_client_id4 string for all servers it communicates
with (also known as the "uniform client string" approach).  Otherwise
NFS servers can not recognize that open and lock state need to be
merged after a file system transition.

Unfortunately, there are some NFSv4.0 servers currently in the field
that do not tolerate the uniform client string approach.

Thus, by default, our NFSv4.0 mounts will continue to use the current
approach, and we introduce a mount option that switches them to use
the uniform model.  Client administrators must identify which servers
can be mounted with this option.  Eventually most NFSv4.0 servers will
be able to handle the uniform approach, and we can change the default.

The first mount of a server controls the behavior for all subsequent
mounts for the lifetime of that set of mounts of that server.  After
the last mount of that server is gone, the client erases the data
structure that tracks the lease.  A subsequent lease may then honor
a different "migration" setting.

This patch adds only the infrastructure for parsing the new mount
option.  Support for uniform client strings is added in a subsequent
patch.
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent ba9b584c
...@@ -752,6 +752,8 @@ static int nfs_init_server(struct nfs_server *server, ...@@ -752,6 +752,8 @@ static int nfs_init_server(struct nfs_server *server,
data->timeo, data->retrans); data->timeo, data->retrans);
if (data->flags & NFS_MOUNT_NORESVPORT) if (data->flags & NFS_MOUNT_NORESVPORT)
set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
if (server->options & NFS_OPTION_MIGRATION)
set_bit(NFS_CS_MIGRATION, &cl_init.init_flags);
/* Allocate or find a client reference we can use */ /* Allocate or find a client reference we can use */
clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX); clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX);
......
...@@ -88,6 +88,7 @@ enum { ...@@ -88,6 +88,7 @@ enum {
Opt_sharecache, Opt_nosharecache, Opt_sharecache, Opt_nosharecache,
Opt_resvport, Opt_noresvport, Opt_resvport, Opt_noresvport,
Opt_fscache, Opt_nofscache, Opt_fscache, Opt_nofscache,
Opt_migration, Opt_nomigration,
/* Mount options that take integer arguments */ /* Mount options that take integer arguments */
Opt_port, Opt_port,
...@@ -147,6 +148,8 @@ static const match_table_t nfs_mount_option_tokens = { ...@@ -147,6 +148,8 @@ static const match_table_t nfs_mount_option_tokens = {
{ Opt_noresvport, "noresvport" }, { Opt_noresvport, "noresvport" },
{ Opt_fscache, "fsc" }, { Opt_fscache, "fsc" },
{ Opt_nofscache, "nofsc" }, { Opt_nofscache, "nofsc" },
{ Opt_migration, "migration" },
{ Opt_nomigration, "nomigration" },
{ Opt_port, "port=%s" }, { Opt_port, "port=%s" },
{ Opt_rsize, "rsize=%s" }, { Opt_rsize, "rsize=%s" },
...@@ -676,6 +679,9 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, ...@@ -676,6 +679,9 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
if (nfss->options & NFS_OPTION_FSCACHE) if (nfss->options & NFS_OPTION_FSCACHE)
seq_printf(m, ",fsc"); seq_printf(m, ",fsc");
if (nfss->options & NFS_OPTION_MIGRATION)
seq_printf(m, ",migration");
if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) { if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) {
if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONE) if (nfss->flags & NFS_MOUNT_LOOKUP_CACHE_NONE)
seq_printf(m, ",lookupcache=none"); seq_printf(m, ",lookupcache=none");
...@@ -1243,6 +1249,12 @@ static int nfs_parse_mount_options(char *raw, ...@@ -1243,6 +1249,12 @@ static int nfs_parse_mount_options(char *raw,
kfree(mnt->fscache_uniq); kfree(mnt->fscache_uniq);
mnt->fscache_uniq = NULL; mnt->fscache_uniq = NULL;
break; break;
case Opt_migration:
mnt->options |= NFS_OPTION_MIGRATION;
break;
case Opt_nomigration:
mnt->options &= NFS_OPTION_MIGRATION;
break;
/* /*
* options that take numeric values * options that take numeric values
...@@ -1535,6 +1547,10 @@ static int nfs_parse_mount_options(char *raw, ...@@ -1535,6 +1547,10 @@ static int nfs_parse_mount_options(char *raw,
if (mnt->minorversion && mnt->version != 4) if (mnt->minorversion && mnt->version != 4)
goto out_minorversion_mismatch; goto out_minorversion_mismatch;
if (mnt->options & NFS_OPTION_MIGRATION &&
mnt->version != 4 && mnt->minorversion != 0)
goto out_migration_misuse;
/* /*
* verify that any proto=/mountproto= options match the address * verify that any proto=/mountproto= options match the address
* familiies in the addr=/mountaddr= options. * familiies in the addr=/mountaddr= options.
...@@ -1572,6 +1588,10 @@ static int nfs_parse_mount_options(char *raw, ...@@ -1572,6 +1588,10 @@ static int nfs_parse_mount_options(char *raw,
printk(KERN_INFO "NFS: mount option vers=%u does not support " printk(KERN_INFO "NFS: mount option vers=%u does not support "
"minorversion=%u\n", mnt->version, mnt->minorversion); "minorversion=%u\n", mnt->version, mnt->minorversion);
return 0; return 0;
out_migration_misuse:
printk(KERN_INFO
"NFS: 'migration' not supported for this NFS version\n");
return 0;
out_nomem: out_nomem:
printk(KERN_INFO "NFS: not enough memory to parse option\n"); printk(KERN_INFO "NFS: not enough memory to parse option\n");
return 0; return 0;
......
...@@ -39,6 +39,7 @@ struct nfs_client { ...@@ -39,6 +39,7 @@ struct nfs_client {
unsigned long cl_flags; /* behavior switches */ unsigned long cl_flags; /* behavior switches */
#define NFS_CS_NORESVPORT 0 /* - use ephemeral src port */ #define NFS_CS_NORESVPORT 0 /* - use ephemeral src port */
#define NFS_CS_DISCRTRY 1 /* - disconnect on RPC retry */ #define NFS_CS_DISCRTRY 1 /* - disconnect on RPC retry */
#define NFS_CS_MIGRATION 2 /* - transparent state migr */
struct sockaddr_storage cl_addr; /* server identifier */ struct sockaddr_storage cl_addr; /* server identifier */
size_t cl_addrlen; size_t cl_addrlen;
char * cl_hostname; /* hostname of server */ char * cl_hostname; /* hostname of server */
...@@ -125,6 +126,7 @@ struct nfs_server { ...@@ -125,6 +126,7 @@ struct nfs_server {
unsigned int namelen; unsigned int namelen;
unsigned int options; /* extra options enabled by mount */ unsigned int options; /* extra options enabled by mount */
#define NFS_OPTION_FSCACHE 0x00000001 /* - local caching enabled */ #define NFS_OPTION_FSCACHE 0x00000001 /* - local caching enabled */
#define NFS_OPTION_MIGRATION 0x00000002 /* - NFSv4 migration enabled */
struct nfs_fsid fsid; struct nfs_fsid fsid;
__u64 maxfilesize; /* maximum file size */ __u64 maxfilesize; /* maximum file size */
......
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