diff options
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 118 |
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 |
1252 | void 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 | |||
1258 | static 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 | |||
1267 | static 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 | |||
1275 | static void nfs41_handle_state_revoked(struct nfs_client *clp) | ||
1276 | { | ||
1277 | /* Temporary */ | ||
1278 | nfs4_reset_all_state(clp); | ||
1279 | } | ||
1280 | |||
1281 | static 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 | |||
1287 | static 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 | |||
1252 | void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) | 1294 | void 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 | ||
1274 | static int nfs4_reset_session(struct nfs_client *clp) | 1313 | static 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 | ||
1291 | out: | 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 | 1337 | out: | |
1299 | return status; | 1338 | return status; |
1300 | } | 1339 | } |
1301 | 1340 | ||
1341 | static 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 */ |
1303 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } | 1370 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } |
1304 | static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } | 1371 | static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } |
1372 | static 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? */ |