6.15-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Snitzer snitzer@kernel.org
commit 1ff4716f420b5a6e6ef095b23bb5db76f46be7fc upstream.
It was reported that NFS client mounts of AWS Elastic File System (EFS) volumes is slow, this is because the AWS firewall disallows LOCALIO (because it doesn't consider the use of NFS_LOCALIO_PROGRAM valid), see: https://bugzilla.redhat.com/show_bug.cgi?id=2335129
Switch to performing the LOCALIO probe asynchronously to address the potential for the NFS LOCALIO protocol being disallowed and/or slowed by the remote server's response.
While at it, fix nfs_local_probe_async() to always take/put a reference on the nfs_client that is using the LOCALIO protocol. Also, unexport the nfs_local_probe() symbol and make it private to fs/nfs/localio.c
This change has the side-effect of initially issuing reads, writes and commits over the wire via SUNRPC until the LOCALIO probe completes.
Suggested-by: Jeff Layton jlayton@kernel.org # to always probe async Fixes: 76d4cb6345da ("nfs: probe for LOCALIO when v4 client reconnects to server") Cc: stable@vger.kernel.org # 6.14+ Signed-off-by: Mike Snitzer snitzer@kernel.org Reviewed-by: Jeff Layton jlayton@kernel.org Signed-off-by: Anna Schumaker anna.schumaker@oracle.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/nfs/client.c | 2 +- fs/nfs/flexfilelayout/flexfilelayoutdev.c | 2 +- fs/nfs/internal.h | 1 - fs/nfs/localio.c | 6 ++++-- 4 files changed, 6 insertions(+), 5 deletions(-)
--- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -439,7 +439,7 @@ struct nfs_client *nfs_get_client(const spin_unlock(&nn->nfs_client_lock); new = rpc_ops->init_client(new, cl_init); if (!IS_ERR(new)) - nfs_local_probe(new); + nfs_local_probe_async(new); return new; }
--- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c +++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c @@ -400,7 +400,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_la * keep ds_clp even if DS is local, so that if local IO cannot * proceed somehow, we can fall back to NFS whenever we want. */ - nfs_local_probe(ds->ds_clp); + nfs_local_probe_async(ds->ds_clp); max_payload = nfs_block_size(rpc_max_payload(ds->ds_clp->cl_rpcclient), NULL); --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -455,7 +455,6 @@ extern int nfs_wait_bit_killable(struct
#if IS_ENABLED(CONFIG_NFS_LOCALIO) /* localio.c */ -extern void nfs_local_probe(struct nfs_client *); extern void nfs_local_probe_async(struct nfs_client *); extern void nfs_local_probe_async_work(struct work_struct *); extern struct nfsd_file *nfs_local_open_fh(struct nfs_client *, --- a/fs/nfs/localio.c +++ b/fs/nfs/localio.c @@ -171,7 +171,7 @@ static bool nfs_server_uuid_is_local(str * - called after alloc_client and init_client (so cl_rpcclient exists) * - this function is idempotent, it can be called for old or new clients */ -void nfs_local_probe(struct nfs_client *clp) +static void nfs_local_probe(struct nfs_client *clp) { /* Disallow localio if disabled via sysfs or AUTH_SYS isn't used */ if (!localio_enabled || @@ -191,14 +191,16 @@ void nfs_local_probe(struct nfs_client * nfs_localio_enable_client(clp); nfs_uuid_end(&clp->cl_uuid); } -EXPORT_SYMBOL_GPL(nfs_local_probe);
void nfs_local_probe_async_work(struct work_struct *work) { struct nfs_client *clp = container_of(work, struct nfs_client, cl_local_probe_work);
+ if (!refcount_inc_not_zero(&clp->cl_count)) + return; nfs_local_probe(clp); + nfs_put_client(clp); }
void nfs_local_probe_async(struct nfs_client *clp)