From: Christoph Hellwig <hch@lst.de>
To: Trond Myklebust <trondmy@kernel.org>, Anna Schumaker <anna@kernel.org>
Cc: linux-nfs@vger.kernel.org
Subject: [PATCH 2/2] NFS: add a clientid mount option
Date: Mon, 14 Jul 2025 08:30:46 +0200 [thread overview]
Message-ID: <20250714063053.1487761-3-hch@lst.de> (raw)
In-Reply-To: <20250714063053.1487761-1-hch@lst.de>
Add a mount option to set a clientid, similarly to how it can be
configured through the per-netfs sysfs file. This allows for easy
testing of behavior that relies on the client ID likes locks or
delegations with having to resort to separate VMs or containers.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
fs/nfs/client.c | 12 ++++++++++++
fs/nfs/fs_context.c | 12 ++++++++++++
fs/nfs/internal.h | 2 ++
fs/nfs/nfs4client.c | 1 +
fs/nfs/nfs4proc.c | 7 ++++++-
include/linux/nfs_fs_sb.h | 1 +
6 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 47258dc3af70..1a55debab6e5 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -181,6 +181,12 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
clp->cl_nconnect = cl_init->nconnect;
clp->cl_max_connect = cl_init->max_connect ? cl_init->max_connect : 1;
clp->cl_net = get_net_track(cl_init->net, &clp->cl_ns_tracker, GFP_KERNEL);
+ if (cl_init->clientid) {
+ err = -ENOMEM;
+ clp->clientid = kstrdup(cl_init->clientid, GFP_KERNEL);
+ if (!clp->clientid)
+ goto error_free_host;
+ }
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
seqlock_init(&clp->cl_boot_lock);
@@ -193,6 +199,8 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
clp->cl_xprtsec = cl_init->xprtsec;
return clp;
+error_free_host:
+ kfree(clp->cl_hostname);
error_cleanup:
put_nfs_version(clp->cl_nfs_mod);
error_dealloc:
@@ -254,6 +262,7 @@ void nfs_free_client(struct nfs_client *clp)
put_nfs_version(clp->cl_nfs_mod);
kfree(clp->cl_hostname);
kfree(clp->cl_acceptor);
+ kfree(clp->clientid);
kfree_rcu(clp, rcu);
}
EXPORT_SYMBOL_GPL(nfs_free_client);
@@ -339,6 +348,9 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
if (clp->cl_xprtsec.policy != data->xprtsec.policy)
continue;
+ if (data->clientid && data->clientid != clp->clientid)
+ continue;
+
refcount_inc(&clp->cl_count);
return clp;
}
diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
index 9e94d18448ff..fe9ecdc8db3c 100644
--- a/fs/nfs/fs_context.c
+++ b/fs/nfs/fs_context.c
@@ -98,6 +98,7 @@ enum nfs_param {
Opt_xprtsec,
Opt_cert_serial,
Opt_privkey_serial,
+ Opt_clientid,
};
enum {
@@ -225,6 +226,7 @@ static const struct fs_parameter_spec nfs_fs_parameters[] = {
fsparam_string("xprtsec", Opt_xprtsec),
fsparam_s32("cert_serial", Opt_cert_serial),
fsparam_s32("privkey_serial", Opt_privkey_serial),
+ fsparam_string("clientid", Opt_clientid),
{}
};
@@ -1031,6 +1033,14 @@ static int nfs_fs_context_parse_param(struct fs_context *fc,
goto out_invalid_value;
}
break;
+ case Opt_clientid:
+ if (!param->string || strlen(param->string) == 0 ||
+ strlen(param->string) > NFS4_CLIENT_ID_UNIQ_LEN - 1)
+ goto out_of_bounds;
+ kfree(ctx->clientid);
+ ctx->clientid = param->string;
+ param->string = NULL;
+ break;
/*
* Special options
@@ -1650,6 +1660,7 @@ static int nfs_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
ctx->nfs_server.hostname = NULL;
ctx->fscache_uniq = NULL;
ctx->clone_data.fattr = NULL;
+ ctx->clientid = NULL;
fc->fs_private = ctx;
return 0;
}
@@ -1670,6 +1681,7 @@ static void nfs_fs_context_free(struct fs_context *fc)
kfree(ctx->fscache_uniq);
nfs_free_fhandle(ctx->mntfh);
nfs_free_fattr(ctx->clone_data.fattr);
+ kfree(ctx->clientid);
kfree(ctx);
}
}
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 69c2c10ee658..1a392676d27c 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -86,6 +86,7 @@ struct nfs_client_initdata {
struct xprtsec_parms xprtsec;
unsigned long connect_timeout;
unsigned long reconnect_timeout;
+ const char *clientid;
};
/*
@@ -115,6 +116,7 @@ struct nfs_fs_context {
unsigned short mountfamily;
bool has_sec_mnt_opts;
int lock_status;
+ char *clientid;
struct {
union {
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 2e623da1a787..3ab5cc985224 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -1153,6 +1153,7 @@ static int nfs4_init_server(struct nfs_server *server, struct fs_context *fc)
.xprtsec = ctx->xprtsec,
.nconnect = ctx->nfs_server.nconnect,
.max_connect = ctx->nfs_server.max_connect,
+ .clientid = ctx->clientid,
};
int error;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ef2077e185b6..ad53bc4ef50c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6487,6 +6487,11 @@ nfs4_get_uniquifier(struct nfs_client *clp, char *buf, size_t buflen)
buf[0] = '\0';
+ if (clp->clientid) {
+ strscpy(buf, clp->clientid, buflen);
+ goto out;
+ }
+
if (nn_clp) {
rcu_read_lock();
id = rcu_dereference(nn_clp->identifier);
@@ -6497,7 +6502,7 @@ nfs4_get_uniquifier(struct nfs_client *clp, char *buf, size_t buflen)
if (nfs4_client_id_uniquifier[0] != '\0' && buf[0] == '\0')
strscpy(buf, nfs4_client_id_uniquifier, buflen);
-
+out:
return strlen(buf);
}
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index d2d36711a119..73bed04529a7 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -128,6 +128,7 @@ struct nfs_client {
netns_tracker cl_ns_tracker;
struct list_head pending_cb_stateids;
struct rcu_head rcu;
+ const char *clientid;
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
struct timespec64 cl_nfssvc_boot;
--
2.47.2
next prev parent reply other threads:[~2025-07-14 6:31 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-14 6:30 add a clientid mount option Christoph Hellwig
2025-07-14 6:30 ` [PATCH 1/2] NFS: pass struct nfs_client_initdata to nfs4_set_client Christoph Hellwig
2025-07-14 15:51 ` Trond Myklebust
2025-07-14 6:30 ` Christoph Hellwig [this message]
2025-07-14 13:24 ` [PATCH 2/2] NFS: add a clientid mount option Chuck Lever
2025-07-14 13:31 ` Christoph Hellwig
2025-07-14 14:47 ` Chuck Lever
2025-07-14 15:49 ` Trond Myklebust
2025-07-15 5:31 ` Christoph Hellwig
2025-07-15 5:30 ` Christoph Hellwig
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=20250714063053.1487761-3-hch@lst.de \
--to=hch@lst.de \
--cc=anna@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=trondmy@kernel.org \
/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