Loading fs/nfs/nfs4_fs.h +2 −0 Original line number Diff line number Diff line Loading @@ -139,9 +139,11 @@ struct nfs4_state { unsigned long flags; /* Do we hold any locks? */ spinlock_t state_lock; /* Protects the lock_states list */ seqlock_t seqlock; /* Protects the stateid/open_stateid */ nfs4_stateid stateid; /* Current stateid: may be delegation */ nfs4_stateid open_stateid; /* OPEN stateid */ /* The following 3 fields are protected by owner->so_lock */ unsigned int n_rdonly; /* Number of read-only references */ unsigned int n_wronly; /* Number of write-only references */ unsigned int n_rdwr; /* Number of read/write references */ Loading fs/nfs/nfs4proc.c +11 −16 Original line number Diff line number Diff line Loading @@ -385,29 +385,28 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid * 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); } Loading Loading @@ -608,12 +607,10 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * */ 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; } Loading Loading @@ -1280,7 +1277,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) 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) { Loading @@ -1294,7 +1290,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) 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 */ Loading fs/nfs/nfs4state.c +6 −4 Original line number Diff line number Diff line Loading @@ -307,6 +307,7 @@ nfs4_alloc_open_state(void) atomic_set(&state->count, 1); INIT_LIST_HEAD(&state->lock_states); spin_lock_init(&state->state_lock); seqlock_init(&state->seqlock); return state; } Loading Loading @@ -411,7 +412,6 @@ void nfs4_put_open_state(struct nfs4_state *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; Loading @@ -419,7 +419,6 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) 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--; Loading @@ -446,7 +445,6 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) 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) { Loading Loading @@ -599,8 +597,12 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl) void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner) { struct nfs4_lock_state *lsp; int seq; 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; Loading Loading
fs/nfs/nfs4_fs.h +2 −0 Original line number Diff line number Diff line Loading @@ -139,9 +139,11 @@ struct nfs4_state { unsigned long flags; /* Do we hold any locks? */ spinlock_t state_lock; /* Protects the lock_states list */ seqlock_t seqlock; /* Protects the stateid/open_stateid */ nfs4_stateid stateid; /* Current stateid: may be delegation */ nfs4_stateid open_stateid; /* OPEN stateid */ /* The following 3 fields are protected by owner->so_lock */ unsigned int n_rdonly; /* Number of read-only references */ unsigned int n_wronly; /* Number of write-only references */ unsigned int n_rdwr; /* Number of read/write references */ Loading
fs/nfs/nfs4proc.c +11 −16 Original line number Diff line number Diff line Loading @@ -385,29 +385,28 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid * 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); } Loading Loading @@ -608,12 +607,10 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * */ 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; } Loading Loading @@ -1280,7 +1277,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) 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) { Loading @@ -1294,7 +1290,6 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) 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 */ Loading
fs/nfs/nfs4state.c +6 −4 Original line number Diff line number Diff line Loading @@ -307,6 +307,7 @@ nfs4_alloc_open_state(void) atomic_set(&state->count, 1); INIT_LIST_HEAD(&state->lock_states); spin_lock_init(&state->state_lock); seqlock_init(&state->seqlock); return state; } Loading Loading @@ -411,7 +412,6 @@ void nfs4_put_open_state(struct nfs4_state *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; Loading @@ -419,7 +419,6 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) 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--; Loading @@ -446,7 +445,6 @@ void nfs4_close_state(struct path *path, struct nfs4_state *state, mode_t mode) 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) { Loading Loading @@ -599,8 +597,12 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl) void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner) { struct nfs4_lock_state *lsp; int seq; 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; Loading