diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 56 |
1 files changed, 25 insertions, 31 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 1143cfb64549..47ec112b266c 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -49,6 +49,7 @@ #include <linux/nfsd/state.h> #include <linux/nfsd/xdr4.h> #include <linux/namei.h> +#include <linux/mutex.h> #define NFSDDBG_FACILITY NFSDDBG_PROC @@ -77,11 +78,11 @@ static void nfs4_set_recdir(char *recdir); /* Locking: * - * client_sema: + * client_mutex: * protects clientid_hashtbl[], clientstr_hashtbl[], * unconfstr_hashtbl[], uncofid_hashtbl[]. */ -static DECLARE_MUTEX(client_sema); +static DEFINE_MUTEX(client_mutex); static kmem_cache_t *stateowner_slab = NULL; static kmem_cache_t *file_slab = NULL; @@ -91,13 +92,13 @@ static kmem_cache_t *deleg_slab = NULL; void nfs4_lock_state(void) { - down(&client_sema); + mutex_lock(&client_mutex); } void nfs4_unlock_state(void) { - up(&client_sema); + mutex_unlock(&client_mutex); } static inline u32 @@ -2639,7 +2640,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock struct nfs4_stateid *lock_stp; struct file *filp; struct file_lock file_lock; - struct file_lock *conflock; + struct file_lock conflock; int status = 0; unsigned int strhashval; @@ -2749,37 +2750,31 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock * Note: locks.c uses the BKL to protect the inode's lock list. */ - status = posix_lock_file(filp, &file_lock); - dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status); + /* XXX?: Just to divert the locks_release_private at the start of + * locks_copy_lock: */ + conflock.fl_ops = NULL; + conflock.fl_lmops = NULL; + status = posix_lock_file_conf(filp, &file_lock, &conflock); + dprintk("NFSD: nfsd4_lock: posix_lock_file_conf status %d\n",status); switch (-status) { case 0: /* success! */ update_stateid(&lock_stp->st_stateid); memcpy(&lock->lk_resp_stateid, &lock_stp->st_stateid, sizeof(stateid_t)); - goto out; - case (EAGAIN): - goto conflicting_lock; + break; + case (EAGAIN): /* conflock holds conflicting lock */ + status = nfserr_denied; + dprintk("NFSD: nfsd4_lock: conflicting lock found!\n"); + nfs4_set_lock_denied(&conflock, &lock->lk_denied); + break; case (EDEADLK): status = nfserr_deadlock; - dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status); - goto out; + break; default: - status = nfserrno(status); - dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status); - goto out; - } - -conflicting_lock: - dprintk("NFSD: nfsd4_lock: conflicting lock found!\n"); - status = nfserr_denied; - /* XXX There is a race here. Future patch needed to provide - * an atomic posix_lock_and_test_file - */ - if (!(conflock = posix_test_lock(filp, &file_lock))) { - status = nfserr_serverfault; - goto out; + dprintk("NFSD: nfsd4_lock: posix_lock_file_conf() failed! status %d\n",status); + status = nfserr_resource; + break; } - nfs4_set_lock_denied(conflock, &lock->lk_denied); out: if (status && lock->lk_is_new && lock_sop) release_stateowner(lock_sop); @@ -2800,7 +2795,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock struct inode *inode; struct file file; struct file_lock file_lock; - struct file_lock *conflicting_lock; + struct file_lock conflock; int status; if (nfs4_in_grace()) @@ -2864,10 +2859,9 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock file.f_dentry = current_fh->fh_dentry; status = nfs_ok; - conflicting_lock = posix_test_lock(&file, &file_lock); - if (conflicting_lock) { + if (posix_test_lock(&file, &file_lock, &conflock)) { status = nfserr_denied; - nfs4_set_lock_denied(conflicting_lock, &lockt->lt_denied); + nfs4_set_lock_denied(&conflock, &lockt->lt_denied); } out: nfs4_unlock_state(); |