nfs41: Check slot table for referring calls
authorMike Sager <sager@netapp.com>
Tue, 19 Jan 2010 17:54:40 +0000 (12:54 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 10 Feb 2010 13:30:55 +0000 (08:30 -0500)
Traverse a list of referring calls and look for a session/slot/seq number
match.

Signed-off-by: Mike Sager <sager@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/callback_proc.c

index defa9b4c470ebf0515d3b7da58585c0ec551e3db..631b44c1439b83f59f2f144c4b9878f9e2d62f10 100644 (file)
@@ -225,6 +225,61 @@ validate_seqid(struct nfs4_slot_table *tbl, u32 slotid, u32 seqid)
        return NULL;
 }
 
+/*
+ * For each referring call triple, check the session's slot table for
+ * a match.  If the slot is in use and the sequence numbers match, the
+ * client is still waiting for a response to the original request.
+ */
+static bool referring_call_exists(struct nfs_client *clp,
+                                 uint32_t nrclists,
+                                 struct referring_call_list *rclists)
+{
+       bool status = 0;
+       int i, j;
+       struct nfs4_session *session;
+       struct nfs4_slot_table *tbl;
+       struct referring_call_list *rclist;
+       struct referring_call *ref;
+
+       /*
+        * XXX When client trunking is implemented, this becomes
+        * a session lookup from within the loop
+        */
+       session = clp->cl_session;
+       tbl = &session->fc_slot_table;
+
+       for (i = 0; i < nrclists; i++) {
+               rclist = &rclists[i];
+               if (memcmp(session->sess_id.data,
+                          rclist->rcl_sessionid.data,
+                          NFS4_MAX_SESSIONID_LEN) != 0)
+                       continue;
+
+               for (j = 0; j < rclist->rcl_nrefcalls; j++) {
+                       ref = &rclist->rcl_refcalls[j];
+
+                       dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u "
+                               "slotid %u\n", __func__,
+                               ((u32 *)&rclist->rcl_sessionid.data)[0],
+                               ((u32 *)&rclist->rcl_sessionid.data)[1],
+                               ((u32 *)&rclist->rcl_sessionid.data)[2],
+                               ((u32 *)&rclist->rcl_sessionid.data)[3],
+                               ref->rc_sequenceid, ref->rc_slotid);
+
+                       spin_lock(&tbl->slot_tbl_lock);
+                       status = (test_bit(ref->rc_slotid, tbl->used_slots) &&
+                                 tbl->slots[ref->rc_slotid].seq_nr ==
+                                       ref->rc_sequenceid);
+                       spin_unlock(&tbl->slot_tbl_lock);
+                       if (status)
+                               goto out;
+               }
+       }
+
+out:
+       return status;
+}
+
 /* FIXME: referring calls should be processed */
 unsigned nfs4_callback_sequence(struct cb_sequenceargs *args,
                                struct cb_sequenceres *res)