NFSv4: Allow the state manager to mark an open_owner as being recovered
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Thu, 7 Feb 2013 19:41:11 +0000 (14:41 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Mon, 11 Feb 2013 20:33:11 +0000 (15:33 -0500)
This patch adds a seqcount_t lock for use by the state manager to
signal that an open owner has been recovered. This mechanism will be
used by the delegation, open and byte range lock code in order to
figure out if they need to replay requests due to collisions with
lock recovery.

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

index a3f488b074a2f0d55d561de8f2e529c7d4614b34..b12b73472020e0a7bc7287f7c08ddc9e8df523a8 100644 (file)
@@ -13,6 +13,8 @@
 
 #define NFS4_MAX_LOOP_ON_RECOVER (10)
 
+#include <linux/seqlock.h>
+
 struct idmap;
 
 enum nfs4_client_state {
@@ -90,6 +92,7 @@ struct nfs4_state_owner {
        unsigned long        so_flags;
        struct list_head     so_states;
        struct nfs_seqid_counter so_seqid;
+       seqcount_t           so_reclaim_seqcount;
 };
 
 enum {
index e61f68d5ef218dd64cdfec220bab02069cf1d72e..fff97228cdec14e0649cfc639776b4890883e360 100644 (file)
@@ -518,6 +518,7 @@ nfs4_alloc_state_owner(struct nfs_server *server,
        nfs4_init_seqid_counter(&sp->so_seqid);
        atomic_set(&sp->so_count, 1);
        INIT_LIST_HEAD(&sp->so_lru);
+       seqcount_init(&sp->so_reclaim_seqcount);
        return sp;
 }
 
@@ -1390,8 +1391,9 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
         * recovering after a network partition or a reboot from a
         * server that doesn't support a grace period.
         */
-restart:
        spin_lock(&sp->so_lock);
+       write_seqcount_begin(&sp->so_reclaim_seqcount);
+restart:
        list_for_each_entry(state, &sp->so_states, open_states) {
                if (!test_and_clear_bit(ops->state_flag_bit, &state->flags))
                        continue;
@@ -1412,6 +1414,7 @@ restart:
                                }
                                spin_unlock(&state->state_lock);
                                nfs4_put_open_state(state);
+                               spin_lock(&sp->so_lock);
                                goto restart;
                        }
                }
@@ -1449,12 +1452,17 @@ restart:
                                goto out_err;
                }
                nfs4_put_open_state(state);
+               spin_lock(&sp->so_lock);
                goto restart;
        }
+       write_seqcount_end(&sp->so_reclaim_seqcount);
        spin_unlock(&sp->so_lock);
        return 0;
 out_err:
        nfs4_put_open_state(state);
+       spin_lock(&sp->so_lock);
+       write_seqcount_end(&sp->so_reclaim_seqcount);
+       spin_unlock(&sp->so_lock);
        return status;
 }