]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
NFS: always probe for LOCALIO support asynchronously
authorMike Snitzer <snitzer@kernel.org>
Tue, 13 May 2025 16:08:31 +0000 (12:08 -0400)
committerAnna Schumaker <anna.schumaker@oracle.com>
Wed, 28 May 2025 21:17:13 +0000 (17:17 -0400)
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>
fs/nfs/client.c
fs/nfs/flexfilelayout/flexfilelayoutdev.c
fs/nfs/internal.h
fs/nfs/localio.c

index 745f3c42f140f2a3d80192f6255e41bca56889ed..cf35ad3f818adfa182a94d42f305f7a3fdad89bd 100644 (file)
@@ -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;
                }
 
index 4a304cf17c4b07a07b9e25e48af9d83c345d2ac1..656d5c50bbce1cc0f4f6cd1dcb934a1c0433e640 100644 (file)
@@ -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);
index 6655e5f32ec63cb92df69e258f6261f84ffefa76..69c2c10ee658c923eae1447c022811218d5e3194 100644 (file)
@@ -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 *,
index 4ec952f9f47dde1c5277dc4f6df9848a633df011..a4bacd9a50520a02cc15cefd3bf22c40a18edcf3 100644 (file)
@@ -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)