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.c118
1 files changed, 98 insertions, 20 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c1e2733f4fa4..6c5ed51f105e 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1249,26 +1249,65 @@ static int nfs4_reclaim_lease(struct nfs_client *clp)
1249} 1249}
1250 1250
1251#ifdef CONFIG_NFS_V4_1 1251#ifdef CONFIG_NFS_V4_1
1252void nfs41_handle_recall_slot(struct nfs_client *clp)
1253{
1254 set_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
1255 nfs4_schedule_state_recovery(clp);
1256}
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);
1264 }
1265}
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
1252void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) 1294void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
1253{ 1295{
1254 if (!flags) 1296 if (!flags)
1255 return; 1297 return;
1256 else if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) { 1298 else if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED)
1257 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1299 nfs41_handle_server_reboot(clp);
1258 nfs4_state_start_reclaim_reboot(clp); 1300 else if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
1259 nfs4_schedule_state_recovery(clp);
1260 } else if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
1261 SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED | 1301 SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED |
1262 SEQ4_STATUS_ADMIN_STATE_REVOKED | 1302 SEQ4_STATUS_ADMIN_STATE_REVOKED |
1263 SEQ4_STATUS_RECALLABLE_STATE_REVOKED | 1303 SEQ4_STATUS_LEASE_MOVED))
1264 SEQ4_STATUS_LEASE_MOVED)) { 1304 nfs41_handle_state_revoked(clp);
1265 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 1305 else if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED)
1266 nfs4_state_start_reclaim_nograce(clp); 1306 nfs41_handle_recallable_state_revoked(clp);
1267 nfs4_schedule_state_recovery(clp); 1307 else if (flags & (SEQ4_STATUS_CB_PATH_DOWN |
1268 } else if (flags & (SEQ4_STATUS_CB_PATH_DOWN |
1269 SEQ4_STATUS_BACKCHANNEL_FAULT | 1308 SEQ4_STATUS_BACKCHANNEL_FAULT |
1270 SEQ4_STATUS_CB_PATH_DOWN_SESSION)) 1309 SEQ4_STATUS_CB_PATH_DOWN_SESSION))
1271 nfs_expire_all_delegations(clp); 1310 nfs41_handle_cb_path_down(clp);
1272} 1311}
1273 1312
1274static int nfs4_reset_session(struct nfs_client *clp) 1313static int nfs4_reset_session(struct nfs_client *clp)
@@ -1285,23 +1324,52 @@ static int nfs4_reset_session(struct nfs_client *clp)
1285 1324
1286 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);
1287 status = nfs4_proc_create_session(clp); 1326 status = nfs4_proc_create_session(clp);
1288 if (status) 1327 if (status) {
1289 status = nfs4_recovery_handle_error(clp, status); 1328 status = nfs4_recovery_handle_error(clp, status);
1329 goto out;
1330 }
1331 /* create_session negotiated new slot table */
1332 clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
1290 1333
1291out: 1334 /* Let the state manager reestablish state */
1292 /* 1335 if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
1293 * Let the state manager reestablish state
1294 */
1295 if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) &&
1296 status == 0)
1297 nfs41_setup_state_renewal(clp); 1336 nfs41_setup_state_renewal(clp);
1298 1337out:
1299 return status; 1338 return status;
1300} 1339}
1301 1340
1341static int nfs4_recall_slot(struct nfs_client *clp)
1342{
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;
1353
1354 spin_lock(&fc_tbl->slot_tbl_lock);
1355 for (i = 0; i < fc_tbl->target_max_slots; i++)
1356 new[i].seq_nr = fc_tbl->slots[i].seq_nr;
1357 old = fc_tbl->slots;
1358 fc_tbl->slots = new;
1359 fc_tbl->max_slots = fc_tbl->target_max_slots;
1360 fc_tbl->target_max_slots = 0;
1361 fc_attrs->max_reqs = fc_tbl->max_slots;
1362 spin_unlock(&fc_tbl->slot_tbl_lock);
1363
1364 kfree(old);
1365 nfs4_end_drain_session(clp);
1366 return 0;
1367}
1368
1302#else /* CONFIG_NFS_V4_1 */ 1369#else /* CONFIG_NFS_V4_1 */
1303static int nfs4_reset_session(struct nfs_client *clp) { return 0; } 1370static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
1304static int nfs4_end_drain_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; }
1305#endif /* CONFIG_NFS_V4_1 */ 1373#endif /* CONFIG_NFS_V4_1 */
1306 1374
1307/* 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
@@ -1314,6 +1382,7 @@ static void nfs4_set_lease_expired(struct nfs_client *clp, int status)
1314 case -NFS4ERR_DELAY: 1382 case -NFS4ERR_DELAY:
1315 case -NFS4ERR_CLID_INUSE: 1383 case -NFS4ERR_CLID_INUSE:
1316 case -EAGAIN: 1384 case -EAGAIN:
1385 case -EKEYEXPIRED:
1317 break; 1386 break;
1318 1387
1319 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery 1388 case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
@@ -1397,6 +1466,15 @@ static void nfs4_state_manager(struct nfs_client *clp)
1397 nfs_client_return_marked_delegations(clp); 1466 nfs_client_return_marked_delegations(clp);
1398 continue; 1467 continue;
1399 } 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
1400 1478
1401 nfs4_clear_state_manager_bit(clp); 1479 nfs4_clear_state_manager_bit(clp);
1402 /* Did we race with an attempt to give us more work? */ 1480 /* Did we race with an attempt to give us more work? */