Introduce nfs_local_probe_async() for the NFS client to initiate if/when it reconnects with server. For NFSv4 it is a simple matter to call nfs_local_probe_async() from nfs4_do_reclaim (during NFSv4 grace). [NFSv3 also needs to reestablish LOCALIO if/when a client reconnects to server, but the stateless nature of v3 means the implementation is more tricky so its been factored out to the following commit.] Signed-off-by: Mike Snitzer <snitzer@xxxxxxxxxx> --- fs/nfs/internal.h | 2 ++ fs/nfs/localio.c | 15 +++++++++++++++ fs/nfs/nfs4state.c | 1 + include/linux/nfs_fs_sb.h | 1 + 4 files changed, 19 insertions(+) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 57af3ab3adbe..efd42efd9405 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -456,6 +456,7 @@ extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode); /* localio.c */ extern void nfs_local_disable(struct nfs_client *); extern void nfs_local_probe(struct nfs_client *); +extern void nfs_local_probe_async(struct nfs_client *); extern struct nfsd_file *nfs_local_open_fh(struct nfs_client *, const struct cred *, struct nfs_fh *, @@ -473,6 +474,7 @@ extern bool nfs_server_is_local(const struct nfs_client *clp); #else /* CONFIG_NFS_LOCALIO */ static inline void nfs_local_disable(struct nfs_client *clp) {} static inline void nfs_local_probe(struct nfs_client *clp) {} +static inline void nfs_local_probe_async(struct nfs_client *clp) {} static inline struct nfsd_file * nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred, struct nfs_fh *fh, struct nfs_file_localio *nfl, diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c index d10d863aaf23..710e537b3402 100644 --- a/fs/nfs/localio.c +++ b/fs/nfs/localio.c @@ -214,6 +214,21 @@ void nfs_local_probe(struct nfs_client *clp) } EXPORT_SYMBOL_GPL(nfs_local_probe); +static void nfs_local_probe_async_work(struct work_struct *work) +{ + struct nfs_client *clp = + container_of(work, struct nfs_client, cl_local_probe_work); + + nfs_local_probe(clp); +} + +void nfs_local_probe_async(struct nfs_client *clp) +{ + INIT_WORK(&clp->cl_local_probe_work, nfs_local_probe_async_work); + queue_work(nfsiod_workqueue, &clp->cl_local_probe_work); +} +EXPORT_SYMBOL_GPL(nfs_local_probe_async); + static inline struct nfsd_file *nfs_local_file_get(struct nfsd_file *nf) { return nfs_to->nfsd_file_get(nf); diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index dafd61186557..2ebb9ac56b7b 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1957,6 +1957,7 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov } rcu_read_unlock(); nfs4_free_state_owners(&freeme); + nfs_local_probe_async(clp); if (lost_locks) pr_warn("NFS: %s: lost %d locks\n", clp->cl_hostname, lost_locks); diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 239d86ef166c..63d7e0f478d8 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -132,6 +132,7 @@ struct nfs_client { struct timespec64 cl_nfssvc_boot; seqlock_t cl_boot_lock; nfs_uuid_t cl_uuid; + struct work_struct cl_local_probe_work; #endif /* CONFIG_NFS_LOCALIO */ }; -- 2.44.0