NFSv4.1: Ping server when our session table limits are too high
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Mon, 26 Nov 2012 21:16:54 +0000 (16:16 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 5 Dec 2012 23:30:47 +0000 (00:30 +0100)
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>
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c

index 322bd0168ebf410857a2f56706a52a5dbcb303d9..8fe155ba16d1a30d263a3b2d78c12758562b0339 100644 (file)
@@ -321,6 +321,7 @@ int nfs41_discover_server_trunking(struct nfs_client *clp,
                        struct nfs_client **, struct rpc_cred *);
 extern void nfs4_schedule_session_recovery(struct nfs4_session *, int);
 extern void nfs41_server_notify_target_slotid_update(struct nfs_client *clp);
+extern void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp);
 
 #else
 static inline void nfs4_schedule_session_recovery(struct nfs4_session *session, int err)
index a0c35ab12a6bfebf6d6306b94d3a54bfd67c5932..ecd4ed3a4f6537afbea7edc9ecebba3f54c97517 100644 (file)
@@ -389,6 +389,7 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
 {
        struct nfs4_session *session;
        struct nfs4_slot_table *tbl;
+       bool send_new_highest_used_slotid = false;
 
        if (!res->sr_slot) {
                /* just wake up the next guy waiting since
@@ -400,12 +401,25 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
        session = tbl->session;
 
        spin_lock(&tbl->slot_tbl_lock);
+       /* Be nice to the server: try to ensure that the last transmitted
+        * value for highest_user_slotid <= target_highest_slotid
+        */
+       if (tbl->highest_used_slotid > tbl->target_highest_slotid)
+               send_new_highest_used_slotid = true;
+
        nfs4_free_slot(tbl, res->sr_slot);
-       if (!nfs4_session_draining(session))
-               rpc_wake_up_first(&tbl->slot_tbl_waitq,
-                               nfs4_set_task_privileged, NULL);
+
+       if (tbl->highest_used_slotid != NFS4_NO_SLOT)
+               send_new_highest_used_slotid = false;
+       if (!nfs4_session_draining(session)) {
+               if (rpc_wake_up_first(&tbl->slot_tbl_waitq,
+                               nfs4_set_task_privileged, NULL) != NULL)
+                       send_new_highest_used_slotid = false;
+       }
        spin_unlock(&tbl->slot_tbl_lock);
        res->sr_slot = NULL;
+       if (send_new_highest_used_slotid)
+               nfs41_server_notify_highest_slotid_update(session->clp);
 }
 
 static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
index 1402283d152d48626134d046bd591e303b80050c..c137421f21233f978bf2e26b508f93843abc7aaa 100644 (file)
@@ -1961,6 +1961,11 @@ void nfs41_server_notify_target_slotid_update(struct nfs_client *clp)
        nfs41_ping_server(clp);
 }
 
+void nfs41_server_notify_highest_slotid_update(struct nfs_client *clp)
+{
+       nfs41_ping_server(clp);
+}
+
 static void nfs4_reset_all_state(struct nfs_client *clp)
 {
        if (test_and_set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) {