diff options
| author | Trond Myklebust <trond.myklebust@hammerspace.com> | 2020-02-26 19:16:09 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-10-10 21:46:44 +0200 |
| commit | f90821f6672728535153146794bd120424834afd (patch) | |
| tree | 01c3a07580e9a9903bfe95b08a806b1a0b3cc42c | |
| parent | e2d4fc53e9f72458c01253aa7de447254d0254fe (diff) | |
| download | linux-f90821f6672728535153146794bd120424834afd.tar.gz linux-f90821f6672728535153146794bd120424834afd.tar.bz2 linux-f90821f6672728535153146794bd120424834afd.zip | |
NFS: Add a helper nfs_client_for_each_server()
[ Upstream commit 3c9e502b59fbd243cfac7cc6c875e432d285102a ]
Add a helper nfs_client_for_each_server() to iterate through all the
filesystems that are attached to a struct nfs_client, and apply
a function to all the active ones.
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Stable-dep-of: ed1cc05aa1f7 ("NFSv4: Fix a nfs4_state_manager() race")
Signed-off-by: Sasha Levin <sashal@kernel.org>
| -rw-r--r-- | fs/nfs/internal.h | 4 | ||||
| -rw-r--r-- | fs/nfs/super.c | 35 |
2 files changed, 38 insertions, 1 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index a4dc182e8989..fcd35c98a937 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -411,7 +411,9 @@ extern int __init register_nfs_fs(void); extern void __exit unregister_nfs_fs(void); extern bool nfs_sb_active(struct super_block *sb); extern void nfs_sb_deactive(struct super_block *sb); - +extern int nfs_client_for_each_server(struct nfs_client *clp, + int (*fn)(struct nfs_server *, void *), + void *data); /* io.c */ extern void nfs_start_io_read(struct inode *inode); extern void nfs_end_io_read(struct inode *inode); diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ecc7277b3eda..1d3b681a6b27 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -436,6 +436,41 @@ void nfs_sb_deactive(struct super_block *sb) } EXPORT_SYMBOL_GPL(nfs_sb_deactive); +static int __nfs_list_for_each_server(struct list_head *head, + int (*fn)(struct nfs_server *, void *), + void *data) +{ + struct nfs_server *server, *last = NULL; + int ret = 0; + + rcu_read_lock(); + list_for_each_entry_rcu(server, head, client_link) { + if (!nfs_sb_active(server->super)) + continue; + rcu_read_unlock(); + if (last) + nfs_sb_deactive(last->super); + last = server; + ret = fn(server, data); + if (ret) + goto out; + rcu_read_lock(); + } + rcu_read_unlock(); +out: + if (last) + nfs_sb_deactive(last->super); + return ret; +} + +int nfs_client_for_each_server(struct nfs_client *clp, + int (*fn)(struct nfs_server *, void *), + void *data) +{ + return __nfs_list_for_each_server(&clp->cl_superblocks, fn, data); +} +EXPORT_SYMBOL_GPL(nfs_client_for_each_server); + /* * Deliver file system statistics to userspace */ |
