Skip to content

Commit a61e147

Browse files
Mike SnitzerAnna Schumaker
authored andcommitted
nfs_common: prepare for the NFS client to use nfsd_file for LOCALIO
The next commit will introduce nfsd_open_local_fh() which returns an nfsd_file structure. This commit exposes LOCALIO's required NFSD symbols to the NFS client: - Make nfsd_open_local_fh() symbol and other required NFSD symbols available to NFS in a global 'nfs_to' nfsd_localio_operations struct (global access suggested by Trond, nfsd_localio_operations suggested by NeilBrown). The next commit will also introduce nfsd_localio_ops_init() that init_nfsd() will call to initialize 'nfs_to'. - Introduce nfsd_file_file() that provides access to nfsd_file's backing file. Keeps nfsd_file structure opaque to NFS client (as suggested by Jeff Layton). - Introduce nfsd_file_put_local() that will put the reference to the nfsd_file's associated nn->nfsd_serv and then put the reference to the nfsd_file (as suggested by NeilBrown). Suggested-by: Trond Myklebust <trond.myklebust@hammerspace.com> # nfs_to Suggested-by: NeilBrown <neilb@suse.de> # nfsd_localio_operations Suggested-by: Jeff Layton <jlayton@kernel.org> # nfsd_file_file Signed-off-by: Mike Snitzer <snitzer@kernel.org> Reviewed-by: NeilBrown <neilb@suse.de> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
1 parent 2a33a85 commit a61e147

File tree

5 files changed

+81
-2
lines changed

5 files changed

+81
-2
lines changed

fs/nfs_common/nfslocalio.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ void nfs_uuid_is_local(const uuid_t *uuid, struct list_head *list,
7272
* invalidated.
7373
*/
7474
list_move(&nfs_uuid->list, list);
75-
nfs_uuid->net = net;
75+
rcu_assign_pointer(nfs_uuid->net, net);
7676

7777
__module_get(mod);
7878
nfsd_mod = mod;
@@ -114,3 +114,26 @@ void nfs_uuid_invalidate_one_client(nfs_uuid_t *nfs_uuid)
114114
}
115115
}
116116
EXPORT_SYMBOL_GPL(nfs_uuid_invalidate_one_client);
117+
118+
/*
119+
* The NFS LOCALIO code needs to call into NFSD using various symbols,
120+
* but cannot be statically linked, because that will make the NFS
121+
* module always depend on the NFSD module.
122+
*
123+
* 'nfs_to' provides NFS access to NFSD functions needed for LOCALIO,
124+
* its lifetime is tightly coupled to the NFSD module and will always
125+
* be available to NFS LOCALIO because any successful client<->server
126+
* LOCALIO handshake results in a reference on the NFSD module (above),
127+
* so NFS implicitly holds a reference to the NFSD module and its
128+
* functions in the 'nfs_to' nfsd_localio_operations cannot disappear.
129+
*
130+
* If the last NFS client using LOCALIO disconnects (and its reference
131+
* on NFSD dropped) then NFSD could be unloaded, resulting in 'nfs_to'
132+
* functions being invalid pointers. But if NFSD isn't loaded then NFS
133+
* will not be able to handshake with NFSD and will have no cause to
134+
* try to call 'nfs_to' function pointers. If/when NFSD is reloaded it
135+
* will reinitialize the 'nfs_to' function pointers and make LOCALIO
136+
* possible.
137+
*/
138+
const struct nfsd_localio_operations *nfs_to;
139+
EXPORT_SYMBOL_GPL(nfs_to);

fs/nfsd/filecache.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,34 @@ nfsd_file_put(struct nfsd_file *nf)
390390
nfsd_file_free(nf);
391391
}
392392

393+
/**
394+
* nfsd_file_put_local - put the reference to nfsd_file and local nfsd_serv
395+
* @nf: nfsd_file of which to put the references
396+
*
397+
* First put the reference of the nfsd_file and then put the
398+
* reference to the associated nn->nfsd_serv.
399+
*/
400+
void
401+
nfsd_file_put_local(struct nfsd_file *nf)
402+
{
403+
struct net *net = nf->nf_net;
404+
405+
nfsd_file_put(nf);
406+
nfsd_serv_put(net);
407+
}
408+
409+
/**
410+
* nfsd_file_file - get the backing file of an nfsd_file
411+
* @nf: nfsd_file of which to access the backing file.
412+
*
413+
* Return backing file for @nf.
414+
*/
415+
struct file *
416+
nfsd_file_file(struct nfsd_file *nf)
417+
{
418+
return nf->nf_file;
419+
}
420+
393421
static void
394422
nfsd_file_dispose_list(struct list_head *dispose)
395423
{

fs/nfsd/filecache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ void nfsd_file_cache_shutdown(void);
5555
int nfsd_file_cache_start_net(struct net *net);
5656
void nfsd_file_cache_shutdown_net(struct net *net);
5757
void nfsd_file_put(struct nfsd_file *nf);
58+
void nfsd_file_put_local(struct nfsd_file *nf);
5859
struct nfsd_file *nfsd_file_get(struct nfsd_file *nf);
60+
struct file *nfsd_file_file(struct nfsd_file *nf);
5961
void nfsd_file_close_inode_sync(struct inode *inode);
6062
void nfsd_file_net_dispose(struct nfsd_net *nn);
6163
bool nfsd_file_is_cached(struct inode *inode);

fs/nfsd/nfssvc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/sunrpc/svc_xprt.h>
2020
#include <linux/lockd/bind.h>
2121
#include <linux/nfsacl.h>
22+
#include <linux/nfslocalio.h>
2223
#include <linux/seq_file.h>
2324
#include <linux/inetdevice.h>
2425
#include <net/addrconf.h>

include/linux/nfslocalio.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/module.h>
1010
#include <linux/list.h>
1111
#include <linux/uuid.h>
12+
#include <linux/sunrpc/clnt.h>
1213
#include <linux/sunrpc/svcauth.h>
1314
#include <linux/nfs.h>
1415
#include <net/net_namespace.h>
@@ -22,7 +23,7 @@
2223
typedef struct {
2324
uuid_t uuid;
2425
struct list_head list;
25-
struct net *net; /* nfsd's network namespace */
26+
struct net __rcu *net; /* nfsd's network namespace */
2627
struct auth_domain *dom; /* auth_domain for localio */
2728
} nfs_uuid_t;
2829

@@ -33,4 +34,28 @@ void nfs_uuid_is_local(const uuid_t *, struct list_head *,
3334
void nfs_uuid_invalidate_clients(struct list_head *list);
3435
void nfs_uuid_invalidate_one_client(nfs_uuid_t *nfs_uuid);
3536

37+
struct nfsd_file;
38+
39+
/* localio needs to map filehandle -> struct nfsd_file */
40+
extern struct nfsd_file *
41+
nfsd_open_local_fh(struct net *, struct auth_domain *, struct rpc_clnt *,
42+
const struct cred *, const struct nfs_fh *,
43+
const fmode_t) __must_hold(rcu);
44+
45+
struct nfsd_localio_operations {
46+
bool (*nfsd_serv_try_get)(struct net *);
47+
void (*nfsd_serv_put)(struct net *);
48+
struct nfsd_file *(*nfsd_open_local_fh)(struct net *,
49+
struct auth_domain *,
50+
struct rpc_clnt *,
51+
const struct cred *,
52+
const struct nfs_fh *,
53+
const fmode_t);
54+
void (*nfsd_file_put_local)(struct nfsd_file *);
55+
struct file *(*nfsd_file_file)(struct nfsd_file *);
56+
} ____cacheline_aligned;
57+
58+
extern void nfsd_localio_ops_init(void);
59+
extern const struct nfsd_localio_operations *nfs_to;
60+
3661
#endif /* __LINUX_NFSLOCALIO_H */

0 commit comments

Comments
 (0)