[PATCH] NFSD4: return conflict lock without races
authorAndy Adamson <andros@citi.umich.edu>
Sun, 26 Mar 2006 09:37:26 +0000 (01:37 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sun, 26 Mar 2006 16:56:56 +0000 (08:56 -0800)
Update the NFSv4 server to use the new posix_lock_file_conf() interface.
Remove unnecessary (and race-prone) posix_test_file() calls.

Signed-off-by: Andy Adamson <andros@citi.umich.edu>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/nfsd/nfs4state.c

index c7b87e92f91b4f00c3d439737a2c6764f729abd3..47ec112b266cf7a7c819babd881eb5176b7b4364 100644 (file)
@@ -2750,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 (!posix_test_lock(filp, &file_lock, &conflock)) {
-               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);