NFSv4.1: Use seqid returned by EXCHANGE_ID after state 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).

When CONFIRMED_R is set, the client throws away the sequence ID
returned by the server. During a Transparent State Migration, however
there's no other way for the client to know what sequence ID to use
with a lease that's been migrated.

Therefore, the client must save and use the contrived slot sequence
value returned by the destination server even when CONFIRMED_R is
set.

Note that some servers always return a seqid of 1 after a migration.

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>
This commit is contained in:
Chuck Lever 2017-06-08 11:52:52 -04:00 committed by Anna Schumaker
parent 8dcbec6d20
commit 838edb9497
1 changed files with 3 additions and 4 deletions

View File

@ -7378,12 +7378,11 @@ static void nfs4_exchange_id_done(struct rpc_task *task, void *data)
if (status == 0) { if (status == 0) {
clp->cl_clientid = cdata->res.clientid; clp->cl_clientid = cdata->res.clientid;
clp->cl_exchange_flags = cdata->res.flags; clp->cl_exchange_flags = cdata->res.flags;
clp->cl_seqid = cdata->res.seqid;
/* Client ID is not confirmed */ /* Client ID is not confirmed */
if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R)) { if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R))
clear_bit(NFS4_SESSION_ESTABLISHED, clear_bit(NFS4_SESSION_ESTABLISHED,
&clp->cl_session->session_state); &clp->cl_session->session_state);
clp->cl_seqid = cdata->res.seqid;
}
kfree(clp->cl_serverowner); kfree(clp->cl_serverowner);
clp->cl_serverowner = cdata->res.server_owner; clp->cl_serverowner = cdata->res.server_owner;