Skip to content

Commit

Permalink
NFSv4.1: Handle EXCHGID4_FLAG_CONFIRMED_R during NFSv4.1 migration
Browse files Browse the repository at this point in the history
Transparent State Migration copies a client's lease state from the
server where a filesystem used to reside to the server where it now
resides. When an NFSv4.1 client first contacts that destination
server, it uses EXCHANGE_ID to detect trunking relationships.

The lease that was copied there is returned to that client, but the
destination server sets EXCHGID4_FLAG_CONFIRMED_R when replying to
the client. This is because the lease was confirmed on the source
server (before it was copied).

Normally, when CONFIRMED_R is set, a client purges the lease and
creates a new one. However, that throws away the entire benefit of
Transparent State Migration.

Therefore, the client must not purge that lease when it is possible
that Transparent State Migration has occurred.

Reported-by: Xuan Qi <xuan.qi@oracle.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Tested-by: Xuan Qi <xuan.qi@oracle.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
  • Loading branch information
chucklever authored and amschuma-ntap committed Jul 13, 2017
1 parent 1f54189 commit 8dcbec6
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 5 deletions.
5 changes: 5 additions & 0 deletions fs/nfs/nfs4client.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
if (clp != old)
clp->cl_preserve_clid = true;
nfs_put_client(clp);
clear_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags);
return old;

error:
Expand Down Expand Up @@ -852,6 +853,8 @@ static int nfs4_set_client(struct nfs_server *server,
set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
if (server->options & NFS_OPTION_MIGRATION)
set_bit(NFS_CS_MIGRATION, &cl_init.init_flags);
if (test_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status))
set_bit(NFS_CS_TSM_POSSIBLE, &cl_init.init_flags);

/* Allocate or find a client reference we can use */
clp = nfs_get_client(&cl_init);
Expand Down Expand Up @@ -1212,9 +1215,11 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname,
return -EAFNOSUPPORT;

nfs_server_remove_lists(server);
set_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
error = nfs4_set_client(server, hostname, sap, salen, buf,
clp->cl_proto, clnt->cl_timeout,
clp->cl_minorversion, net);
clear_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
nfs_put_client(clp);
if (error != 0) {
nfs_server_insert_lists(server);
Expand Down
16 changes: 11 additions & 5 deletions fs/nfs/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,11 +352,17 @@ int nfs41_discover_server_trunking(struct nfs_client *clp,
if (clp != *result)
return 0;

/* Purge state if the client id was established in a prior instance */
if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R)
set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state);
else
set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
/*
* Purge state if the client id was established in a prior
* instance and the client id could not have arrived on the
* server via Transparent State Migration.
*/
if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R) {
if (!test_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags))
set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state);
else
set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
}
nfs4_schedule_state_manager(clp);
status = nfs_wait_client_init_complete(clp);
if (status < 0)
Expand Down
2 changes: 2 additions & 0 deletions include/linux/nfs_fs_sb.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct nfs_client {
#define NFS_CS_MIGRATION 2 /* - transparent state migr */
#define NFS_CS_INFINITE_SLOTS 3 /* - don't limit TCP slots */
#define NFS_CS_NO_RETRANS_TIMEOUT 4 /* - Disable retransmit timeouts */
#define NFS_CS_TSM_POSSIBLE 5 /* - Maybe state migration */
struct sockaddr_storage cl_addr; /* server identifier */
size_t cl_addrlen;
char * cl_hostname; /* hostname of server */
Expand Down Expand Up @@ -210,6 +211,7 @@ struct nfs_server {
unsigned long mig_status;
#define NFS_MIG_IN_TRANSITION (1)
#define NFS_MIG_FAILED (2)
#define NFS_MIG_TSM_POSSIBLE (3)

void (*destroy)(struct nfs_server *);

Expand Down

0 comments on commit 8dcbec6

Please sign in to comment.