diff options
| author | J. Bruce Fields <bfields@citi.umich.edu> | 2009-02-04 17:35:38 -0500 |
|---|---|---|
| committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-02-09 13:19:46 -0500 |
| commit | 9d9b87c1218be78ddecbc85ec3bb91c79c1d56ab (patch) | |
| tree | e33e637f4fa8b4dd1946c6a29e290078d34a388c /fs | |
| parent | eda58a85ec3fc05855a26654d97a2b53f0e715b9 (diff) | |
lockd: fix regression in lockd's handling of blocked locks
If a client requests a blocking lock, is denied, then requests it again,
then here in nlmsvc_lock() we will call vfs_lock_file() without FL_SLEEP
set, because we've already queued a block and don't need the locks code
to do it again.
But that means vfs_lock_file() will return -EAGAIN instead of
FILE_LOCK_DENIED. So we still need to translate that -EAGAIN return
into a nlm_lck_blocked error in this case, and put ourselves back on
lockd's block list.
The bug was introduced by bde74e4bc64415b1 "locks: add special return
value for asynchronous locks".
Thanks to Frank van Maarseveen for the report; his original test
case was essentially
for i in `seq 30`; do flock /nfsmount/foo sleep 10 & done
Tested-by: Frank van Maarseveen <frankvm@frankvm.com>
Reported-by: Frank van Maarseveen <frankvm@frankvm.com>
Cc: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/lockd/svclock.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 6063a8e4b9f3..763b78a6e9de 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
| @@ -427,7 +427,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
| 427 | goto out; | 427 | goto out; |
| 428 | case -EAGAIN: | 428 | case -EAGAIN: |
| 429 | ret = nlm_lck_denied; | 429 | ret = nlm_lck_denied; |
| 430 | goto out; | 430 | break; |
| 431 | case FILE_LOCK_DEFERRED: | 431 | case FILE_LOCK_DEFERRED: |
| 432 | if (wait) | 432 | if (wait) |
| 433 | break; | 433 | break; |
| @@ -443,6 +443,10 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
| 443 | goto out; | 443 | goto out; |
| 444 | } | 444 | } |
| 445 | 445 | ||
| 446 | ret = nlm_lck_denied; | ||
| 447 | if (!wait) | ||
| 448 | goto out; | ||
| 449 | |||
| 446 | ret = nlm_lck_blocked; | 450 | ret = nlm_lck_blocked; |
| 447 | 451 | ||
| 448 | /* Append to list of blocked */ | 452 | /* Append to list of blocked */ |
