Skip to content

Commit

Permalink
NFS: Force server to drop NFSv4 state
Browse files Browse the repository at this point in the history
nfs4_reset_all_state() refreshes the boot verifier a server sees to
trigger that server to wipe this client's state.  This function is
invoked when an NFSv4.1 server reports that it has revoked some or
all of a client's NFSv4 state.

To facilitate server trunking discovery, we will eventually want to
move the cl_boot_time field to a more global structure.  The Uniform
Client String model (and specifically, server trunking detection)
requires that all servers see the same boot verifier until the client
actually does reboot, and not a fresh verifier every time the client
unmounts and remounts the server.

Without the cl_boot_time field, however, nfs4_reset_all_state() will
have to find some other way to force the server to purge the client's
NFSv4 state.

Because these verifiers are opaque (ie, the server doesn't know or
care that they happen to be timestamps), we can force the server
to wipe NFSv4 state by updating the boot verifier as we do now, then
immediately afterwards establish a fresh client ID using the old boot
verifier again.

Hopefully there are no extra paranoid server implementations that keep
track of the client's boot verifiers and prevent clients from reusing
a previous one.

Signed-off-by: Chuck Lever <[email protected]>
Signed-off-by: Trond Myklebust <[email protected]>
  • Loading branch information
chucklever authored and Trond Myklebust committed May 22, 2012
1 parent ce1c8fc commit 2c820d9
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 4 deletions.
1 change: 1 addition & 0 deletions fs/nfs/nfs4_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum nfs4_client_state {
NFS4CLNT_RECALL_SLOT,
NFS4CLNT_LEASE_CONFIRM,
NFS4CLNT_SERVER_SCOPE_MISMATCH,
NFS4CLNT_PURGE_STATE,
};

enum nfs4_session_state {
Expand Down
11 changes: 9 additions & 2 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3908,8 +3908,15 @@ static void nfs4_construct_boot_verifier(struct nfs_client *clp,
{
__be32 verf[2];

verf[0] = (__be32)clp->cl_boot_time.tv_sec;
verf[1] = (__be32)clp->cl_boot_time.tv_nsec;
if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) {
/* An impossible timestamp guarantees this value
* will never match a generated boot time. */
verf[0] = 0;
verf[1] = (__be32)(NSEC_PER_SEC + 1);
} else {
verf[0] = (__be32)clp->cl_boot_time.tv_sec;
verf[1] = (__be32)clp->cl_boot_time.tv_nsec;
}
memcpy(bootverf->data, verf, sizeof(bootverf->data));
}

Expand Down
13 changes: 11 additions & 2 deletions fs/nfs/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -1615,7 +1615,7 @@ void nfs41_handle_recall_slot(struct nfs_client *clp)
static void nfs4_reset_all_state(struct nfs_client *clp)
{
if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) {
clp->cl_boot_time = CURRENT_TIME;
set_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state);
nfs4_state_start_reclaim_nograce(clp);
nfs4_schedule_state_manager(clp);
}
Expand All @@ -1631,7 +1631,6 @@ static void nfs41_handle_server_reboot(struct nfs_client *clp)

static void nfs41_handle_state_revoked(struct nfs_client *clp)
{
/* Temporary */
nfs4_reset_all_state(clp);
}

Expand All @@ -1652,6 +1651,10 @@ void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
{
if (!flags)
return;

dprintk("%s: \"%s\" (client ID %llx) flags=0x%08x\n",
__func__, clp->cl_hostname, clp->cl_clientid, flags);

if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED)
nfs41_handle_server_reboot(clp);
if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
Expand Down Expand Up @@ -1762,6 +1765,12 @@ static void nfs4_state_manager(struct nfs_client *clp)

/* Ensure exclusive access to NFSv4 state */
do {
if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) {
nfs4_reclaim_lease(clp);
clear_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state);
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
}

if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
/* We're going to have to re-establish a clientid */
status = nfs4_reclaim_lease(clp);
Expand Down

0 comments on commit 2c820d9

Please sign in to comment.