1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * Copyright (C) 2024 Mike Snitzer <snitzer@hammerspace.com>
4 * Copyright (C) 2024 NeilBrown <neilb@suse.de>
5 */
6 #ifndef __LINUX_NFSLOCALIO_H
7 #define __LINUX_NFSLOCALIO_H
8
9 #if IS_ENABLED(CONFIG_NFS_LOCALIO)
10
11 #include <linux/module.h>
12 #include <linux/list.h>
13 #include <linux/uuid.h>
14 #include <linux/sunrpc/clnt.h>
15 #include <linux/sunrpc/svcauth.h>
16 #include <linux/nfs.h>
17 #include <net/net_namespace.h>
18
19 struct nfs_client;
20 struct nfs_file_localio;
21
22 /*
23 * Useful to allow a client to negotiate if localio
24 * possible with its server.
25 *
26 * See Documentation/filesystems/nfs/localio.rst for more detail.
27 */
28 typedef struct {
29 uuid_t uuid;
30 unsigned nfs3_localio_probe_count;
31 /* this struct is over a cacheline, avoid bouncing */
32 spinlock_t ____cacheline_aligned lock;
33 struct list_head list;
34 spinlock_t *list_lock; /* nn->local_clients_lock */
35 struct net __rcu *net; /* nfsd's network namespace */
36 struct auth_domain *dom; /* auth_domain for localio */
37 /* Local files to close when net is shut down or exports change */
38 struct list_head files;
39 } nfs_uuid_t;
40
41 void nfs_uuid_init(nfs_uuid_t *);
42 bool nfs_uuid_begin(nfs_uuid_t *);
43 void nfs_uuid_end(nfs_uuid_t *);
44 void nfs_uuid_is_local(const uuid_t *, struct list_head *, spinlock_t *,
45 struct net *, struct auth_domain *, struct module *);
46
47 void nfs_localio_enable_client(struct nfs_client *clp);
48 void nfs_localio_disable_client(struct nfs_client *clp);
49 void nfs_localio_invalidate_clients(struct list_head *nn_local_clients,
50 spinlock_t *nn_local_clients_lock);
51
52 /* localio needs to map filehandle -> struct nfsd_file */
53 void nfs_close_local_fh(struct nfs_file_localio *);
54
55 struct nfsd_localio_operations {
56 bool (*nfsd_net_try_get)(struct net *);
57 void (*nfsd_net_put)(struct net *);
58 struct nfsd_file *(*nfsd_open_local_fh)(struct net *,
59 struct auth_domain *,
60 struct rpc_clnt *,
61 const struct cred *,
62 const struct nfs_fh *,
63 struct nfsd_file __rcu **pnf,
64 const fmode_t);
65 struct net *(*nfsd_file_put_local)(struct nfsd_file __rcu **);
66 struct nfsd_file *(*nfsd_file_get_local)(struct nfsd_file *);
67 struct file *(*nfsd_file_file)(struct nfsd_file *);
68 } ____cacheline_aligned;
69
70 extern void nfsd_localio_ops_init(void);
71 extern const struct nfsd_localio_operations *nfs_to;
72
73 struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *,
74 struct rpc_clnt *, const struct cred *,
75 const struct nfs_fh *, struct nfs_file_localio *,
76 struct nfsd_file __rcu **pnf,
77 const fmode_t);
78
nfs_to_nfsd_net_put(struct net * net)79 static inline void nfs_to_nfsd_net_put(struct net *net)
80 {
81 /*
82 * Once reference to net (and associated nfsd_serv) is dropped, NFSD
83 * could be unloaded, so ensure safe return from nfsd_net_put() by
84 * always taking RCU.
85 */
86 rcu_read_lock();
87 nfs_to->nfsd_net_put(net);
88 rcu_read_unlock();
89 }
90
nfs_to_nfsd_file_put_local(struct nfsd_file __rcu ** localio)91 static inline void nfs_to_nfsd_file_put_local(struct nfsd_file __rcu **localio)
92 {
93 /*
94 * Either *localio must be guaranteed to be non-NULL, or caller
95 * must prevent nfsd shutdown from completing as nfs_close_local_fh()
96 * does by blocking the nfs_uuid from being finally put.
97 */
98 struct net *net;
99
100 net = nfs_to->nfsd_file_put_local(localio);
101
102 if (net)
103 nfs_to_nfsd_net_put(net);
104 }
105
106 #else /* CONFIG_NFS_LOCALIO */
107
108 struct nfs_file_localio;
nfs_close_local_fh(struct nfs_file_localio * nfl)109 static inline void nfs_close_local_fh(struct nfs_file_localio *nfl)
110 {
111 }
nfsd_localio_ops_init(void)112 static inline void nfsd_localio_ops_init(void)
113 {
114 }
115 struct nfs_client;
nfs_localio_disable_client(struct nfs_client * clp)116 static inline void nfs_localio_disable_client(struct nfs_client *clp)
117 {
118 }
119
120 #endif /* CONFIG_NFS_LOCALIO */
121
122 #endif /* __LINUX_NFSLOCALIO_H */
123