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