From: Jeff Layton <jlayton@kernel.org>
To: Chuck Lever <cel@kernel.org>, NeilBrown <neil@brown.name>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <Dai.Ngo@oracle.com>, Tom Talpey <tom@talpey.com>
Cc: Scott Mayhew <smayhew@redhat.com>,
linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org,
Jeff Layton <jlayton@kernel.org>
Subject: [PATCH 1/2] nfsd: remove the nfsdcltrack usermodehelper tracking backend
Date: Wed, 23 Sep 2026 12:14:21 -0400 [thread overview]
Message-ID: <20260923-nfsd-legacy-v1-1-8490c0c12ea5@kernel.org> (raw)
In-Reply-To: <20260923-nfsd-legacy-v1-0-8490c0c12ea5@kernel.org>
The usermodehelper upcall to /sbin/nfsdcltrack was deprecated with the
rest of the legacy client tracking methods. It never worked in
containers and nfsdcld has superseded it. Remove the backend and the
cltrack_prog and cltrack_legacy_disable module parameters.
Assisted-by: LLM
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
fs/nfsd/nfs4recover.c | 347 +-------------------------------------------------
1 file changed, 1 insertion(+), 346 deletions(-)
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 5e7788e3fb79..ecf8ced8074a 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -1611,358 +1611,13 @@ static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2 = {
};
#ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING
-/* upcall via usermodehelper */
-static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack";
-module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog),
- S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program");
-
-static bool cltrack_legacy_disable;
-module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(cltrack_legacy_disable,
- "Disable legacy recoverydir conversion. Default: false");
-
-#define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR="
-#define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR="
-#define HAS_SESSION_ENV_PREFIX "NFSDCLTRACK_CLIENT_HAS_SESSION="
-#define GRACE_START_ENV_PREFIX "NFSDCLTRACK_GRACE_START="
-
-static char *
-nfsd4_cltrack_legacy_topdir(void)
-{
- int copied;
- size_t len;
- char *result;
-
- if (cltrack_legacy_disable)
- return NULL;
-
- len = strlen(LEGACY_TOPDIR_ENV_PREFIX) +
- strlen(nfs4_recoverydir()) + 1;
-
- result = kmalloc(len, GFP_KERNEL);
- if (!result)
- return result;
-
- copied = snprintf(result, len, LEGACY_TOPDIR_ENV_PREFIX "%s",
- nfs4_recoverydir());
- if (copied >= len) {
- /* just return nothing if output was truncated */
- kfree(result);
- return NULL;
- }
-
- return result;
-}
-
-static char *
-nfsd4_cltrack_legacy_recdir(const struct xdr_netobj *name)
-{
- int copied;
- size_t len;
- char *result;
-
- if (cltrack_legacy_disable)
- return NULL;
-
- /* +1 is for '/' between "topdir" and "recdir" */
- len = strlen(LEGACY_RECDIR_ENV_PREFIX) +
- strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN;
-
- result = kmalloc(len, GFP_KERNEL);
- if (!result)
- return result;
-
- copied = snprintf(result, len, LEGACY_RECDIR_ENV_PREFIX "%s/",
- nfs4_recoverydir());
- if (copied > (len - HEXDIR_LEN)) {
- /* just return nothing if output will be truncated */
- kfree(result);
- return NULL;
- }
-
- nfs4_make_rec_clidname(result + copied, name);
-
- return result;
-}
-
-static char *
-nfsd4_cltrack_client_has_session(struct nfs4_client *clp)
-{
- int copied;
- size_t len;
- char *result;
-
- /* prefix + Y/N character + terminating NULL */
- len = strlen(HAS_SESSION_ENV_PREFIX) + 1 + 1;
-
- result = kmalloc(len, GFP_KERNEL);
- if (!result)
- return result;
-
- copied = snprintf(result, len, HAS_SESSION_ENV_PREFIX "%c",
- clp->cl_minorversion ? 'Y' : 'N');
- if (copied >= len) {
- /* just return nothing if output was truncated */
- kfree(result);
- return NULL;
- }
-
- return result;
-}
-
-static char *
-nfsd4_cltrack_grace_start(time64_t grace_start)
-{
- int copied;
- size_t len;
- char *result;
-
- /* prefix + max width of int64_t string + terminating NULL */
- len = strlen(GRACE_START_ENV_PREFIX) + 22 + 1;
-
- result = kmalloc(len, GFP_KERNEL);
- if (!result)
- return result;
-
- copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%lld",
- grace_start);
- if (copied >= len) {
- /* just return nothing if output was truncated */
- kfree(result);
- return NULL;
- }
-
- return result;
-}
-
-static int
-nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
-{
- char *envp[3];
- char *argv[4];
- int ret;
-
- if (unlikely(!cltrack_prog[0])) {
- dprintk("%s: cltrack_prog is disabled\n", __func__);
- return -EACCES;
- }
-
- dprintk("%s: cmd: %s\n", __func__, cmd);
- dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)");
- dprintk("%s: env0: %s\n", __func__, env0 ? env0 : "(null)");
- dprintk("%s: env1: %s\n", __func__, env1 ? env1 : "(null)");
-
- envp[0] = env0;
- envp[1] = env1;
- envp[2] = NULL;
-
- argv[0] = (char *)cltrack_prog;
- argv[1] = cmd;
- argv[2] = arg;
- argv[3] = NULL;
-
- ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
- /*
- * Disable the upcall mechanism if we're getting an ENOENT or EACCES
- * error. The admin can re-enable it on the fly by using sysfs
- * once the problem has been fixed.
- */
- if (ret == -ENOENT || ret == -EACCES) {
- dprintk("NFSD: %s was not found or isn't executable (%d). "
- "Setting cltrack_prog to blank string!",
- cltrack_prog, ret);
- cltrack_prog[0] = '\0';
- }
- dprintk("%s: %s return value: %d\n", __func__, cltrack_prog, ret);
-
- return ret;
-}
-
-static char *
-bin_to_hex_dup(const unsigned char *src, int srclen)
-{
- char *buf;
-
- /* +1 for terminating NULL */
- buf = kzalloc((srclen * 2) + 1, GFP_KERNEL);
- if (!buf)
- return buf;
-
- bin2hex(buf, src, srclen);
- return buf;
-}
-
-static int
-nfsd4_umh_cltrack_init(struct net *net)
-{
- int ret;
- struct nfsd_net *nn = net_generic(net, nfsd_net_id);
- char *grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
-
- /* XXX: The usermode helper s not working in container yet. */
- if (net != &init_net) {
- pr_warn("NFSD: attempt to initialize umh client tracking in a container ignored.\n");
- kfree(grace_start);
- return -EINVAL;
- }
-
- ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL);
- kfree(grace_start);
- if (!ret)
- pr_info("NFSD: Using UMH upcall client tracking operations.\n");
- return ret;
-}
-
-static void
-nfsd4_cltrack_upcall_lock(struct nfs4_client *clp)
-{
- wait_on_bit_lock(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK,
- TASK_UNINTERRUPTIBLE);
-}
-
-static void
-nfsd4_cltrack_upcall_unlock(struct nfs4_client *clp)
-{
- clear_and_wake_up_bit(NFSD4_CLIENT_UPCALL_LOCK, &clp->cl_flags);
-}
-
-static void
-nfsd4_umh_cltrack_create(struct nfs4_client *clp)
-{
- char *hexid, *has_session, *grace_start;
- struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
-
- /*
- * With v4.0 clients, there's little difference in outcome between a
- * create and check operation, and we can end up calling into this
- * function multiple times per client (once for each openowner). So,
- * for v4.0 clients skip upcalling once the client has been recorded
- * on stable storage.
- *
- * For v4.1+ clients, the outcome of the two operations is different,
- * so we must ensure that we upcall for the create operation. v4.1+
- * clients call this on RECLAIM_COMPLETE though, so we should only end
- * up doing a single create upcall per client.
- */
- if (clp->cl_minorversion == 0 &&
- test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
- return;
-
- hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
- if (!hexid) {
- dprintk("%s: can't allocate memory for upcall!\n", __func__);
- return;
- }
-
- has_session = nfsd4_cltrack_client_has_session(clp);
- grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
-
- nfsd4_cltrack_upcall_lock(clp);
- if (!nfsd4_umh_cltrack_upcall("create", hexid, has_session, grace_start))
- set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
- nfsd4_cltrack_upcall_unlock(clp);
-
- kfree(has_session);
- kfree(grace_start);
- kfree(hexid);
-}
-
-static void
-nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
-{
- char *hexid;
-
- if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
- return;
-
- hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
- if (!hexid) {
- dprintk("%s: can't allocate memory for upcall!\n", __func__);
- return;
- }
-
- nfsd4_cltrack_upcall_lock(clp);
- if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags) &&
- nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL) == 0)
- clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
- nfsd4_cltrack_upcall_unlock(clp);
-
- kfree(hexid);
-}
-
-static int
-nfsd4_umh_cltrack_check(struct nfs4_client *clp)
-{
- int ret;
- char *hexid, *has_session, *legacy;
-
- if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
- return 0;
-
- hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
- if (!hexid) {
- dprintk("%s: can't allocate memory for upcall!\n", __func__);
- return -ENOMEM;
- }
-
- has_session = nfsd4_cltrack_client_has_session(clp);
- legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name);
-
- nfsd4_cltrack_upcall_lock(clp);
- if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) {
- ret = 0;
- } else {
- ret = nfsd4_umh_cltrack_upcall("check", hexid, has_session, legacy);
- if (ret == 0)
- set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
- }
- nfsd4_cltrack_upcall_unlock(clp);
- kfree(has_session);
- kfree(legacy);
- kfree(hexid);
-
- return ret;
-}
-
-static void
-nfsd4_umh_cltrack_grace_done(struct nfsd_net *nn)
-{
- char *legacy;
- char timestr[22]; /* FIXME: better way to determine max size? */
-
- sprintf(timestr, "%lld", nn->boot_time);
- legacy = nfsd4_cltrack_legacy_topdir();
- nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy, NULL);
- kfree(legacy);
-}
-
-static const struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = {
- .init = nfsd4_umh_cltrack_init,
- .exit = NULL,
- .create = nfsd4_umh_cltrack_create,
- .remove = nfsd4_umh_cltrack_remove,
- .check = nfsd4_umh_cltrack_check,
- .grace_done = nfsd4_umh_cltrack_grace_done,
- .version = 1,
- .msglen = 0,
-};
-
static inline int check_for_legacy_methods(int status, struct net *net)
{
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
struct path path;
/*
- * Next, try the UMH upcall.
- */
- nn->client_tracking_ops = &nfsd4_umh_tracking_ops;
- status = nn->client_tracking_ops->init(net);
- if (!status)
- return status;
-
- /*
- * Finally, See if the recoverydir exists and is a directory.
+ * See if the recoverydir exists and is a directory.
* If it is, then use the legacy ops.
*/
nn->client_tracking_ops = &nfsd4_legacy_tracking_ops;
--
2.55.0
next prev parent reply other threads:[~2026-09-23 16:14 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-23 16:14 [PATCH 0/2] nfsd: remove legacy tracking methods Jeff Layton
2026-09-23 16:14 ` Jeff Layton [this message]
2026-09-23 16:14 ` [PATCH 2/2] nfsd: remove CONFIG_NFSD_LEGACY_CLIENT_TRACKING Jeff Layton
2026-09-23 18:25 ` [PATCH 0/2] nfsd: remove legacy tracking methods 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=20260923-nfsd-legacy-v1-1-8490c0c12ea5@kernel.org \
--to=jlayton@kernel.org \
--cc=Dai.Ngo@oracle.com \
--cc=cel@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neil@brown.name \
--cc=okorniev@redhat.com \
--cc=smayhew@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
all inboxes | Powered by JetHome®