Commit c137afab authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Allow the state manager to mark an open_owner as being recovered

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent c5f5e9c5
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#define NFS4_MAX_LOOP_ON_RECOVER (10) #define NFS4_MAX_LOOP_ON_RECOVER (10)
#include <linux/seqlock.h>
struct idmap; struct idmap;
enum nfs4_client_state { enum nfs4_client_state {
...@@ -90,6 +92,7 @@ struct nfs4_state_owner { ...@@ -90,6 +92,7 @@ struct nfs4_state_owner {
unsigned long so_flags; unsigned long so_flags;
struct list_head so_states; struct list_head so_states;
struct nfs_seqid_counter so_seqid; struct nfs_seqid_counter so_seqid;
seqcount_t so_reclaim_seqcount;
}; };
enum { enum {
......
...@@ -518,6 +518,7 @@ nfs4_alloc_state_owner(struct nfs_server *server, ...@@ -518,6 +518,7 @@ nfs4_alloc_state_owner(struct nfs_server *server,
nfs4_init_seqid_counter(&sp->so_seqid); nfs4_init_seqid_counter(&sp->so_seqid);
atomic_set(&sp->so_count, 1); atomic_set(&sp->so_count, 1);
INIT_LIST_HEAD(&sp->so_lru); INIT_LIST_HEAD(&sp->so_lru);
seqcount_init(&sp->so_reclaim_seqcount);
return sp; return sp;
} }
...@@ -1390,8 +1391,9 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs ...@@ -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 * recovering after a network partition or a reboot from a
* server that doesn't support a grace period. * server that doesn't support a grace period.
*/ */
restart:
spin_lock(&sp->so_lock); spin_lock(&sp->so_lock);
write_seqcount_begin(&sp->so_reclaim_seqcount);
restart:
list_for_each_entry(state, &sp->so_states, open_states) { list_for_each_entry(state, &sp->so_states, open_states) {
if (!test_and_clear_bit(ops->state_flag_bit, &state->flags)) if (!test_and_clear_bit(ops->state_flag_bit, &state->flags))
continue; continue;
...@@ -1412,6 +1414,7 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs ...@@ -1412,6 +1414,7 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
} }
spin_unlock(&state->state_lock); spin_unlock(&state->state_lock);
nfs4_put_open_state(state); nfs4_put_open_state(state);
spin_lock(&sp->so_lock);
goto restart; goto restart;
} }
} }
...@@ -1449,12 +1452,17 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs ...@@ -1449,12 +1452,17 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
goto out_err; goto out_err;
} }
nfs4_put_open_state(state); nfs4_put_open_state(state);
spin_lock(&sp->so_lock);
goto restart; goto restart;
} }
write_seqcount_end(&sp->so_reclaim_seqcount);
spin_unlock(&sp->so_lock); spin_unlock(&sp->so_lock);
return 0; return 0;
out_err: out_err:
nfs4_put_open_state(state); nfs4_put_open_state(state);
spin_lock(&sp->so_lock);
write_seqcount_end(&sp->so_reclaim_seqcount);
spin_unlock(&sp->so_lock);
return status; return status;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment