From cc77b1521d06be07c9bb1a4a3e1f775dcaa15093 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 25 Jul 2008 01:48:55 -0700 Subject: lockd: dont return EAGAIN for a permanent error Fix nlm_fopen() to return NLM_FAILED (or NLM_LCK_DENIED_NOLOCKS) instead of NLM_LCK_DENIED. The latter means the lock request failed because of a conflicting lock (i.e. a temporary error), which is wrong in this case. Also fix the client to return ENOLCK instead of EAGAIN if a blocking lock request returns with NLM_LOCK_DENIED. Signed-off-by: Miklos Szeredi Cc: Trond Myklebust Cc: "J. Bruce Fields" Cc: Matthew Wilcox Cc: David Teigland Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/lockd/clntproc.c | 10 +++++++++- fs/nfsd/lockd.c | 13 +++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 1f6dc518505..31668b690e0 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -582,7 +582,15 @@ again: } if (status < 0) goto out_unlock; - status = nlm_stat_to_errno(resp->status); + /* + * EAGAIN doesn't make sense for sleeping locks, and in some + * cases NLM_LCK_DENIED is returned for a permanent error. So + * turn it into an ENOLCK. + */ + if (resp->status == nlm_lck_denied && (fl_flags & FL_SLEEP)) + status = -ENOLCK; + else + status = nlm_stat_to_errno(resp->status); out_unblock: nlmclnt_finish_block(block); out: diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c index 6b6225ac492..15c6faeec77 100644 --- a/fs/nfsd/lockd.c +++ b/fs/nfsd/lockd.c @@ -19,6 +19,13 @@ #define NFSDDBG_FACILITY NFSDDBG_LOCKD +#ifdef CONFIG_LOCKD_V4 +#define nlm_stale_fh nlm4_stale_fh +#define nlm_failed nlm4_failed +#else +#define nlm_stale_fh nlm_lck_denied_nolocks +#define nlm_failed nlm_lck_denied_nolocks +#endif /* * Note: we hold the dentry use count while the file is open. */ @@ -47,12 +54,10 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp) return 0; case nfserr_dropit: return nlm_drop_reply; -#ifdef CONFIG_LOCKD_V4 case nfserr_stale: - return nlm4_stale_fh; -#endif + return nlm_stale_fh; default: - return nlm_lck_denied; + return nlm_failed; } } -- cgit