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? */ |
