diff options
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 8406cacd3240..9164758c1ace 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1249,6 +1249,12 @@ 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 | |||
1252 | void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) | 1258 | void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) |
1253 | { | 1259 | { |
1254 | if (!flags) | 1260 | if (!flags) |
@@ -1299,9 +1305,38 @@ out: | |||
1299 | return status; | 1305 | return status; |
1300 | } | 1306 | } |
1301 | 1307 | ||
1308 | static int nfs4_recall_slot(struct nfs_client *clp) | ||
1309 | { | ||
1310 | struct nfs4_slot_table *fc_tbl = &clp->cl_session->fc_slot_table; | ||
1311 | struct nfs4_channel_attrs *fc_attrs = &clp->cl_session->fc_attrs; | ||
1312 | struct nfs4_slot *new, *old; | ||
1313 | int i; | ||
1314 | |||
1315 | nfs4_begin_drain_session(clp); | ||
1316 | new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot), | ||
1317 | GFP_KERNEL); | ||
1318 | if (!new) | ||
1319 | return -ENOMEM; | ||
1320 | |||
1321 | spin_lock(&fc_tbl->slot_tbl_lock); | ||
1322 | for (i = 0; i < fc_tbl->target_max_slots; i++) | ||
1323 | new[i].seq_nr = fc_tbl->slots[i].seq_nr; | ||
1324 | old = fc_tbl->slots; | ||
1325 | fc_tbl->slots = new; | ||
1326 | fc_tbl->max_slots = fc_tbl->target_max_slots; | ||
1327 | fc_tbl->target_max_slots = 0; | ||
1328 | fc_attrs->max_reqs = fc_tbl->max_slots; | ||
1329 | spin_unlock(&fc_tbl->slot_tbl_lock); | ||
1330 | |||
1331 | kfree(old); | ||
1332 | nfs4_end_drain_session(clp); | ||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1302 | #else /* CONFIG_NFS_V4_1 */ | 1336 | #else /* CONFIG_NFS_V4_1 */ |
1303 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } | 1337 | static int nfs4_reset_session(struct nfs_client *clp) { return 0; } |
1304 | static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } | 1338 | static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; } |
1339 | static int nfs4_recall_slot(struct nfs_client *clp) { return 0; } | ||
1305 | #endif /* CONFIG_NFS_V4_1 */ | 1340 | #endif /* CONFIG_NFS_V4_1 */ |
1306 | 1341 | ||
1307 | /* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors | 1342 | /* Set NFS4CLNT_LEASE_EXPIRED for all v4.0 errors and for recoverable errors |
@@ -1398,6 +1433,15 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1398 | nfs_client_return_marked_delegations(clp); | 1433 | nfs_client_return_marked_delegations(clp); |
1399 | continue; | 1434 | continue; |
1400 | } | 1435 | } |
1436 | /* Recall session slots */ | ||
1437 | if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state) | ||
1438 | && nfs4_has_session(clp)) { | ||
1439 | status = nfs4_recall_slot(clp); | ||
1440 | if (status < 0) | ||
1441 | goto out_error; | ||
1442 | continue; | ||
1443 | } | ||
1444 | |||
1401 | 1445 | ||
1402 | nfs4_clear_state_manager_bit(clp); | 1446 | nfs4_clear_state_manager_bit(clp); |
1403 | /* Did we race with an attempt to give us more work? */ | 1447 | /* Did we race with an attempt to give us more work? */ |