1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (C) 2024 Mike Snitzer <[email protected]> 4 * Copyright (C) 2024 NeilBrown <[email protected]> 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 extern struct nfsd_file * 54 nfsd_open_local_fh(struct net *, struct auth_domain *, struct rpc_clnt *, 55 const struct cred *, const struct nfs_fh *, 56 const fmode_t) __must_hold(rcu); 57 void nfs_close_local_fh(struct nfs_file_localio *); 58 59 struct nfsd_localio_operations { 60 bool (*nfsd_net_try_get)(struct net *); 61 void (*nfsd_net_put)(struct net *); 62 struct nfsd_file *(*nfsd_open_local_fh)(struct net *, 63 struct auth_domain *, 64 struct rpc_clnt *, 65 const struct cred *, 66 const struct nfs_fh *, 67 const fmode_t); 68 struct net *(*nfsd_file_put_local)(struct nfsd_file *); 69 struct nfsd_file *(*nfsd_file_get)(struct nfsd_file *); 70 void (*nfsd_file_put)(struct nfsd_file *); 71 struct file *(*nfsd_file_file)(struct nfsd_file *); 72 } ____cacheline_aligned; 73 74 extern void nfsd_localio_ops_init(void); 75 extern const struct nfsd_localio_operations *nfs_to; 76 77 struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *, 78 struct rpc_clnt *, const struct cred *, 79 const struct nfs_fh *, struct nfs_file_localio *, 80 const fmode_t); 81 82 static inline void nfs_to_nfsd_net_put(struct net *net) 83 { 84 /* 85 * Once reference to net (and associated nfsd_serv) is dropped, NFSD 86 * could be unloaded, so ensure safe return from nfsd_net_put() by 87 * always taking RCU. 88 */ 89 rcu_read_lock(); 90 nfs_to->nfsd_net_put(net); 91 rcu_read_unlock(); 92 } 93 94 static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio) 95 { 96 /* 97 * Must not hold RCU otherwise nfsd_file_put() can easily trigger: 98 * "Voluntary context switch within RCU read-side critical section!" 99 * by scheduling deep in underlying filesystem (e.g. XFS). 100 */ 101 struct net *net = nfs_to->nfsd_file_put_local(localio); 102 103 nfs_to_nfsd_net_put(net); 104 } 105 106 #else /* CONFIG_NFS_LOCALIO */ 107 108 struct nfs_file_localio; 109 static inline void nfs_close_local_fh(struct nfs_file_localio *nfl) 110 { 111 } 112 static inline void nfsd_localio_ops_init(void) 113 { 114 } 115 struct nfs_client; 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