NFSv4.1: CB_RECALL_SLOT must schedule a sequence op after updating targets
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 21 Nov 2012 14:06:11 +0000 (09:06 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 5 Dec 2012 23:30:43 +0000 (00:30 +0100)
RFC5661 requires us to make sure that the server knows we've updated
our slot table size by sending at least one SEQUENCE op containing the
new 'highest_slotid' value.
We can do so using the 'CHECK_LEASE' functionality of the state
manager.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/callback_proc.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4state.c

index 8610bd1..f99faad 100644 (file)
@@ -570,6 +570,7 @@ __be32 nfs4_callback_recallslot(struct cb_recallslotargs *args, void *dummy,
        status = htonl(NFS4_OK);
 
        nfs41_set_target_slotid(fc_tbl, args->crsa_target_highest_slotid);
+       nfs41_server_notify_target_slotid_update(cps->clp);
 out:
        dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
        return status;
index fa1a055..0a109ec 100644 (file)
@@ -334,6 +334,7 @@ struct rpc_cred *nfs4_get_exchange_id_cred(struct nfs_client *clp);
 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);
 #else
 static inline void nfs4_schedule_session_recovery(struct nfs4_session *session, int err)
 {
index 3940cd4..896be21 100644 (file)
@@ -1904,6 +1904,18 @@ void nfs4_schedule_session_recovery(struct nfs4_session *session, int err)
 }
 EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery);
 
+static void nfs41_ping_server(struct nfs_client *clp)
+{
+       /* Use CHECK_LEASE to ping the server with a SEQUENCE */
+       set_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
+       nfs4_schedule_state_manager(clp);
+}
+
+void nfs41_server_notify_target_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) {