diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 47 |
1 files changed, 21 insertions, 26 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index f6ab762bea99..47ec112b266c 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/nfsd/state.h> | 49 | #include <linux/nfsd/state.h> |
50 | #include <linux/nfsd/xdr4.h> | 50 | #include <linux/nfsd/xdr4.h> |
51 | #include <linux/namei.h> | 51 | #include <linux/namei.h> |
52 | #include <linux/mutex.h> | ||
52 | 53 | ||
53 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 54 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
54 | 55 | ||
@@ -77,11 +78,11 @@ static void nfs4_set_recdir(char *recdir); | |||
77 | 78 | ||
78 | /* Locking: | 79 | /* Locking: |
79 | * | 80 | * |
80 | * client_sema: | 81 | * client_mutex: |
81 | * protects clientid_hashtbl[], clientstr_hashtbl[], | 82 | * protects clientid_hashtbl[], clientstr_hashtbl[], |
82 | * unconfstr_hashtbl[], uncofid_hashtbl[]. | 83 | * unconfstr_hashtbl[], uncofid_hashtbl[]. |
83 | */ | 84 | */ |
84 | static DECLARE_MUTEX(client_sema); | 85 | static DEFINE_MUTEX(client_mutex); |
85 | 86 | ||
86 | static kmem_cache_t *stateowner_slab = NULL; | 87 | static kmem_cache_t *stateowner_slab = NULL; |
87 | static kmem_cache_t *file_slab = NULL; | 88 | static kmem_cache_t *file_slab = NULL; |
@@ -91,13 +92,13 @@ static kmem_cache_t *deleg_slab = NULL; | |||
91 | void | 92 | void |
92 | nfs4_lock_state(void) | 93 | nfs4_lock_state(void) |
93 | { | 94 | { |
94 | down(&client_sema); | 95 | mutex_lock(&client_mutex); |
95 | } | 96 | } |
96 | 97 | ||
97 | void | 98 | void |
98 | nfs4_unlock_state(void) | 99 | nfs4_unlock_state(void) |
99 | { | 100 | { |
100 | up(&client_sema); | 101 | mutex_unlock(&client_mutex); |
101 | } | 102 | } |
102 | 103 | ||
103 | static inline u32 | 104 | static inline u32 |
@@ -2749,37 +2750,31 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2749 | * Note: locks.c uses the BKL to protect the inode's lock list. | 2750 | * Note: locks.c uses the BKL to protect the inode's lock list. |
2750 | */ | 2751 | */ |
2751 | 2752 | ||
2752 | status = posix_lock_file(filp, &file_lock); | 2753 | /* XXX?: Just to divert the locks_release_private at the start of |
2753 | dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status); | 2754 | * locks_copy_lock: */ |
2755 | conflock.fl_ops = NULL; | ||
2756 | conflock.fl_lmops = NULL; | ||
2757 | status = posix_lock_file_conf(filp, &file_lock, &conflock); | ||
2758 | dprintk("NFSD: nfsd4_lock: posix_lock_file_conf status %d\n",status); | ||
2754 | switch (-status) { | 2759 | switch (-status) { |
2755 | case 0: /* success! */ | 2760 | case 0: /* success! */ |
2756 | update_stateid(&lock_stp->st_stateid); | 2761 | update_stateid(&lock_stp->st_stateid); |
2757 | memcpy(&lock->lk_resp_stateid, &lock_stp->st_stateid, | 2762 | memcpy(&lock->lk_resp_stateid, &lock_stp->st_stateid, |
2758 | sizeof(stateid_t)); | 2763 | sizeof(stateid_t)); |
2759 | goto out; | 2764 | break; |
2760 | case (EAGAIN): | 2765 | case (EAGAIN): /* conflock holds conflicting lock */ |
2761 | goto conflicting_lock; | 2766 | status = nfserr_denied; |
2767 | dprintk("NFSD: nfsd4_lock: conflicting lock found!\n"); | ||
2768 | nfs4_set_lock_denied(&conflock, &lock->lk_denied); | ||
2769 | break; | ||
2762 | case (EDEADLK): | 2770 | case (EDEADLK): |
2763 | status = nfserr_deadlock; | 2771 | status = nfserr_deadlock; |
2764 | dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status); | 2772 | break; |
2765 | goto out; | ||
2766 | default: | 2773 | default: |
2767 | status = nfserrno(status); | 2774 | dprintk("NFSD: nfsd4_lock: posix_lock_file_conf() failed! status %d\n",status); |
2768 | dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status); | 2775 | status = nfserr_resource; |
2769 | goto out; | 2776 | break; |
2770 | } | ||
2771 | |||
2772 | conflicting_lock: | ||
2773 | dprintk("NFSD: nfsd4_lock: conflicting lock found!\n"); | ||
2774 | status = nfserr_denied; | ||
2775 | /* XXX There is a race here. Future patch needed to provide | ||
2776 | * an atomic posix_lock_and_test_file | ||
2777 | */ | ||
2778 | if (!posix_test_lock(filp, &file_lock, &conflock)) { | ||
2779 | status = nfserr_serverfault; | ||
2780 | goto out; | ||
2781 | } | 2777 | } |
2782 | nfs4_set_lock_denied(&conflock, &lock->lk_denied); | ||
2783 | out: | 2778 | out: |
2784 | if (status && lock->lk_is_new && lock_sop) | 2779 | if (status && lock->lk_is_new && lock_sop) |
2785 | release_stateowner(lock_sop); | 2780 | release_stateowner(lock_sop); |