NFS: Replace up/down(&state_owner->so_sema) Start the migration to non-semaphore based locks Signed-off-by: Trond Myklebust --- fs/nfs/nfs4_fs.h | 18 +++++++++++++++--- fs/nfs/nfs4proc.c | 22 +++++++++++----------- fs/nfs/nfs4state.c | 12 ++++++------ 3 files changed, 32 insertions(+), 20 deletions(-) Index: linux-2.6.12-rc1/fs/nfs/nfs4proc.c =================================================================== --- linux-2.6.12-rc1.orig/fs/nfs/nfs4proc.c +++ linux-2.6.12-rc1/fs/nfs/nfs4proc.c @@ -307,7 +307,7 @@ static int _nfs4_open_delegation_recall( }; int status = 0; - down(&sp->so_sema); + nfs_lock_state_owner(sp); if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) goto out; if (state->state == 0) @@ -323,7 +323,7 @@ static int _nfs4_open_delegation_recall( clear_bit(NFS_DELEGATED_STATE, &state->flags); } out: - up(&sp->so_sema); + nfs_unlock_state_owner(sp); dput(parent); return status; } @@ -555,7 +555,7 @@ static int _nfs4_open_delegated(struct i dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__); goto out_err; } - down(&sp->so_sema); + nfs_lock_state_owner(sp); state = nfs4_get_open_state(inode, sp); if (state == NULL) goto out_err; @@ -580,7 +580,7 @@ static int _nfs4_open_delegated(struct i set_bit(NFS_DELEGATED_STATE, &state->flags); update_open_stateid(state, &delegation->stateid, open_flags); out_ok: - up(&sp->so_sema); + nfs_unlock_state_owner(sp); nfs4_put_state_owner(sp); up_read(&nfsi->rwsem); up_read(&clp->cl_sem); @@ -591,7 +591,7 @@ out_err: if (sp != NULL) { if (state != NULL) nfs4_put_open_state(state); - up(&sp->so_sema); + nfs_unlock_state_owner(sp); nfs4_put_state_owner(sp); } up_read(&nfsi->rwsem); @@ -656,7 +656,7 @@ static int _nfs4_do_open(struct inode *d } else o_arg.u.attrs = sattr; /* Serialization for the sequence id */ - down(&sp->so_sema); + nfs_lock_state_owner(sp); status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); if (status != 0) @@ -672,7 +672,7 @@ static int _nfs4_do_open(struct inode *d update_open_stateid(state, &o_res.stateid, flags); if (o_res.delegation_type != 0) nfs_inode_set_delegation(inode, cred, &o_res); - up(&sp->so_sema); + nfs_unlock_state_owner(sp); nfs4_put_state_owner(sp); up_read(&clp->cl_sem); *res = state; @@ -681,7 +681,7 @@ out_err: if (sp != NULL) { if (state != NULL) nfs4_put_open_state(state); - up(&sp->so_sema); + nfs_unlock_state_owner(sp); nfs4_put_state_owner(sp); } /* Note: clp->cl_sem must be released before nfs4_put_open_state()! */ @@ -808,7 +808,7 @@ static void nfs4_close_done(struct rpc_t } state->state = calldata->arg.open_flags; nfs4_put_open_state(state); - up(&sp->so_sema); + nfs_unlock_state_owner(sp); nfs4_put_state_owner(sp); up_read(&server->nfs4_state->cl_sem); kfree(calldata); @@ -2809,13 +2809,13 @@ static int _nfs4_do_setlk(struct nfs4_st largs.u.open_lock = &otl; largs.new_lock_owner = 1; arg.u.lock = &largs; - down(&owner->so_sema); + nfs_lock_state_owner(owner); otl.open_seqid = owner->so_seqid; status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); /* increment open_owner seqid on success, and * seqid mutating errors */ nfs4_increment_seqid(status, owner); - up(&owner->so_sema); + nfs_unlock_state_owner(owner); } else { struct nfs_exist_lock el = { .seqid = lsp->ls_seqid, Index: linux-2.6.12-rc1/fs/nfs/nfs4state.c =================================================================== --- linux-2.6.12-rc1.orig/fs/nfs/nfs4state.c +++ linux-2.6.12-rc1/fs/nfs/nfs4state.c @@ -266,7 +266,7 @@ nfs4_alloc_state_owner(void) sp = kmalloc(sizeof(*sp),GFP_KERNEL); if (!sp) return NULL; - init_MUTEX(&sp->so_sema); + iosem_init(&sp->so_iosem); sp->so_seqid = 0; /* arbitrary */ INIT_LIST_HEAD(&sp->so_states); INIT_LIST_HEAD(&sp->so_delegations); @@ -460,7 +460,7 @@ out: /* * Beware! Caller must be holding exactly one - * reference to clp->cl_sem and owner->so_sema! + * reference to clp->cl_sem and the state owner lock! */ void nfs4_put_open_state(struct nfs4_state *state) { @@ -481,7 +481,7 @@ void nfs4_put_open_state(struct nfs4_sta /* * Beware! Caller must be holding no references to clp->cl_sem! - * of owner->so_sema! + * or state owner lock! */ void nfs4_close_state(struct nfs4_state *state, mode_t mode) { @@ -492,7 +492,7 @@ void nfs4_close_state(struct nfs4_state atomic_inc(&owner->so_count); down_read(&clp->cl_sem); - down(&owner->so_sema); + nfs_lock_state_owner(owner); /* Protect against nfs4_find_state() */ spin_lock(&inode->i_lock); if (mode & FMODE_READ) @@ -519,7 +519,7 @@ void nfs4_close_state(struct nfs4_state } out: nfs4_put_open_state(state); - up(&owner->so_sema); + nfs_unlock_state_owner(owner); nfs4_put_state_owner(owner); up_read(&clp->cl_sem); } @@ -702,7 +702,7 @@ nfs4_put_lock_state(struct nfs4_lock_sta } /* -* Called with sp->so_sema and clp->cl_sem held. +* Called with state owner lock and clp->cl_sem held. * * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or * failed with a seqid incrementing error - Index: linux-2.6.12-rc1/fs/nfs/nfs4_fs.h =================================================================== --- linux-2.6.12-rc1.orig/fs/nfs/nfs4_fs.h +++ linux-2.6.12-rc1/fs/nfs/nfs4_fs.h @@ -11,6 +11,8 @@ #ifdef CONFIG_NFS_V4 +#include + struct idmap; /* @@ -97,7 +99,7 @@ struct nfs4_client { * sequences of RPC calls. Their sole purpose is to provide once-only * semantics by allowing the server to identify replayed requests. * - * The ->so_sema is held during all state_owner seqid-mutating operations: + * The ->so_iosem is held during all state_owner seqid-mutating operations: * OPEN, OPEN_DOWNGRADE, and CLOSE. Its purpose is to properly serialize * so_seqid. */ @@ -105,8 +107,8 @@ struct nfs4_state_owner { struct list_head so_list; /* per-clientid list of state_owners */ struct nfs4_client *so_client; u32 so_id; /* 32-bit identifier, unique */ - struct semaphore so_sema; - u32 so_seqid; /* protected by so_sema */ + struct iosem so_iosem; + u32 so_seqid; /* protected by so_iosem */ atomic_t so_count; struct rpc_cred *so_cred; /* Associated cred */ @@ -235,6 +237,16 @@ extern void nfs4_copy_stateid(nfs4_state extern const nfs4_stateid zero_stateid; +static void inline nfs_lock_state_owner(struct nfs4_state_owner *sp) +{ + iosem_lock(&sp->so_iosem); +} + +static void inline nfs_unlock_state_owner(struct nfs4_state_owner *sp) +{ + iosem_unlock(&sp->so_iosem); +} + /* nfs4xdr.c */ extern uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus); extern struct rpc_procinfo nfs4_procedures[];