Skip to content

Commit 8dcbec6

Browse files
chuckleveramschuma-ntap
authored andcommitted
NFSv4.1: Handle EXCHGID4_FLAG_CONFIRMED_R during NFSv4.1 migration
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 <[email protected]> Signed-off-by: Chuck Lever <[email protected]> Tested-by: Xuan Qi <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 1f54189 commit 8dcbec6

3 files changed

Lines changed: 18 additions & 5 deletions

File tree

fs/nfs/nfs4client.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
414414
if (clp != old)
415415
clp->cl_preserve_clid = true;
416416
nfs_put_client(clp);
417+
clear_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags);
417418
return old;
418419

419420
error:
@@ -852,6 +853,8 @@ static int nfs4_set_client(struct nfs_server *server,
852853
set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
853854
if (server->options & NFS_OPTION_MIGRATION)
854855
set_bit(NFS_CS_MIGRATION, &cl_init.init_flags);
856+
if (test_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status))
857+
set_bit(NFS_CS_TSM_POSSIBLE, &cl_init.init_flags);
855858

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

12141217
nfs_server_remove_lists(server);
1218+
set_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
12151219
error = nfs4_set_client(server, hostname, sap, salen, buf,
12161220
clp->cl_proto, clnt->cl_timeout,
12171221
clp->cl_minorversion, net);
1222+
clear_bit(NFS_MIG_TSM_POSSIBLE, &server->mig_status);
12181223
nfs_put_client(clp);
12191224
if (error != 0) {
12201225
nfs_server_insert_lists(server);

fs/nfs/nfs4state.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -352,11 +352,17 @@ int nfs41_discover_server_trunking(struct nfs_client *clp,
352352
if (clp != *result)
353353
return 0;
354354

355-
/* Purge state if the client id was established in a prior instance */
356-
if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R)
357-
set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state);
358-
else
359-
set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
355+
/*
356+
* Purge state if the client id was established in a prior
357+
* instance and the client id could not have arrived on the
358+
* server via Transparent State Migration.
359+
*/
360+
if (clp->cl_exchange_flags & EXCHGID4_FLAG_CONFIRMED_R) {
361+
if (!test_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags))
362+
set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state);
363+
else
364+
set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
365+
}
360366
nfs4_schedule_state_manager(clp);
361367
status = nfs_wait_client_init_complete(clp);
362368
if (status < 0)

include/linux/nfs_fs_sb.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct nfs_client {
4242
#define NFS_CS_MIGRATION 2 /* - transparent state migr */
4343
#define NFS_CS_INFINITE_SLOTS 3 /* - don't limit TCP slots */
4444
#define NFS_CS_NO_RETRANS_TIMEOUT 4 /* - Disable retransmit timeouts */
45+
#define NFS_CS_TSM_POSSIBLE 5 /* - Maybe state migration */
4546
struct sockaddr_storage cl_addr; /* server identifier */
4647
size_t cl_addrlen;
4748
char * cl_hostname; /* hostname of server */
@@ -210,6 +211,7 @@ struct nfs_server {
210211
unsigned long mig_status;
211212
#define NFS_MIG_IN_TRANSITION (1)
212213
#define NFS_MIG_FAILED (2)
214+
#define NFS_MIG_TSM_POSSIBLE (3)
213215

214216
void (*destroy)(struct nfs_server *);
215217

0 commit comments

Comments
 (0)