aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-10-04 17:59:08 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-10-19 19:42:53 -0400
commit6eaa61496fb3b93cceface7a296415fc4c030bce (patch)
tree88093c8ca07058b940a871d92fd1074968098dbe /fs
parentae1007d37e00144b72906a4bdc47d517ae91bcc1 (diff)
NFSv4: Don't call nfs4_reclaim_complete() on receiving NFS4ERR_STALE_CLIENTID
If the server sends us an NFS4ERR_STALE_CLIENTID while the state management thread is busy reclaiming state, we do want to treat all state that wasn't reclaimed before the STALE_CLIENTID as if a network partition occurred (see the edge conditions described in RFC3530 and RFC5661). What we do not want to do is to send an nfs4_reclaim_complete(), since we haven't yet even started reclaiming state after the server rebooted. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: stable@kernel.org
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/nfs4state.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 3e2f19b04c06..940cf7c070af 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1138,16 +1138,14 @@ static void nfs4_reclaim_complete(struct nfs_client *clp,
1138 (void)ops->reclaim_complete(clp); 1138 (void)ops->reclaim_complete(clp);
1139} 1139}
1140 1140
1141static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) 1141static int nfs4_state_clear_reclaim_reboot(struct nfs_client *clp)
1142{ 1142{
1143 struct nfs4_state_owner *sp; 1143 struct nfs4_state_owner *sp;
1144 struct rb_node *pos; 1144 struct rb_node *pos;
1145 struct nfs4_state *state; 1145 struct nfs4_state *state;
1146 1146
1147 if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) 1147 if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
1148 return; 1148 return 0;
1149
1150 nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops);
1151 1149
1152 for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { 1150 for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
1153 sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); 1151 sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
@@ -1161,6 +1159,14 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
1161 } 1159 }
1162 1160
1163 nfs_delegation_reap_unclaimed(clp); 1161 nfs_delegation_reap_unclaimed(clp);
1162 return 1;
1163}
1164
1165static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
1166{
1167 if (!nfs4_state_clear_reclaim_reboot(clp))
1168 return;
1169 nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops);
1164} 1170}
1165 1171
1166static void nfs_delegation_clear_all(struct nfs_client *clp) 1172static void nfs_delegation_clear_all(struct nfs_client *clp)
@@ -1187,7 +1193,7 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1187 case -NFS4ERR_STALE_CLIENTID: 1193 case -NFS4ERR_STALE_CLIENTID:
1188 case -NFS4ERR_LEASE_MOVED: 1194 case -NFS4ERR_LEASE_MOVED:
1189 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1195 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1190 nfs4_state_end_reclaim_reboot(clp); 1196 nfs4_state_clear_reclaim_reboot(clp);
1191 nfs4_state_start_reclaim_reboot(clp); 1197 nfs4_state_start_reclaim_reboot(clp);
1192 break; 1198 break;
1193 case -NFS4ERR_EXPIRED: 1199 case -NFS4ERR_EXPIRED: