From ef7306b458390381e9884855acdb6371e22785b7 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 23 Aug 2004 12:00:57 -0400 Subject: [PATCH] NFSv4: return all delegations we hold if the server issues a NFS4ERR_CB_PATH_DOWN error. --- fs/nfs/delegation.c | 24 ++++++++++++++++++++++++ fs/nfs/delegation.h | 1 + fs/nfs/nfs4proc.c | 8 ++++++-- fs/nfs/nfs4state.c | 6 ++++-- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index cb510fb292ee0..5b9c60f97791c 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -193,6 +193,30 @@ restart: spin_unlock(&clp->cl_lock); } +/* + * Return all delegations following an NFS4ERR_CB_PATH_DOWN error. + */ +void nfs_handle_cb_pathdown(struct nfs4_client *clp) +{ + struct nfs_delegation *delegation; + struct inode *inode; + + if (clp == NULL) + return; +restart: + spin_lock(&clp->cl_lock); + list_for_each_entry(delegation, &clp->cl_delegations, super_list) { + inode = igrab(delegation->inode); + if (inode == NULL) + continue; + spin_unlock(&clp->cl_lock); + nfs_inode_return_delegation(inode); + iput(inode); + goto restart; + } + spin_unlock(&clp->cl_lock); +} + struct recall_threadargs { struct inode *inode; struct nfs4_client *clp; diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 2be2f32abb9a3..3f6c45a29d6a4 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h @@ -30,6 +30,7 @@ int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *s struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle); void nfs_return_all_delegations(struct super_block *sb); +void nfs_handle_cb_pathdown(struct nfs4_client *clp); void nfs_delegation_mark_reclaim(struct nfs4_client *clp); void nfs_delegation_reap_unclaimed(struct nfs4_client *clp); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f63d3d60ea86e..c95512eec50e0 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1940,9 +1940,11 @@ renew_done(struct rpc_task *task) if (task->tk_status < 0) { switch (task->tk_status) { case -NFS4ERR_STALE_CLIENTID: + case -NFS4ERR_EXPIRED: + case -NFS4ERR_CB_PATH_DOWN: nfs4_schedule_state_recovery(clp); - return; } + return; } spin_lock(&clp->cl_lock); if (time_before(clp->cl_last_renewal,timestamp)) @@ -1975,11 +1977,13 @@ nfs4_proc_renew(struct nfs4_client *clp) int status; status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); + if (status < 0) + return status; spin_lock(&clp->cl_lock); if (time_before(clp->cl_last_renewal,now)) clp->cl_last_renewal = now; spin_unlock(&clp->cl_lock); - return status; + return 0; } /* diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 20068657e24b9..8f0e19913b2ff 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -842,7 +842,7 @@ static int reclaimer(void *ptr) struct reclaimer_args *args = (struct reclaimer_args *)ptr; struct nfs4_client *clp = args->clp; struct nfs4_state_owner *sp; - int status; + int status = 0; daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr)); allow_signal(SIGKILL); @@ -858,7 +858,7 @@ static int reclaimer(void *ptr) goto out; restart_loop: status = nfs4_proc_renew(clp); - if (status == 0) + if (status == 0 || status == -NFS4ERR_CB_PATH_DOWN) goto out; status = nfs4_init_client(clp); if (status) @@ -881,6 +881,8 @@ out: unlock_kernel(); wake_up_all(&clp->cl_waitq); rpc_wake_up(&clp->cl_rpcwaitq); + if (status == -NFS4ERR_CB_PATH_DOWN) + nfs_handle_cb_pathdown(clp); nfs4_put_client(clp); return 0; out_error: -- 2.53.0