Skip to content

Commit

Permalink
NFSv4.1 handle DS stateid errors
Browse files Browse the repository at this point in the history
Handle DS READ and WRITE stateid errors by recovering the stateid on the MDS.

NFS4ERR_OLD_STATEID is ignored as the client always sends a
state sequenceid of zero for DS READ and WRITE stateids.

Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
  • Loading branch information
Andy Adamson authored and Trond Myklebust committed Mar 7, 2012
1 parent 4f1abd2 commit 9cb8196
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 1 deletion.
1 change: 1 addition & 0 deletions fs/nfs/delegation.c
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ void nfs_remove_bad_delegation(struct inode *inode)
nfs_free_delegation(delegation);
}
}
EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation);

/**
* nfs_expire_all_delegation_types
Expand Down
29 changes: 28 additions & 1 deletion fs/nfs/nfs4filelayout.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <linux/sunrpc/metrics.h>

#include "internal.h"
#include "delegation.h"
#include "nfs4filelayout.h"

#define NFSDBG_FACILITY NFSDBG_PNFS_LD
Expand Down Expand Up @@ -86,12 +87,31 @@ static int filelayout_async_handle_error(struct rpc_task *task,
struct nfs_client *clp,
int *reset)
{
struct nfs_server *mds_server = NFS_SERVER(state->inode);
struct nfs_client *mds_client = mds_server->nfs_client;

if (task->tk_status >= 0)
return 0;

*reset = 0;

switch (task->tk_status) {
/* MDS state errors */
case -NFS4ERR_DELEG_REVOKED:
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_BAD_STATEID:
if (state != NULL)
nfs_remove_bad_delegation(state->inode);
case -NFS4ERR_OPENMODE:
if (state == NULL)
break;
nfs4_schedule_stateid_recovery(mds_server, state);
goto wait_on_recovery;
case -NFS4ERR_EXPIRED:
if (state != NULL)
nfs4_schedule_stateid_recovery(mds_server, state);
nfs4_schedule_lease_recovery(mds_client);
goto wait_on_recovery;
/* DS session errors */
case -NFS4ERR_BADSESSION:
case -NFS4ERR_BADSLOT:
case -NFS4ERR_BAD_HIGH_SLOT:
Expand All @@ -117,8 +137,15 @@ static int filelayout_async_handle_error(struct rpc_task *task,
*reset = 1;
break;
}
out:
task->tk_status = 0;
return -EAGAIN;
wait_on_recovery:
rpc_sleep_on(&mds_client->cl_rpcwaitq, task, NULL);
if (test_bit(NFS4CLNT_MANAGER_RUNNING, &mds_client->cl_state) == 0)
rpc_wake_up_queued_task(&mds_client->cl_rpcwaitq, task);
goto out;

}

/* NFS_PROTO call done callback routines */
Expand Down
2 changes: 2 additions & 0 deletions fs/nfs/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,7 @@ void nfs4_schedule_lease_recovery(struct nfs_client *clp)
set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
nfs4_schedule_state_manager(clp);
}
EXPORT_SYMBOL_GPL(nfs4_schedule_lease_recovery);

void nfs4_schedule_path_down_recovery(struct nfs_client *clp)
{
Expand Down Expand Up @@ -1109,6 +1110,7 @@ void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4
nfs4_state_mark_reclaim_nograce(clp, state);
nfs4_schedule_state_manager(clp);
}
EXPORT_SYMBOL_GPL(nfs4_schedule_stateid_recovery);

void nfs_inode_find_state_and_recover(struct inode *inode,
const nfs4_stateid *stateid)
Expand Down

0 comments on commit 9cb8196

Please sign in to comment.