Skip to content

Commit 70ba381

Browse files
westonandrosadamsonAnna Schumaker
authored andcommitted
nfs: add LOCALIO support
Add client support for bypassing NFS for localhost reads, writes, and commits. This is only useful when the client and the server are running on the same host. nfs_local_probe() is stubbed out, later commits will enable client and server handshake via a Linux-only LOCALIO auxiliary RPC protocol. This has dynamic binding with the nfsd module (via nfs_localio module which is part of nfs_common). LOCALIO will only work if nfsd is already loaded. The "localio_enabled" nfs kernel module parameter can be used to disable and enable the ability to use LOCALIO support. CONFIG_NFS_LOCALIO enables NFS client support for LOCALIO. Lastly, LOCALIO uses an nfsd_file to initiate all IO. To make proper use of nfsd_file (and nfsd's filecache) its lifetime (duration before nfsd_file_put is called) must extend until after commit, read and write operations. So rather than immediately drop the nfsd_file reference in nfs_local_open_fh(), that doesn't happen until nfs_local_pgio_release() for read/write and not until nfs_local_release_commit_data() for commit. The same applies to the reference held on nfsd's nn->nfsd_serv. Both objects' lifetimes and associated references are managed through calls to nfs_to->nfsd_file_put_local(). Signed-off-by: Weston Andros Adamson <dros@primarydata.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Co-developed-by: Mike Snitzer <snitzer@kernel.org> Signed-off-by: Mike Snitzer <snitzer@kernel.org> Signed-off-by: NeilBrown <neilb@suse.de> # nfs_open_local_fh Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
1 parent df24c48 commit 70ba381

File tree

11 files changed

+773
-0
lines changed

11 files changed

+773
-0
lines changed

fs/nfs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ nfs-y := client.o dir.o file.o getroot.o inode.o super.o \
1313
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o
1414
nfs-$(CONFIG_SYSCTL) += sysctl.o
1515
nfs-$(CONFIG_NFS_FSCACHE) += fscache.o
16+
nfs-$(CONFIG_NFS_LOCALIO) += localio.o
1617

1718
obj-$(CONFIG_NFS_V2) += nfsv2.o
1819
nfsv2-y := nfs2super.o proc.o nfs2xdr.o

fs/nfs/client.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,14 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
178178
clp->cl_max_connect = cl_init->max_connect ? cl_init->max_connect : 1;
179179
clp->cl_net = get_net(cl_init->net);
180180

181+
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
182+
seqlock_init(&clp->cl_boot_lock);
183+
ktime_get_real_ts64(&clp->cl_nfssvc_boot);
184+
clp->cl_uuid.net = NULL;
185+
clp->cl_uuid.dom = NULL;
186+
spin_lock_init(&clp->cl_localio_lock);
187+
#endif /* CONFIG_NFS_LOCALIO */
188+
181189
clp->cl_principal = "*";
182190
clp->cl_xprtsec = cl_init->xprtsec;
183191
return clp;
@@ -233,6 +241,8 @@ static void pnfs_init_server(struct nfs_server *server)
233241
*/
234242
void nfs_free_client(struct nfs_client *clp)
235243
{
244+
nfs_local_disable(clp);
245+
236246
/* -EIO all pending I/O */
237247
if (!IS_ERR(clp->cl_rpcclient))
238248
rpc_shutdown_client(clp->cl_rpcclient);
@@ -424,6 +434,7 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
424434
list_add_tail(&new->cl_share_link,
425435
&nn->nfs_client_list);
426436
spin_unlock(&nn->nfs_client_lock);
437+
nfs_local_probe(new);
427438
return rpc_ops->init_client(new, cl_init);
428439
}
429440

fs/nfs/internal.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,51 @@ extern void nfs_set_cache_invalid(struct inode *inode, unsigned long flags);
451451
extern bool nfs_check_cache_invalid(struct inode *, unsigned long);
452452
extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode);
453453

454+
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
455+
/* localio.c */
456+
extern void nfs_local_disable(struct nfs_client *);
457+
extern void nfs_local_probe(struct nfs_client *);
458+
extern struct nfsd_file *nfs_local_open_fh(struct nfs_client *,
459+
const struct cred *,
460+
struct nfs_fh *,
461+
const fmode_t);
462+
extern int nfs_local_doio(struct nfs_client *,
463+
struct nfsd_file *,
464+
struct nfs_pgio_header *,
465+
const struct rpc_call_ops *);
466+
extern int nfs_local_commit(struct nfsd_file *,
467+
struct nfs_commit_data *,
468+
const struct rpc_call_ops *, int);
469+
extern bool nfs_server_is_local(const struct nfs_client *clp);
470+
471+
#else /* CONFIG_NFS_LOCALIO */
472+
static inline void nfs_local_disable(struct nfs_client *clp) {}
473+
static inline void nfs_local_probe(struct nfs_client *clp) {}
474+
static inline struct nfsd_file *
475+
nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
476+
struct nfs_fh *fh, const fmode_t mode)
477+
{
478+
return NULL;
479+
}
480+
static inline int nfs_local_doio(struct nfs_client *clp,
481+
struct nfsd_file *localio,
482+
struct nfs_pgio_header *hdr,
483+
const struct rpc_call_ops *call_ops)
484+
{
485+
return -EINVAL;
486+
}
487+
static inline int nfs_local_commit(struct nfsd_file *localio,
488+
struct nfs_commit_data *data,
489+
const struct rpc_call_ops *call_ops, int how)
490+
{
491+
return -EINVAL;
492+
}
493+
static inline bool nfs_server_is_local(const struct nfs_client *clp)
494+
{
495+
return false;
496+
}
497+
#endif /* CONFIG_NFS_LOCALIO */
498+
454499
/* super.c */
455500
extern const struct super_operations nfs_sops;
456501
bool nfs_auth_info_match(const struct nfs_auth_info *, rpc_authflavor_t);

0 commit comments

Comments
 (0)