Commit 1ff4716f authored by Mike Snitzer's avatar Mike Snitzer Committed by Anna Schumaker
Browse files

NFS: always probe for LOCALIO support asynchronously

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: 76d4cb63 ("nfs: probe for LOCALIO when v4 client reconnects to server")
Cc: stable@vger.kernel.org # 6.14+
Signed-off-by: default avatarMike Snitzer <snitzer@kernel.org>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarAnna Schumaker <anna.schumaker@oracle.com>
parent 04a15263
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -439,7 +439,7 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
			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;
		}

+1 −1
Original line number Diff line number Diff line
@@ -400,7 +400,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg,
		 * 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);
+0 −1
Original line number Diff line number Diff line
@@ -455,7 +455,6 @@ extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode);

#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 *,
+4 −2
Original line number Diff line number Diff line
@@ -171,7 +171,7 @@ static bool nfs_server_uuid_is_local(struct nfs_client *clp)
 * - 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 *clp)
		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)