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 file *(*nfsd_file_file)(struct nfsd_file *);
67 void (*nfsd_file_dio_alignment)(struct nfsd_file *,
68 u32 *, u32 *, u32 *);
69 } ____cacheline_aligned;
70
71 extern void nfsd_localio_ops_init(void);
72 extern const struct nfsd_localio_operations *nfs_to;
73
74 struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *,
75 struct rpc_clnt *, const struct cred *,
76 const struct nfs_fh *, struct nfs_file_localio *,
77 struct nfsd_file __rcu **pnf,
78 const fmode_t);
79
nfs_to_nfsd_net_put(struct net * net)80 static inline void nfs_to_nfsd_net_put(struct net *net)
81 {
82 /*
83 * Once reference to net (and associated nfsd_serv) is dropped, NFSD
84 * could be unloaded, so ensure safe return from nfsd_net_put() by
85 * always taking RCU.
86 */
87 rcu_read_lock();
88 nfs_to->nfsd_net_put(net);
89 rcu_read_unlock();
90 }
91
nfs_to_nfsd_file_put_local(struct nfsd_file __rcu ** localio)92 static inline void nfs_to_nfsd_file_put_local(struct nfsd_file __rcu **localio)
93 {
94 /*
95 * Either *localio must be guaranteed to be non-NULL, or caller
96 * must prevent nfsd shutdown from completing as nfs_close_local_fh()
97 * does by blocking the nfs_uuid from being finally put.
98 */
99 struct net *net;
100
101 net = nfs_to->nfsd_file_put_local(localio);
102
103 if (net)
104 nfs_to_nfsd_net_put(net);
105 }
106
107 #else /* CONFIG_NFS_LOCALIO */
108
109 struct nfs_file_localio;
nfs_close_local_fh(struct nfs_file_localio * nfl)110 static inline void nfs_close_local_fh(struct nfs_file_localio *nfl)
111 {
112 }
nfsd_localio_ops_init(void)113 static inline void nfsd_localio_ops_init(void)
114 {
115 }
116 struct nfs_client;
nfs_localio_disable_client(struct nfs_client * clp)117 static inline void nfs_localio_disable_client(struct nfs_client *clp)
118 {
119 }
120
121 #endif /* CONFIG_NFS_LOCALIO */
122
123 #endif /* __LINUX_NFSLOCALIO_H */
124