Commit eb76b3fd authored by Andy Adamson's avatar Andy Adamson Committed by Linus Torvalds

[PATCH] NFSD4: return conflict lock without races

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: default avatarAndy Adamson <andros@citi.umich.edu>
Signed-off-by: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
Cc: Neil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5842add2
...@@ -2750,37 +2750,31 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock ...@@ -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. * Note: locks.c uses the BKL to protect the inode's lock list.
*/ */
status = posix_lock_file(filp, &file_lock); /* XXX?: Just to divert the locks_release_private at the start of
dprintk("NFSD: nfsd4_lock: posix_lock_file status %d\n",status); * 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) { switch (-status) {
case 0: /* success! */ case 0: /* success! */
update_stateid(&lock_stp->st_stateid); update_stateid(&lock_stp->st_stateid);
memcpy(&lock->lk_resp_stateid, &lock_stp->st_stateid, memcpy(&lock->lk_resp_stateid, &lock_stp->st_stateid,
sizeof(stateid_t)); sizeof(stateid_t));
goto out; break;
case (EAGAIN): case (EAGAIN): /* conflock holds conflicting lock */
goto conflicting_lock; status = nfserr_denied;
dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
nfs4_set_lock_denied(&conflock, &lock->lk_denied);
break;
case (EDEADLK): case (EDEADLK):
status = nfserr_deadlock; status = nfserr_deadlock;
dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status); break;
goto out;
default: default:
status = nfserrno(status); dprintk("NFSD: nfsd4_lock: posix_lock_file_conf() failed! status %d\n",status);
dprintk("NFSD: nfsd4_lock: posix_lock_file() failed! status %d\n",status); status = nfserr_resource;
goto out; break;
}
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;
} }
nfs4_set_lock_denied(&conflock, &lock->lk_denied);
out: out:
if (status && lock->lk_is_new && lock_sop) if (status && lock->lk_is_new && lock_sop)
release_stateowner(lock_sop); release_stateowner(lock_sop);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment