static void nfs_set_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
{
- spin_lock(&state->owner->so_lock);
- spin_lock(&state->inode->i_lock);
+ write_seqlock(&state->seqlock);
nfs_set_open_stateid_locked(state, stateid, open_flags);
- spin_unlock(&state->inode->i_lock);
- spin_unlock(&state->owner->so_lock);
+ write_sequnlock(&state->seqlock);
}
static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, nfs4_stateid *deleg_stateid, int open_flags)
{
- struct inode *inode = state->inode;
-
open_flags &= (FMODE_READ|FMODE_WRITE);
- /* Protect against nfs4_find_state_byowner() */
- spin_lock(&state->owner->so_lock);
- spin_lock(&inode->i_lock);
+ /*
+ * Protect the call to nfs4_state_set_mode_locked and
+ * serialise the stateid update
+ */
+ write_seqlock(&state->seqlock);
if (deleg_stateid != NULL) {
memcpy(state->stateid.data, deleg_stateid->data, sizeof(state->stateid.data));
set_bit(NFS_DELEGATED_STATE, &state->flags);
}
if (open_stateid != NULL)
nfs_set_open_stateid_locked(state, open_stateid, open_flags);
+ write_sequnlock(&state->seqlock);
+ spin_lock(&state->owner->so_lock);
update_open_stateflags(state, open_flags);
- spin_unlock(&inode->i_lock);
spin_unlock(&state->owner->so_lock);
}
*/
if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0 &&
memcmp(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data)) != 0) {
- spin_lock(&state->owner->so_lock);
- spin_lock(&state->inode->i_lock);
+ write_seqlock(&state->seqlock);
if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0)
memcpy(state->stateid.data, state->open_stateid.data, sizeof(state->stateid.data));
- spin_unlock(&state->inode->i_lock);
- spin_unlock(&state->owner->so_lock);
+ write_sequnlock(&state->seqlock);
}
return 0;
}
mode = FMODE_READ|FMODE_WRITE;
clear_rd = clear_wr = clear_rdwr = 0;
spin_lock(&state->owner->so_lock);
- spin_lock(&calldata->inode->i_lock);
/* Calculate the change in open mode */
if (state->n_rdwr == 0) {
if (state->n_rdonly == 0) {
clear_rdwr |= test_and_clear_bit(NFS_O_RDWR_STATE, &state->flags);
}
}
- spin_unlock(&calldata->inode->i_lock);
spin_unlock(&state->owner->so_lock);
if (!clear_rd && !clear_wr && !clear_rdwr) {
/* Note: exit _without_ calling nfs4_close_done */
atomic_set(&state->count, 1);
INIT_LIST_HEAD(&state->lock_states);
spin_lock_init(&state->state_lock);
+ seqlock_init(&state->seqlock);
return state;
}
*/
void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode)
{
- struct inode *inode = state->inode;
struct nfs4_state_owner *owner = state->owner;
int call_close = 0;
int newstate;
atomic_inc(&owner->so_count);
/* Protect against nfs4_find_state() */
spin_lock(&owner->so_lock);
- spin_lock(&inode->i_lock);
switch (mode & (FMODE_READ | FMODE_WRITE)) {
case FMODE_READ:
state->n_rdonly--;
clear_bit(NFS_DELEGATED_STATE, &state->flags);
}
nfs4_state_set_mode_locked(state, newstate);
- spin_unlock(&inode->i_lock);
spin_unlock(&owner->so_lock);
if (!call_close) {
void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
{
struct nfs4_lock_state *lsp;
+ int seq;
- memcpy(dst, &state->stateid, sizeof(*dst));
+ do {
+ seq = read_seqbegin(&state->seqlock);
+ memcpy(dst, &state->stateid, sizeof(*dst));
+ } while (read_seqretry(&state->seqlock, seq));
if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
return;