nfs41: check SEQUENCE status flag
authorAlexandros Batsakis <batsakis@netapp.com>
Sat, 5 Dec 2009 18:46:14 +0000 (13:46 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Sat, 5 Dec 2009 18:46:14 +0000 (13:46 -0500)
the server can indicate a number of error conditions by setting the
appropriate bits in the SEQUENCE operation. The client re-establishes
state with the server when it receives one of those, with the action
depending on the specific case.

Signed-off-by: Alexandros Batsakis <batsakis@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
include/linux/nfs4.h
include/linux/nfs_xdr.h

index 0d25a82451d9ab1b72d42b789248e2232d9b4a83..9a866368896a61571e1b46dddde468e56b7e2913 100644 (file)
@@ -270,6 +270,7 @@ extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
 extern void nfs4_schedule_state_recovery(struct nfs_client *);
 extern void nfs4_schedule_state_manager(struct nfs_client *);
 extern int nfs4_state_mark_reclaim_nograce(struct nfs_client *clp, struct nfs4_state *state);
+extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
 extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
 extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
index d897b9e34f128659feb8e1bcefed786d1a5574ba..71993f122214c1de618b7221fda768de7d086646 100644 (file)
@@ -405,6 +405,8 @@ static void nfs41_sequence_done(struct nfs_client *clp,
                if (time_before(clp->cl_last_renewal, timestamp))
                        clp->cl_last_renewal = timestamp;
                spin_unlock(&clp->cl_lock);
+               /* Check sequence flags */
+               nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
                return;
        }
 out:
index 46c69e2248e356d2c2d1008c29f6d5009175b5d4..a86f3acf3212f84f639be199b4b30baff28846f3 100644 (file)
@@ -1173,6 +1173,28 @@ static int nfs4_reclaim_lease(struct nfs_client *clp)
 }
 
 #ifdef CONFIG_NFS_V4_1
+void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
+{
+       if (!flags)
+               return;
+       else if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) {
+               set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+               nfs4_state_start_reclaim_reboot(clp);
+               nfs4_schedule_state_recovery(clp);
+       } else if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
+                           SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED |
+                           SEQ4_STATUS_ADMIN_STATE_REVOKED |
+                           SEQ4_STATUS_RECALLABLE_STATE_REVOKED |
+                           SEQ4_STATUS_LEASE_MOVED)) {
+               set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+               nfs4_state_start_reclaim_nograce(clp);
+               nfs4_schedule_state_recovery(clp);
+       } else if (flags & (SEQ4_STATUS_CB_PATH_DOWN |
+                           SEQ4_STATUS_BACKCHANNEL_FAULT |
+                           SEQ4_STATUS_CB_PATH_DOWN_SESSION))
+               nfs_expire_all_delegations(clp);
+}
+
 static void nfs4_session_recovery_handle_error(struct nfs_client *clp, int err)
 {
        switch (err) {
index 4ddd04a1113e395c575cd23c0b7f27913e348a28..f740472370aa5fb5eb00ccd41db2f1a441280ee5 100644 (file)
@@ -4614,8 +4614,8 @@ static int decode_sequence(struct xdr_stream *xdr,
        dummy = be32_to_cpup(p++);
        /* target highest slot id - currently not processed */
        dummy = be32_to_cpup(p++);
-       /* result flags - currently not processed */
-       dummy = be32_to_cpup(p);
+       /* result flags */
+       res->sr_status_flags = be32_to_cpup(p);
        status = 0;
 out_err:
        res->sr_status = status;
index c4c060208109b35ca6ebde436c0d6302ba93cd6a..89404bfb72b65cbd2ae64c4a93ed879cb2dea813 100644 (file)
 #define SEQ4_STATUS_RECALLABLE_STATE_REVOKED   0x00000040
 #define SEQ4_STATUS_LEASE_MOVED                        0x00000080
 #define SEQ4_STATUS_RESTART_RECLAIM_NEEDED     0x00000100
+#define SEQ4_STATUS_CB_PATH_DOWN_SESSION       0x00000200
+#define SEQ4_STATUS_BACKCHANNEL_FAULT          0x00000400
 
 #define NFS4_MAX_UINT64        (~(u64)0)
 
index 8c880372536e78969360a5d7e8138df0e601c126..ea32db30c2899cb7e340b132a4cb0910e68b50ef 100644 (file)
@@ -172,6 +172,7 @@ struct nfs4_sequence_res {
        u8                      sr_slotid;      /* slot used to send request */
        int                     sr_status;      /* sequence operation status */
        unsigned long           sr_renewal_time;
+       u32                     sr_status_flags;
 };
 
 struct nfs4_get_lease_time_args {