summaryrefslogtreecommitdiff
path: root/fs/lockd
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-24 16:21:27 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-07-24 16:21:27 +0200
commit8f9aa2c90530ab92301a82231ae44f3722becd93 (patch)
treefb282e955b0a880b07131a135257fe3ec764e928 /fs/lockd
parent93467b31bec6da512b51544e5e4584f2745e995e (diff)
parent155b42bec9cbb6b8cdc47dd9bd09503a81fbe493 (diff)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/lockd.h8
-rw-r--r--fs/lockd/svc4proc.c19
-rw-r--r--fs/lockd/svcproc.c2
-rw-r--r--fs/lockd/svcsubs.c7
4 files changed, 25 insertions, 11 deletions
diff --git a/fs/lockd/lockd.h b/fs/lockd/lockd.h
index 1db6cb352542..9aa6acb43f9a 100644
--- a/fs/lockd/lockd.h
+++ b/fs/lockd/lockd.h
@@ -52,6 +52,14 @@
*/
#define LOCKD_DFLT_TIMEO 10
+/*
+ * Number of leading bytes of nfs_fh.data that file_hash()
+ * digests when bucketing nlm_files[]. Sized for historical
+ * NFSv2 handles; nfs_fh.data must be initialized at least
+ * this far before lookup, regardless of fh.size.
+ */
+#define LOCKD_FH_HASH_SIZE 32
+
/* error codes new to NLMv4 */
#define nlm4_deadlock cpu_to_be32(NLM_DEADLCK)
#define nlm4_rofs cpu_to_be32(NLM_ROFS)
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 41cab858de57..f3ba2615ae77 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -157,6 +157,9 @@ nlm4svc_lookup_file(struct svc_rqst *rqstp, struct nlm_host *host,
return nlm_lck_denied_nolocks;
lock->fh.size = xdr_lock->fh.len;
memcpy(lock->fh.data, xdr_lock->fh.data, xdr_lock->fh.len);
+ if (xdr_lock->fh.len < LOCKD_FH_HASH_SIZE)
+ memset(lock->fh.data + xdr_lock->fh.len, 0,
+ LOCKD_FH_HASH_SIZE - xdr_lock->fh.len);
lock->oh.len = xdr_lock->oh.len;
lock->oh.data = xdr_lock->oh.data;
@@ -513,12 +516,12 @@ out:
* nlm4_res NLMPROC4_GRANTED(nlm4_testargs) = 5;
*
* Permissible procedure status codes:
- * %NLM4_GRANTED: The requested lock was granted.
- * %NLM4_DENIED: The server could not allocate the resources
- * needed to process the request.
- * %NLM4_DENIED_GRACE_PERIOD: The server has recently restarted and is
- * re-establishing existing locks, and is not
- * yet ready to accept normal service requests.
+ * %NLM4_GRANTED: The granted lock was accepted.
+ * %NLM4_DENIED: The procedure failed, possibly due to
+ * internal resource constraints.
+ * %NLM4_DENIED_GRACE_PERIOD: The client host recently restarted and
+ * its NLM is re-establishing existing locks,
+ * so it is not yet ready to accept callbacks.
*/
static __be32
nlm4svc_proc_granted(struct svc_rqst *rqstp)
@@ -669,6 +672,8 @@ __nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock,
argp->xdrgen.block, &resp->cookie,
argp->xdrgen.reclaim);
+ if (resp->status == nlm__int__deadlock)
+ resp->status = nlm4_deadlock;
nlmsvc_release_lockowner(&argp->lock);
out:
@@ -697,7 +702,7 @@ static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp)
struct nlm4_lockargs_wrapper *argp = rqstp->rq_argp;
struct nlm_host *host;
- host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, true);
+ host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
if (!host)
return rpc_system_err;
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index c0a3487719e2..110e186802b6 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -49,7 +49,7 @@ static inline __be32 cast_status(__be32 status)
status = nlm_lck_denied_nolocks;
break;
default:
- if (be32_to_cpu(status) >= 30000)
+ if (be32_to_cpu(status) > be32_to_cpu(nlm__int__drop_reply))
pr_warn_once("lockd: unhandled internal status %u\n",
be32_to_cpu(status));
break;
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 9da9d6e0b42e..c7945282d479 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -17,7 +17,6 @@
#include <linux/sunrpc/addr.h>
#include <linux/module.h>
#include <linux/mount.h>
-#include <uapi/linux/nfs2.h>
#include "lockd.h"
#include "share.h"
@@ -67,7 +66,7 @@ static inline unsigned int file_hash(struct nfs_fh *f)
{
unsigned int tmp=0;
int i;
- for (i=0; i<NFS2_FHSIZE;i++)
+ for (i = 0; i < LOCKD_FH_HASH_SIZE; i++)
tmp += f->data[i];
return tmp & (FILE_NRHASH - 1);
}
@@ -150,6 +149,8 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
mutex_lock(&file->f_mutex);
nfserr = nlm_do_fopen(rqstp, file, mode);
mutex_unlock(&file->f_mutex);
+ if (nfserr)
+ goto out_unlock;
goto found;
}
nlm_debug_print_fh("creating file for", &lock->fh);
@@ -166,7 +167,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
nfserr = nlm_do_fopen(rqstp, file, mode);
if (nfserr)
- goto out_unlock;
+ goto out_free;
hlist_add_head(&file->f_list, &nlm_files[hash]);