mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
NFSv4: Fix up locking for nfs4_state_owner
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
4e51336a00
commit
ec07342828
3 changed files with 18 additions and 5 deletions
|
@ -126,6 +126,7 @@ static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status
|
||||||
* semantics by allowing the server to identify replayed requests.
|
* semantics by allowing the server to identify replayed requests.
|
||||||
*/
|
*/
|
||||||
struct nfs4_state_owner {
|
struct nfs4_state_owner {
|
||||||
|
spinlock_t so_lock;
|
||||||
struct list_head so_list; /* per-clientid list of state_owners */
|
struct list_head so_list; /* per-clientid list of state_owners */
|
||||||
struct nfs4_client *so_client;
|
struct nfs4_client *so_client;
|
||||||
u32 so_id; /* 32-bit identifier, unique */
|
u32 so_id; /* 32-bit identifier, unique */
|
||||||
|
|
|
@ -212,6 +212,7 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid,
|
||||||
|
|
||||||
open_flags &= (FMODE_READ|FMODE_WRITE);
|
open_flags &= (FMODE_READ|FMODE_WRITE);
|
||||||
/* Protect against nfs4_find_state() */
|
/* Protect against nfs4_find_state() */
|
||||||
|
spin_lock(&state->owner->so_lock);
|
||||||
spin_lock(&inode->i_lock);
|
spin_lock(&inode->i_lock);
|
||||||
state->state |= open_flags;
|
state->state |= open_flags;
|
||||||
/* NB! List reordering - see the reclaim code for why. */
|
/* NB! List reordering - see the reclaim code for why. */
|
||||||
|
@ -221,6 +222,7 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid,
|
||||||
state->nreaders++;
|
state->nreaders++;
|
||||||
memcpy(&state->stateid, stateid, sizeof(state->stateid));
|
memcpy(&state->stateid, stateid, sizeof(state->stateid));
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
|
spin_unlock(&state->owner->so_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -267,6 +267,7 @@ nfs4_alloc_state_owner(void)
|
||||||
sp = kzalloc(sizeof(*sp),GFP_KERNEL);
|
sp = kzalloc(sizeof(*sp),GFP_KERNEL);
|
||||||
if (!sp)
|
if (!sp)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
spin_lock_init(&sp->so_lock);
|
||||||
INIT_LIST_HEAD(&sp->so_states);
|
INIT_LIST_HEAD(&sp->so_states);
|
||||||
INIT_LIST_HEAD(&sp->so_delegations);
|
INIT_LIST_HEAD(&sp->so_delegations);
|
||||||
rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue");
|
rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue");
|
||||||
|
@ -438,20 +439,23 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner)
|
||||||
if (state)
|
if (state)
|
||||||
goto out;
|
goto out;
|
||||||
new = nfs4_alloc_open_state();
|
new = nfs4_alloc_open_state();
|
||||||
|
spin_lock(&owner->so_lock);
|
||||||
spin_lock(&inode->i_lock);
|
spin_lock(&inode->i_lock);
|
||||||
state = __nfs4_find_state_byowner(inode, owner);
|
state = __nfs4_find_state_byowner(inode, owner);
|
||||||
if (state == NULL && new != NULL) {
|
if (state == NULL && new != NULL) {
|
||||||
state = new;
|
state = new;
|
||||||
/* Note: The reclaim code dictates that we add stateless
|
|
||||||
* and read-only stateids to the end of the list */
|
|
||||||
list_add_tail(&state->open_states, &owner->so_states);
|
|
||||||
state->owner = owner;
|
state->owner = owner;
|
||||||
atomic_inc(&owner->so_count);
|
atomic_inc(&owner->so_count);
|
||||||
list_add(&state->inode_states, &nfsi->open_states);
|
list_add(&state->inode_states, &nfsi->open_states);
|
||||||
state->inode = igrab(inode);
|
state->inode = igrab(inode);
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
|
/* Note: The reclaim code dictates that we add stateless
|
||||||
|
* and read-only stateids to the end of the list */
|
||||||
|
list_add_tail(&state->open_states, &owner->so_states);
|
||||||
|
spin_unlock(&owner->so_lock);
|
||||||
} else {
|
} else {
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
|
spin_unlock(&owner->so_lock);
|
||||||
if (new)
|
if (new)
|
||||||
nfs4_free_open_state(new);
|
nfs4_free_open_state(new);
|
||||||
}
|
}
|
||||||
|
@ -468,12 +472,14 @@ void nfs4_put_open_state(struct nfs4_state *state)
|
||||||
struct inode *inode = state->inode;
|
struct inode *inode = state->inode;
|
||||||
struct nfs4_state_owner *owner = state->owner;
|
struct nfs4_state_owner *owner = state->owner;
|
||||||
|
|
||||||
if (!atomic_dec_and_lock(&state->count, &inode->i_lock))
|
if (!atomic_dec_and_lock(&state->count, &owner->so_lock))
|
||||||
return;
|
return;
|
||||||
|
spin_lock(&inode->i_lock);
|
||||||
if (!list_empty(&state->inode_states))
|
if (!list_empty(&state->inode_states))
|
||||||
list_del(&state->inode_states);
|
list_del(&state->inode_states);
|
||||||
spin_unlock(&inode->i_lock);
|
|
||||||
list_del(&state->open_states);
|
list_del(&state->open_states);
|
||||||
|
spin_unlock(&inode->i_lock);
|
||||||
|
spin_unlock(&owner->so_lock);
|
||||||
iput(inode);
|
iput(inode);
|
||||||
BUG_ON (state->state != 0);
|
BUG_ON (state->state != 0);
|
||||||
nfs4_free_open_state(state);
|
nfs4_free_open_state(state);
|
||||||
|
@ -491,6 +497,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
|
||||||
|
|
||||||
atomic_inc(&owner->so_count);
|
atomic_inc(&owner->so_count);
|
||||||
/* Protect against nfs4_find_state() */
|
/* Protect against nfs4_find_state() */
|
||||||
|
spin_lock(&owner->so_lock);
|
||||||
spin_lock(&inode->i_lock);
|
spin_lock(&inode->i_lock);
|
||||||
if (mode & FMODE_READ)
|
if (mode & FMODE_READ)
|
||||||
state->nreaders--;
|
state->nreaders--;
|
||||||
|
@ -503,6 +510,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode)
|
||||||
list_move_tail(&state->open_states, &owner->so_states);
|
list_move_tail(&state->open_states, &owner->so_states);
|
||||||
}
|
}
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
|
spin_unlock(&owner->so_lock);
|
||||||
newstate = 0;
|
newstate = 0;
|
||||||
if (state->state != 0) {
|
if (state->state != 0) {
|
||||||
if (state->nreaders)
|
if (state->nreaders)
|
||||||
|
@ -899,6 +907,7 @@ static void nfs4_state_mark_reclaim(struct nfs4_client *clp)
|
||||||
list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
|
list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
|
||||||
sp->so_seqid.counter = 0;
|
sp->so_seqid.counter = 0;
|
||||||
sp->so_seqid.flags = 0;
|
sp->so_seqid.flags = 0;
|
||||||
|
spin_lock(&sp->so_lock);
|
||||||
list_for_each_entry(state, &sp->so_states, open_states) {
|
list_for_each_entry(state, &sp->so_states, open_states) {
|
||||||
list_for_each_entry(lock, &state->lock_states, ls_locks) {
|
list_for_each_entry(lock, &state->lock_states, ls_locks) {
|
||||||
lock->ls_seqid.counter = 0;
|
lock->ls_seqid.counter = 0;
|
||||||
|
@ -906,6 +915,7 @@ static void nfs4_state_mark_reclaim(struct nfs4_client *clp)
|
||||||
lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
|
lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
spin_unlock(&sp->so_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue