mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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


  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®