summaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c56
1 files changed, 25 insertions, 31 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 1143cfb6454..47ec112b266 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();