]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
NFSv4: Don't call nfs4_reclaim_complete() on receiving NFS4ERR_STALE_CLIENTID
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Mon, 4 Oct 2010 21:59:08 +0000 (17:59 -0400)
committerAndi Kleen <ak@linux.intel.com>
Tue, 14 Dec 2010 22:40:03 +0000 (23:40 +0100)
commit 6eaa61496fb3b93cceface7a296415fc4c030bce upstream.

If the server sends us an NFS4ERR_STALE_CLIENTID while the state management
thread is busy reclaiming state, we do want to treat all state that wasn't
reclaimed before the STALE_CLIENTID as if a network partition occurred (see
the edge conditions described in RFC3530 and RFC5661).
What we do not want to do is to send an nfs4_reclaim_complete(), since we
haven't yet even started reclaiming state after the server rebooted.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
fs/nfs/nfs4state.c

index 34acf5926fdc3e4ec73e2a531f0e61166f26c0c0..53f05ddce765573908614c3829385fa1845c52e8 100644 (file)
@@ -1111,17 +1111,14 @@ static void nfs4_reclaim_complete(struct nfs_client *clp,
                (void)ops->reclaim_complete(clp);
 }
 
-static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
+static int nfs4_state_clear_reclaim_reboot(struct nfs_client *clp)
 {
        struct nfs4_state_owner *sp;
        struct rb_node *pos;
        struct nfs4_state *state;
 
        if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
-               return;
-
-       nfs4_reclaim_complete(clp,
-               nfs4_reboot_recovery_ops[clp->cl_minorversion]);
+               return 0;
 
        for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
                sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
@@ -1135,6 +1132,14 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
        }
 
        nfs_delegation_reap_unclaimed(clp);
+       return 1;
+}
+
+static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
+{
+       if (!nfs4_state_clear_reclaim_reboot(clp))
+               return;
+       nfs4_reclaim_complete(clp, nfs4_reboot_recovery_ops[clp->cl_minorversion]);
 }
 
 static void nfs_delegation_clear_all(struct nfs_client *clp)
@@ -1161,7 +1166,7 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_LEASE_MOVED:
                        set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-                       nfs4_state_end_reclaim_reboot(clp);
+                       nfs4_state_clear_reclaim_reboot(clp);
                        nfs4_state_start_reclaim_reboot(clp);
                        break;
                case -NFS4ERR_EXPIRED: