diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-11-26 16:16:54 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-12-05 18:30:47 -0500 |
commit | c10e449827e6008ef5a4a71c0247c7eb73948e1b (patch) | |
tree | 7512d993fc182b24655d91ea930706451c0591e6 /fs/nfs | |
parent | 0ca3f4825ac92a10aa8f6534f765c44f22778dd3 (diff) |
NFSv4.1: Ping server when our session table limits are too high
If the server requests a lower target_highest_slotid, then ensure
that we ping it with at least one RPC call containing an
appropriate SEQUENCE op. This ensures that the server won't need to
send a recall callback in order to shrink the slot table.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4_fs.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 20 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 5 |
3 files changed, 23 insertions, 3 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 322bd0168ebf..8fe155ba16d1 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -321,6 +321,7 @@ int nfs41_discover_server_trunking(struct nfs_client *clp, | |||
321 | struct nfs_client **, struct rpc_cred *); | 321 | struct nfs_client **, struct rpc_cred *); |
322 | extern void nfs4_schedule_session_recovery(struct nfs4_session *, int); | 322 | extern void nfs4_schedule_session_recovery(struct nfs4_session *, int); |
323 | extern void nfs41_server_notify_target_slotid_update(struct nfs_client *clp); | 323 | extern void nfs41_server_notify_target_slotid_update(struct nfs_client *clp); |
324 | extern void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp); | ||
324 | 325 | ||
325 | #else | 326 | #else |
326 | static inline void nfs4_schedule_session_recovery(struct nfs4_session *session, int err) | 327 | static inline void nfs4_schedule_session_recovery(struct nfs4_session *session, int err) |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a0c35ab12a6b..ecd4ed3a4f65 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -389,6 +389,7 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | |||
389 | { | 389 | { |
390 | struct nfs4_session *session; | 390 | struct nfs4_session *session; |
391 | struct nfs4_slot_table *tbl; | 391 | struct nfs4_slot_table *tbl; |
392 | bool send_new_highest_used_slotid = false; | ||
392 | 393 | ||
393 | if (!res->sr_slot) { | 394 | if (!res->sr_slot) { |
394 | /* just wake up the next guy waiting since | 395 | /* just wake up the next guy waiting since |
@@ -400,12 +401,25 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | |||
400 | session = tbl->session; | 401 | session = tbl->session; |
401 | 402 | ||
402 | spin_lock(&tbl->slot_tbl_lock); | 403 | spin_lock(&tbl->slot_tbl_lock); |
404 | /* Be nice to the server: try to ensure that the last transmitted | ||
405 | * value for highest_user_slotid <= target_highest_slotid | ||
406 | */ | ||
407 | if (tbl->highest_used_slotid > tbl->target_highest_slotid) | ||
408 | send_new_highest_used_slotid = true; | ||
409 | |||
403 | nfs4_free_slot(tbl, res->sr_slot); | 410 | nfs4_free_slot(tbl, res->sr_slot); |
404 | if (!nfs4_session_draining(session)) | 411 | |
405 | rpc_wake_up_first(&tbl->slot_tbl_waitq, | 412 | if (tbl->highest_used_slotid != NFS4_NO_SLOT) |
406 | nfs4_set_task_privileged, NULL); | 413 | send_new_highest_used_slotid = false; |
414 | if (!nfs4_session_draining(session)) { | ||
415 | if (rpc_wake_up_first(&tbl->slot_tbl_waitq, | ||
416 | nfs4_set_task_privileged, NULL) != NULL) | ||
417 | send_new_highest_used_slotid = false; | ||
418 | } | ||
407 | spin_unlock(&tbl->slot_tbl_lock); | 419 | spin_unlock(&tbl->slot_tbl_lock); |
408 | res->sr_slot = NULL; | 420 | res->sr_slot = NULL; |
421 | if (send_new_highest_used_slotid) | ||
422 | nfs41_server_notify_highest_slotid_update(session->clp); | ||
409 | } | 423 | } |
410 | 424 | ||
411 | static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) | 425 | static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 1402283d152d..c137421f2123 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1961,6 +1961,11 @@ void nfs41_server_notify_target_slotid_update(struct nfs_client *clp) | |||
1961 | nfs41_ping_server(clp); | 1961 | nfs41_ping_server(clp); |
1962 | } | 1962 | } |
1963 | 1963 | ||
1964 | void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp) | ||
1965 | { | ||
1966 | nfs41_ping_server(clp); | ||
1967 | } | ||
1968 | |||
1964 | static void nfs4_reset_all_state(struct nfs_client *clp) | 1969 | static void nfs4_reset_all_state(struct nfs_client *clp) |
1965 | { | 1970 | { |
1966 | if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { | 1971 | if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) { |