aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r--fs/nfs/nfs4state.c317
1 files changed, 247 insertions, 70 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 2ef4fecf3984..6c5ed51f105e 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -116,6 +116,79 @@ struct rpc_cred *nfs4_get_renew_cred_locked(struct nfs_client *clp)
116 116
117#if defined(CONFIG_NFS_V4_1) 117#if defined(CONFIG_NFS_V4_1)
118 118
119static int nfs41_setup_state_renewal(struct nfs_client *clp)
120{
121 int status;
122 struct nfs_fsinfo fsinfo;
123
124 status = nfs4_proc_get_lease_time(clp, &fsinfo);
125 if (status == 0) {
126 /* Update lease time and schedule renewal */
127 spin_lock(&clp->cl_lock);
128 clp->cl_lease_time = fsinfo.lease_time * HZ;
129 clp->cl_last_renewal = jiffies;
130 spin_unlock(&clp->cl_lock);
131
132 nfs4_schedule_state_renewal(clp);
133 }
134
135 return status;
136}
137
138static void nfs4_end_drain_session(struct nfs_client *clp)
139{
140 struct nfs4_session *ses = clp->cl_session;
141 int max_slots;
142
143 if (test_and_clear_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state)) {
144 spin_lock(&ses->fc_slot_table.slot_tbl_lock);
145 max_slots = ses->fc_slot_table.max_slots;
146 while (max_slots--) {
147 struct rpc_task *task;
148
149 task = rpc_wake_up_next(&ses->fc_slot_table.
150 slot_tbl_waitq);
151 if (!task)
152 break;
153 rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
154 }
155 spin_unlock(&ses->fc_slot_table.slot_tbl_lock);
156 }
157}
158
159static int nfs4_begin_drain_session(struct nfs_client *clp)
160{
161 struct nfs4_session *ses = clp->cl_session;
162 struct nfs4_slot_table *tbl = &ses->fc_slot_table;
163
164 spin_lock(&tbl->slot_tbl_lock);
165 set_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state);
166 if (tbl->highest_used_slotid != -1) {
167 INIT_COMPLETION(ses->complete);
168 spin_unlock(&tbl->slot_tbl_lock);
169 return wait_for_completion_interruptible(&ses->complete);
170 }
171 spin_unlock(&tbl->slot_tbl_lock);
172 return 0;
173}
174
175int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
176{
177 int status;
178
179 nfs4_begin_drain_session(clp);
180 status = nfs4_proc_exchange_id(clp, cred);
181 if (status != 0)
182 goto out;
183 status = nfs4_proc_create_session(clp);
184 if (status != 0)
185 goto out;
186 nfs41_setup_state_renewal(clp);
187 nfs_mark_client_ready(clp, NFS_CS_READY);
188out:
189 return status;
190}
191
119struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp) 192struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp)
120{ 193{
121 struct rpc_cred *cred; 194 struct rpc_cred *cred;
@@ -693,16 +766,21 @@ struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter)
693 return new; 766 return new;
694} 767}
695 768
696void nfs_free_seqid(struct nfs_seqid *seqid) 769void nfs_release_seqid(struct nfs_seqid *seqid)
697{ 770{
698 if (!list_empty(&seqid->list)) { 771 if (!list_empty(&seqid->list)) {
699 struct rpc_sequence *sequence = seqid->sequence->sequence; 772 struct rpc_sequence *sequence = seqid->sequence->sequence;
700 773
701 spin_lock(&sequence->lock); 774 spin_lock(&sequence->lock);
702 list_del(&seqid->list); 775 list_del_init(&seqid->list);
703 spin_unlock(&sequence->lock); 776 spin_unlock(&sequence->lock);
704 rpc_wake_up(&sequence->wait); 777 rpc_wake_up(&sequence->wait);
705 } 778 }
779}
780
781void nfs_free_seqid(struct nfs_seqid *seqid)
782{
783 nfs_release_seqid(seqid);
706 kfree(seqid); 784 kfree(seqid);
707} 785}
708 786
@@ -823,7 +901,7 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp)
823 nfs4_schedule_state_manager(clp); 901 nfs4_schedule_state_manager(clp);
824} 902}
825 903
826static int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state) 904int nfs4_state_mark_reclaim_reboot(struct nfs_client *clp, struct nfs4_state *state)
827{ 905{
828 906
829 set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags); 907 set_bit(NFS_STATE_RECLAIM_REBOOT, &state->flags);
@@ -877,6 +955,10 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_
877 case -NFS4ERR_EXPIRED: 955 case -NFS4ERR_EXPIRED:
878 case -NFS4ERR_NO_GRACE: 956 case -NFS4ERR_NO_GRACE:
879 case -NFS4ERR_STALE_CLIENTID: 957 case -NFS4ERR_STALE_CLIENTID:
958 case -NFS4ERR_BADSESSION:
959 case -NFS4ERR_BADSLOT:
960 case -NFS4ERR_BAD_HIGH_SLOT:
961 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
880 goto out; 962 goto out;
881 default: 963 default:
882 printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n", 964 printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
@@ -959,6 +1041,10 @@ restart:
959 case -NFS4ERR_NO_GRACE: 1041 case -NFS4ERR_NO_GRACE:
960 nfs4_state_mark_reclaim_nograce(sp->so_client, state); 1042 nfs4_state_mark_reclaim_nograce(sp->so_client, state);
961 case -NFS4ERR_STALE_CLIENTID: 1043 case -NFS4ERR_STALE_CLIENTID:
1044 case -NFS4ERR_BADSESSION:
1045 case -NFS4ERR_BADSLOT:
1046 case -NFS4ERR_BAD_HIGH_SLOT:
1047 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
962 goto out_err; 1048 goto out_err;
963 } 1049 }
964 nfs4_put_open_state(state); 1050 nfs4_put_open_state(state);
@@ -1011,6 +1097,14 @@ static void nfs4_state_start_reclaim_reboot(struct nfs_client *clp)
1011 nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_reboot); 1097 nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_reboot);
1012} 1098}
1013 1099
1100static void nfs4_reclaim_complete(struct nfs_client *clp,
1101 const struct nfs4_state_recovery_ops *ops)
1102{
1103 /* Notify the server we're done reclaiming our state */
1104 if (ops->reclaim_complete)
1105 (void)ops->reclaim_complete(clp);
1106}
1107
1014static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) 1108static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
1015{ 1109{
1016 struct nfs4_state_owner *sp; 1110 struct nfs4_state_owner *sp;
@@ -1020,6 +1114,9 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
1020 if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) 1114 if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
1021 return; 1115 return;
1022 1116
1117 nfs4_reclaim_complete(clp,
1118 nfs4_reboot_recovery_ops[clp->cl_minorversion]);
1119
1023 for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { 1120 for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
1024 sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); 1121 sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
1025 spin_lock(&sp->so_lock); 1122 spin_lock(&sp->so_lock);
@@ -1046,25 +1143,25 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp)
1046 nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); 1143 nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce);
1047} 1144}
1048 1145
1049static void nfs4_state_end_reclaim_nograce(struct nfs_client *clp) 1146static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1050{
1051 clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
1052}
1053
1054static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1055{ 1147{
1056 switch (error) { 1148 switch (error) {
1057 case -NFS4ERR_CB_PATH_DOWN: 1149 case -NFS4ERR_CB_PATH_DOWN:
1058 nfs_handle_cb_pathdown(clp); 1150 nfs_handle_cb_pathdown(clp);
1059 break; 1151 return 0;
1152 case -NFS4ERR_NO_GRACE:
1153 nfs4_state_end_reclaim_reboot(clp);
1154 return 0;
1060 case -NFS4ERR_STALE_CLIENTID: 1155 case -NFS4ERR_STALE_CLIENTID:
1061 case -NFS4ERR_LEASE_MOVED: 1156 case -NFS4ERR_LEASE_MOVED:
1062 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1157 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1158 nfs4_state_end_reclaim_reboot(clp);
1063 nfs4_state_start_reclaim_reboot(clp); 1159 nfs4_state_start_reclaim_reboot(clp);
1064 break; 1160 break;
1065 case -NFS4ERR_EXPIRED: 1161 case -NFS4ERR_EXPIRED:
1066 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1162 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
1067 nfs4_state_start_reclaim_nograce(clp); 1163 nfs4_state_start_reclaim_nograce(clp);
1164 break;
1068 case -NFS4ERR_BADSESSION: 1165 case -NFS4ERR_BADSESSION:
1069 case -NFS4ERR_BADSLOT: 1166 case -NFS4ERR_BADSLOT:
1070 case -NFS4ERR_BAD_HIGH_SLOT: 1167 case -NFS4ERR_BAD_HIGH_SLOT:
@@ -1072,8 +1169,11 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
1072 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: 1169 case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
1073 case -NFS4ERR_SEQ_FALSE_RETRY: 1170 case -NFS4ERR_SEQ_FALSE_RETRY:
1074 case -NFS4ERR_SEQ_MISORDERED: 1171 case -NFS4ERR_SEQ_MISORDERED:
1075 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); 1172 set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
1173 /* Zero session reset errors */
1174 return 0;
1076 } 1175 }
1176 return error;
1077} 1177}
1078 1178
1079static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops) 1179static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops)
@@ -1093,8 +1193,7 @@ restart:
1093 if (status < 0) { 1193 if (status < 0) {
1094 set_bit(ops->owner_flag_bit, &sp->so_flags); 1194 set_bit(ops->owner_flag_bit, &sp->so_flags);
1095 nfs4_put_state_owner(sp); 1195 nfs4_put_state_owner(sp);
1096 nfs4_recovery_handle_error(clp, status); 1196 return nfs4_recovery_handle_error(clp, status);
1097 return status;
1098 } 1197 }
1099 nfs4_put_state_owner(sp); 1198 nfs4_put_state_owner(sp);
1100 goto restart; 1199 goto restart;
@@ -1124,8 +1223,7 @@ static int nfs4_check_lease(struct nfs_client *clp)
1124 status = ops->renew_lease(clp, cred); 1223 status = ops->renew_lease(clp, cred);
1125 put_rpccred(cred); 1224 put_rpccred(cred);
1126out: 1225out:
1127 nfs4_recovery_handle_error(clp, status); 1226 return nfs4_recovery_handle_error(clp, status);
1128 return status;
1129} 1227}
1130 1228
1131static int nfs4_reclaim_lease(struct nfs_client *clp) 1229static int nfs4_reclaim_lease(struct nfs_client *clp)
@@ -1151,55 +1249,127 @@ static int nfs4_reclaim_lease(struct nfs_client *clp)
1151} 1249}
1152 1250
1153#ifdef CONFIG_NFS_V4_1 1251#ifdef CONFIG_NFS_V4_1
1154static void nfs4_session_recovery_handle_error(struct nfs_client *clp, int err) 1252void nfs41_handle_recall_slot(struct nfs_client *clp)
1155{ 1253{
1156 switch (err) { 1254 set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
1157 case -NFS4ERR_STALE_CLIENTID: 1255 nfs4_schedule_state_recovery(clp);
1158 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1256}
1159 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); 1257
1258static void nfs4_reset_all_state(struct nfs_client *clp)
1259{
1260 if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) {
1261 clp->cl_boot_time = CURRENT_TIME;
1262 nfs4_state_start_reclaim_nograce(clp);
1263 nfs4_schedule_state_recovery(clp);
1160 } 1264 }
1161} 1265}
1162 1266
1267static void nfs41_handle_server_reboot(struct nfs_client *clp)
1268{
1269 if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) {
1270 nfs4_state_start_reclaim_reboot(clp);
1271 nfs4_schedule_state_recovery(clp);
1272 }
1273}
1274
1275static void nfs41_handle_state_revoked(struct nfs_client *clp)
1276{
1277 /* Temporary */
1278 nfs4_reset_all_state(clp);
1279}
1280
1281static void nfs41_handle_recallable_state_revoked(struct nfs_client *clp)
1282{
1283 /* This will need to handle layouts too */
1284 nfs_expire_all_delegations(clp);
1285}
1286
1287static void nfs41_handle_cb_path_down(struct nfs_client *clp)
1288{
1289 nfs_expire_all_delegations(clp);
1290 if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0)
1291 nfs4_schedule_state_recovery(clp);
1292}
1293
1294void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
1295{
1296 if (!flags)
1297 return;
1298 else if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED)
1299 nfs41_handle_server_reboot(clp);
1300 else if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
1301 SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED |
1302 SEQ4_STATUS_ADMIN_STATE_REVOKED |
1303 SEQ4_STATUS_LEASE_MOVED))
1304 nfs41_handle_state_revoked(clp);
1305 else if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED)
1306 nfs41_handle_recallable_state_revoked(clp);
1307 else if (flags & (SEQ4_STATUS_CB_PATH_DOWN |
1308 SEQ4_STATUS_BACKCHANNEL_FAULT |
1309 SEQ4_STATUS_CB_PATH_DOWN_SESSION))
1310 nfs41_handle_cb_path_down(clp);
1311}
1312
1163static int nfs4_reset_session(struct nfs_client *clp) 1313static int nfs4_reset_session(struct nfs_client *clp)
1164{ 1314{
1165 int status; 1315 int status;
1166 1316
1317 nfs4_begin_drain_session(clp);
1167 status = nfs4_proc_destroy_session(clp->cl_session); 1318 status = nfs4_proc_destroy_session(clp->cl_session);
1168 if (status && status != -NFS4ERR_BADSESSION && 1319 if (status && status != -NFS4ERR_BADSESSION &&
1169 status != -NFS4ERR_DEADSESSION) { 1320 status != -NFS4ERR_DEADSESSION) {
1170 nfs4_session_recovery_handle_error(clp, status); 1321 status = nfs4_recovery_handle_error(clp, status);
1171 goto out; 1322 goto out;
1172 } 1323 }
1173 1324
1174 memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN); 1325 memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN);
1175 status = nfs4_proc_create_session(clp, 1); 1326 status = nfs4_proc_create_session(clp);
1176 if (status) 1327 if (status) {
1177 nfs4_session_recovery_handle_error(clp, status); 1328 status = nfs4_recovery_handle_error(clp, status);
1178 /* fall through*/ 1329 goto out;
1330 }
1331 /* create_session negotiated new slot table */
1332 clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
1333
1334 /* Let the state manager reestablish state */
1335 if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
1336 nfs41_setup_state_renewal(clp);
1179out: 1337out:
1180 /* Wake up the next rpc task even on error */
1181 rpc_wake_up_next(&clp->cl_session->fc_slot_table.slot_tbl_waitq);
1182 return status; 1338 return status;
1183} 1339}
1184 1340
1185static int nfs4_initialize_session(struct nfs_client *clp) 1341static int nfs4_recall_slot(struct nfs_client *clp)
1186{ 1342{
1187 int status; 1343 struct nfs4_slot_table *fc_tbl = &clp->cl_session->fc_slot_table;
1344 struct nfs4_channel_attrs *fc_attrs = &clp->cl_session->fc_attrs;
1345 struct nfs4_slot *new, *old;
1346 int i;
1347
1348 nfs4_begin_drain_session(clp);
1349 new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot),
1350 GFP_KERNEL);
1351 if (!new)
1352 return -ENOMEM;
1188 1353
1189 status = nfs4_proc_create_session(clp, 0); 1354 spin_lock(&fc_tbl->slot_tbl_lock);
1190 if (!status) { 1355 for (i = 0; i < fc_tbl->target_max_slots; i++)
1191 nfs_mark_client_ready(clp, NFS_CS_READY); 1356 new[i].seq_nr = fc_tbl->slots[i].seq_nr;
1192 } else if (status == -NFS4ERR_STALE_CLIENTID) { 1357 old = fc_tbl->slots;
1193 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1358 fc_tbl->slots = new;
1194 set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); 1359 fc_tbl->max_slots = fc_tbl->target_max_slots;
1195 } else { 1360 fc_tbl->target_max_slots = 0;
1196 nfs_mark_client_ready(clp, status); 1361 fc_attrs->max_reqs = fc_tbl->max_slots;
1197 } 1362 spin_unlock(&fc_tbl->slot_tbl_lock);
1198 return status; 1363
1364 kfree(old);
1365 nfs4_end_drain_session(clp);
1366 return 0;
1199} 1367}
1368
1200#else /* CONFIG_NFS_V4_1 */ 1369#else /* CONFIG_NFS_V4_1 */
1201static int nfs4_reset_session(struct nfs_client *clp) { return 0; } 1370static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
1202static int nfs4_initialize_session(struct nfs_client *clp) { return 0; } 1371static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; }
1372static int nfs4_recall_slot(struct nfs_client *clp) { return 0; }
1203#endif /* CONFIG_NFS_V4_1 */ 1373#endif /* CONFIG_NFS_V4_1 */
1204 1374
1205/* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors 1375/* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors
@@ -1212,6 +1382,7 @@ static void nfs4_set_lease_expired(struct nfs_client *clp, int status)
1212 case -NFS4ERR_DELAY: 1382 case -NFS4ERR_DELAY:
1213 case -NFS4ERR_CLID_INUSE: 1383 case -NFS4ERR_CLID_INUSE:
1214 case -EAGAIN: 1384 case -EAGAIN:
1385 case -EKEYEXPIRED:
1215 break; 1386 break;
1216 1387
1217 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery 1388 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
@@ -1234,7 +1405,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
1234 status = nfs4_reclaim_lease(clp); 1405 status = nfs4_reclaim_lease(clp);
1235 if (status) { 1406 if (status) {
1236 nfs4_set_lease_expired(clp, status); 1407 nfs4_set_lease_expired(clp, status);
1237 if (status == -EAGAIN) 1408 if (test_bit(NFS4CLNT_LEASE_EXPIRED,
1409 &clp->cl_state))
1238 continue; 1410 continue;
1239 if (clp->cl_cons_state == 1411 if (clp->cl_cons_state ==
1240 NFS_CS_SESSION_INITING) 1412 NFS_CS_SESSION_INITING)
@@ -1242,61 +1414,67 @@ static void nfs4_state_manager(struct nfs_client *clp)
1242 goto out_error; 1414 goto out_error;
1243 } 1415 }
1244 clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state); 1416 clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
1417 set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state);
1245 } 1418 }
1246 1419
1247 if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { 1420 if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
1248 status = nfs4_check_lease(clp); 1421 status = nfs4_check_lease(clp);
1249 if (status != 0) 1422 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
1250 continue; 1423 continue;
1424 if (status < 0 && status != -NFS4ERR_CB_PATH_DOWN)
1425 goto out_error;
1251 } 1426 }
1427
1252 /* Initialize or reset the session */ 1428 /* Initialize or reset the session */
1253 if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) 1429 if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)
1254 && nfs4_has_session(clp)) { 1430 && nfs4_has_session(clp)) {
1255 if (clp->cl_cons_state == NFS_CS_SESSION_INITING) 1431 status = nfs4_reset_session(clp);
1256 status = nfs4_initialize_session(clp); 1432 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
1257 else 1433 continue;
1258 status = nfs4_reset_session(clp); 1434 if (status < 0)
1259 if (status) {
1260 if (status == -NFS4ERR_STALE_CLIENTID)
1261 continue;
1262 goto out_error; 1435 goto out_error;
1263 }
1264 } 1436 }
1437
1265 /* First recover reboot state... */ 1438 /* First recover reboot state... */
1266 if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { 1439 if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
1267 status = nfs4_do_reclaim(clp, 1440 status = nfs4_do_reclaim(clp,
1268 nfs4_reboot_recovery_ops[clp->cl_minorversion]); 1441 nfs4_reboot_recovery_ops[clp->cl_minorversion]);
1269 if (status == -NFS4ERR_STALE_CLIENTID) 1442 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
1270 continue; 1443 test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state))
1271 if (test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
1272 continue; 1444 continue;
1273 nfs4_state_end_reclaim_reboot(clp); 1445 nfs4_state_end_reclaim_reboot(clp);
1274 continue; 1446 if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state))
1447 continue;
1448 if (status < 0)
1449 goto out_error;
1275 } 1450 }
1276 1451
1277 /* Now recover expired state... */ 1452 /* Now recover expired state... */
1278 if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { 1453 if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
1279 status = nfs4_do_reclaim(clp, 1454 status = nfs4_do_reclaim(clp,
1280 nfs4_nograce_recovery_ops[clp->cl_minorversion]); 1455 nfs4_nograce_recovery_ops[clp->cl_minorversion]);
1281 if (status < 0) { 1456 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
1282 set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); 1457 test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) ||
1283 if (status == -NFS4ERR_STALE_CLIENTID) 1458 test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
1284 continue; 1459 continue;
1285 if (status == -NFS4ERR_EXPIRED) 1460 if (status < 0)
1286 continue;
1287 if (test_bit(NFS4CLNT_SESSION_SETUP,
1288 &clp->cl_state))
1289 continue;
1290 goto out_error; 1461 goto out_error;
1291 } else
1292 nfs4_state_end_reclaim_nograce(clp);
1293 continue;
1294 } 1462 }
1295 1463
1464 nfs4_end_drain_session(clp);
1296 if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { 1465 if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
1297 nfs_client_return_marked_delegations(clp); 1466 nfs_client_return_marked_delegations(clp);
1298 continue; 1467 continue;
1299 } 1468 }
1469 /* Recall session slots */
1470 if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state)
1471 && nfs4_has_session(clp)) {
1472 status = nfs4_recall_slot(clp);
1473 if (status < 0)
1474 goto out_error;
1475 continue;
1476 }
1477
1300 1478
1301 nfs4_clear_state_manager_bit(clp); 1479 nfs4_clear_state_manager_bit(clp);
1302 /* Did we race with an attempt to give us more work? */ 1480 /* Did we race with an attempt to give us more work? */
@@ -1309,8 +1487,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
1309out_error: 1487out_error:
1310 printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" 1488 printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
1311 " with error %d\n", clp->cl_hostname, -status); 1489 " with error %d\n", clp->cl_hostname, -status);
1312 if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) 1490 nfs4_end_drain_session(clp);
1313 nfs4_state_end_reclaim_reboot(clp);
1314 nfs4_clear_state_manager_bit(clp); 1491 nfs4_clear_state_manager_bit(clp);
1315} 1492}
1316 1493