delegation.c | 24 ++++++++++++++++++++++++ delegation.h | 1 + nfs4proc.c | 8 ++++++-- nfs4state.c | 6 ++++-- 4 files changed, 35 insertions(+), 4 deletions(-) diff -u --recursive --new-file --show-c-function linux-2.6.8-40-delegation_cache/fs/nfs/delegation.c linux-2.6.8-41-cb_pathdown/fs/nfs/delegation.c --- linux-2.6.8-40-delegation_cache/fs/nfs/delegation.c 2004-08-05 14:00:50.000000000 -0700 +++ linux-2.6.8-41-cb_pathdown/fs/nfs/delegation.c 2004-08-05 18:13:48.000000000 -0700 @@ -195,6 +195,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 -u --recursive --new-file --show-c-function linux-2.6.8-40-delegation_cache/fs/nfs/delegation.h linux-2.6.8-41-cb_pathdown/fs/nfs/delegation.h --- linux-2.6.8-40-delegation_cache/fs/nfs/delegation.h 2004-08-05 14:00:50.000000000 -0700 +++ linux-2.6.8-41-cb_pathdown/fs/nfs/delegation.h 2004-08-05 18:14:11.000000000 -0700 @@ -30,6 +30,7 @@ int nfs_async_inode_return_delegation(st 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 -u --recursive --new-file --show-c-function linux-2.6.8-40-delegation_cache/fs/nfs/nfs4proc.c linux-2.6.8-41-cb_pathdown/fs/nfs/nfs4proc.c --- linux-2.6.8-40-delegation_cache/fs/nfs/nfs4proc.c 2004-08-05 14:00:42.000000000 -0700 +++ linux-2.6.8-41-cb_pathdown/fs/nfs/nfs4proc.c 2004-08-05 18:25:14.000000000 -0700 @@ -1935,9 +1935,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)) @@ -1970,11 +1972,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 -u --recursive --new-file --show-c-function linux-2.6.8-40-delegation_cache/fs/nfs/nfs4state.c linux-2.6.8-41-cb_pathdown/fs/nfs/nfs4state.c --- linux-2.6.8-40-delegation_cache/fs/nfs/nfs4state.c 2004-08-05 14:00:36.000000000 -0700 +++ linux-2.6.8-41-cb_pathdown/fs/nfs/nfs4state.c 2004-08-05 18:20:11.000000000 -0700 @@ -844,7 +844,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); @@ -860,7 +860,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) @@ -883,6 +883,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: