xref: /linux/include/linux/nfslocalio.h (revision e9ef810dfee7a2227da9d423aecb0ced35faddbe)
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