From: Chuck Lever <cel@kernel.org>
To: NeilBrown <neilb@ownmail.net>, Jeff Layton <jlayton@kernel.org>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <dai.ngo@oracle.com>, Tom Talpey <tom@talpey.com>
Cc: <linux-nfs@vger.kernel.org>, Chuck Lever <chuck.lever@oracle.com>
Subject: [PATCH v4 04/14] lockd: Have nlm_fopen() return errno values
Date: Wed, 28 Jan 2026 10:19:25 -0500 [thread overview]
Message-ID: <20260128151935.1646063-5-cel@kernel.org> (raw)
In-Reply-To: <20260128151935.1646063-1-cel@kernel.org>
From: Chuck Lever <chuck.lever@oracle.com>
The nlm_fopen() function is part of the API between nfsd and lockd.
Currently its return value is an on-the-wire NLM status code. But
that forces NFSD to include NLM wire protocol definitions despite
having no other dependency on the NLM wire protocol.
In addition, a CONFIG_LOCKD_V4 Kconfig symbol appears in the middle
of NFSD source code.
Refactor: Let's not use on-the-wire values as part of a high-level
API between two Linux kernel modules. That's what we have errno for,
right?
And, instead of simply moving the CONFIG_LOCKD_V4 check, we can get
rid of it entirely and let the decision of what actual NLM status
code goes on the wire to be left up to NLM version-specific code.
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/lockd/svc4proc.c | 18 ++++++++++---
fs/lockd/svcproc.c | 14 ++++++++++-
fs/lockd/svcsubs.c | 27 +++++++++++++++-----
fs/nfsd/lockd.c | 50 +++++++++++++++++++++----------------
include/linux/lockd/bind.h | 8 +++---
include/linux/lockd/lockd.h | 2 ++
6 files changed, 82 insertions(+), 37 deletions(-)
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 55b6dcc56db1..4ceb27cc72e4 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -73,9 +73,21 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
no_locks:
nlmsvc_release_host(host);
- if (error)
- return error;
- return nlm_lck_denied_nolocks;
+ switch (error) {
+ case nlm_granted:
+ return nlm_lck_denied_nolocks;
+ case nlm__int__stale_fh:
+ return nlm4_stale_fh;
+ case nlm__int__failed:
+ return nlm4_failed;
+ default:
+ if (be32_to_cpu(error) >= 30000) {
+ pr_warn_once("lockd: unhandled internal status %u\n",
+ be32_to_cpu(error));
+ return nlm4_failed;
+ }
+ return error;
+ }
}
/*
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 27ed71935e45..272c8f36ed2a 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -39,8 +39,20 @@ static inline __be32 cast_status(__be32 status)
#else
static inline __be32 cast_status(__be32 status)
{
- if (status == nlm__int__deadlock)
+ switch (status) {
+ case nlm__int__deadlock:
status = nlm_lck_denied;
+ break;
+ case nlm__int__stale_fh:
+ case nlm__int__failed:
+ status = nlm_lck_denied_nolocks;
+ break;
+ default:
+ if (be32_to_cpu(status) >= 30000)
+ pr_warn_once("lockd: unhandled internal status %u\n",
+ be32_to_cpu(status));
+ break;
+ }
return status;
}
#endif
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 9103896164f6..4186e53190ac 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -87,14 +87,29 @@ static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
struct nlm_file *file, int mode)
{
struct file **fp = &file->f_file[mode];
- __be32 nfserr;
+ __be32 nlmerr = nlm_granted;
+ int error;
if (*fp)
- return 0;
- nfserr = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, mode);
- if (nfserr)
- dprintk("lockd: open failed (error %d)\n", nfserr);
- return nfserr;
+ return nlmerr;
+
+ error = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, mode);
+ if (error) {
+ dprintk("lockd: open failed (errno %d)\n", error);
+ switch (error) {
+ case -EWOULDBLOCK:
+ nlmerr = nlm__int__drop_reply;
+ break;
+ case -ESTALE:
+ nlmerr = nlm__int__stale_fh;
+ break;
+ default:
+ nlmerr = nlm__int__failed;
+ break;
+ }
+ }
+
+ return nlmerr;
}
/*
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 8c230ccd6645..6fe1325815e0 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -14,19 +14,20 @@
#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.
+/**
+ * nlm_fopen - Open an NFSD file
+ * @rqstp: NLM RPC procedure execution context
+ * @f: NFS file handle to be opened
+ * @filp: OUT: an opened struct file
+ * @flags: the POSIX open flags to use
+ *
+ * nlm_fopen() holds the dentry reference until nlm_fclose() releases it.
+ *
+ * Returns zero on success or a negative errno value if the file
+ * cannot be opened.
*/
-static __be32
-nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp,
- int mode)
+static int nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f,
+ struct file **filp, int flags)
{
__be32 nfserr;
int access;
@@ -47,18 +48,17 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp,
* if NFSEXP_NOAUTHNLM is set. Some older clients use AUTH_NULL
* for NLM requests.
*/
- access = (mode == O_WRONLY) ? NFSD_MAY_WRITE : NFSD_MAY_READ;
+ access = (flags == O_WRONLY) ? NFSD_MAY_WRITE : NFSD_MAY_READ;
access |= NFSD_MAY_NLM | NFSD_MAY_OWNER_OVERRIDE | NFSD_MAY_BYPASS_GSS;
nfserr = nfsd_open(rqstp, &fh, S_IFREG, access, filp);
fh_put(&fh);
- /* We return nlm error codes as nlm doesn't know
- * about nfsd, but nfsd does know about nlm..
- */
+
switch (nfserr) {
case nfs_ok:
- return 0;
+ break;
case nfserr_jukebox:
- /* this error can indicate a presence of a conflicting
+ /*
+ * This error can indicate a presence of a conflicting
* delegation to an NLM lock request. Options are:
* (1) For now, drop this request and make the client
* retry. When delegation is returned, client's lock retry
@@ -66,19 +66,25 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp,
* (2) NLM4_DENIED as per "spec" signals to the client
* that the lock is unavailable now but client can retry.
* Linux client implementation does not. It treats
- * NLM4_DENIED same as NLM4_FAILED and errors the request.
+ * NLM4_DENIED same as NLM4_FAILED and fails the request.
* (3) For the future, treat this as blocked lock and try
* to callback when the delegation is returned but might
* not have a proper lock request to block on.
*/
- return nlm__int__drop_reply;
+ return -EWOULDBLOCK;
case nfserr_stale:
- return nlm_stale_fh;
+ return -ESTALE;
default:
- return nlm_failed;
+ return -ENOLCK;
}
+
+ return 0;
}
+/**
+ * nlm_fclose - Close an NFSD file
+ * @filp: a struct file that was opened by nlm_fopen()
+ */
static void
nlm_fclose(struct file *filp)
{
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index c53c81242e72..2f5dd9e943ee 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -26,11 +26,9 @@ struct rpc_clnt;
* This is the set of functions for lockd->nfsd communication
*/
struct nlmsvc_binding {
- __be32 (*fopen)(struct svc_rqst *,
- struct nfs_fh *,
- struct file **,
- int mode);
- void (*fclose)(struct file *);
+ int (*fopen)(struct svc_rqst *rqstp, struct nfs_fh *f,
+ struct file **filp, int flags);
+ void (*fclose)(struct file *filp);
};
extern const struct nlmsvc_binding *nlmsvc_ops;
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 793691912137..195e6ce28f6e 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -44,6 +44,8 @@
*/
#define nlm__int__drop_reply cpu_to_be32(30000)
#define nlm__int__deadlock cpu_to_be32(30001)
+#define nlm__int__stale_fh cpu_to_be32(30002)
+#define nlm__int__failed cpu_to_be32(30003)
/*
* Lockd host handle (used both by the client and server personality).
--
2.52.0
next prev parent reply other threads:[~2026-01-28 15:19 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-28 15:19 [PATCH v4 00/14] Subject: Clarify module API boundaries Chuck Lever
2026-01-28 15:19 ` [PATCH v4 01/14] lockd: Simplify cast_status() in svcproc.c Chuck Lever
2026-01-28 15:19 ` [PATCH v4 02/14] lockd: Relocate and rename nlm_drop_reply Chuck Lever
2026-01-28 15:19 ` [PATCH v4 03/14] lockd: Introduce nlm__int__deadlock Chuck Lever
2026-01-28 15:19 ` Chuck Lever [this message]
2026-01-28 15:19 ` [PATCH v4 05/14] lockd: Relocate nlmsvc_unlock API declarations Chuck Lever
2026-01-28 15:19 ` [PATCH v4 06/14] NFS: Use nlmclnt_shutdown_rpc_clnt() to safely shut down NLM Chuck Lever
2026-01-28 15:19 ` [PATCH v4 07/14] lockd: Move xdr4.h from include/linux/lockd/ to fs/lockd/ Chuck Lever
2026-01-28 15:19 ` [PATCH v4 08/14] lockd: Move share.h " Chuck Lever
2026-01-28 15:19 ` [PATCH v4 09/14] lockd: Relocate include/linux/lockd/lockd.h Chuck Lever
2026-01-28 15:19 ` [PATCH v4 10/14] lockd: Remove lockd/debug.h Chuck Lever
2026-01-28 15:19 ` [PATCH v4 11/14] lockd: Move xdr.h from include/linux/lockd/ to fs/lockd/ Chuck Lever
2026-01-29 7:06 ` kernel test robot
2026-01-28 15:19 ` [PATCH v4 12/14] lockd: Make linux/lockd/nlm.h an internal header Chuck Lever
2026-01-28 15:19 ` [PATCH v4 13/14] lockd: Move nlm4svc_set_file_lock_range() Chuck Lever
2026-01-28 15:19 ` [PATCH v4 14/14] lockd: Relocate svc_version definitions to XDR layer Chuck Lever
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260128151935.1646063-5-cel@kernel.org \
--to=cel@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=dai.ngo@oracle.com \
--cc=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neilb@ownmail.net \
--cc=okorniev@redhat.com \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox