mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
nfs: cache all open LOCALIO nfsd_file(s) in client
This commit switches from leaning heavily on NFSD's filecache (in terms of GC'd nfsd_files) back to caching nfsd_files in the client. A later commit will add the callback mechanism needed to allow NFSD to force the NFS client to cleanup all cached nfsd_files. Add nfs_fh_localio_init() and 'struct nfs_fh_localio' to cache opened nfsd_file(s) (both a RO and RW nfsd_file is able to be opened and cached for a given nfs_fh). Update nfs_local_open_fh() to cache the nfsd_file once it is opened using __nfs_local_open_fh(). Introduce nfs_close_local_fh() to clear the cached open nfsd_files and call nfs_to_nfsd_file_put_local(). Refcounting is such that: - nfs_local_open_fh() is paired with nfs_close_local_fh(). - __nfs_local_open_fh() is paired with nfs_to_nfsd_file_put_local(). - nfs_local_file_get() is paired with nfs_local_file_put(). Signed-off-by: Mike Snitzer <snitzer@kernel.org> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
This commit is contained in:
parent
4ee7ba4000
commit
86e0041225
10 changed files with 177 additions and 45 deletions
|
@ -164,18 +164,17 @@ decode_name(struct xdr_stream *xdr, u32 *id)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nfsd_file *
|
static struct nfsd_file *
|
||||||
ff_local_open_fh(struct nfs_client *clp, const struct cred *cred,
|
ff_local_open_fh(struct pnfs_layout_segment *lseg, u32 ds_idx,
|
||||||
|
struct nfs_client *clp, const struct cred *cred,
|
||||||
struct nfs_fh *fh, fmode_t mode)
|
struct nfs_fh *fh, fmode_t mode)
|
||||||
{
|
{
|
||||||
if (mode & FMODE_WRITE) {
|
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
|
||||||
/*
|
struct nfs4_ff_layout_mirror *mirror = FF_LAYOUT_COMP(lseg, ds_idx);
|
||||||
* Always request read and write access since this corresponds
|
|
||||||
* to a rw layout.
|
|
||||||
*/
|
|
||||||
mode |= FMODE_READ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nfs_local_open_fh(clp, cred, fh, mode);
|
return nfs_local_open_fh(clp, cred, fh, &mirror->nfl, mode);
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ff_mirror_match_fh(const struct nfs4_ff_layout_mirror *m1,
|
static bool ff_mirror_match_fh(const struct nfs4_ff_layout_mirror *m1,
|
||||||
|
@ -247,6 +246,7 @@ static struct nfs4_ff_layout_mirror *ff_layout_alloc_mirror(gfp_t gfp_flags)
|
||||||
spin_lock_init(&mirror->lock);
|
spin_lock_init(&mirror->lock);
|
||||||
refcount_set(&mirror->ref, 1);
|
refcount_set(&mirror->ref, 1);
|
||||||
INIT_LIST_HEAD(&mirror->mirrors);
|
INIT_LIST_HEAD(&mirror->mirrors);
|
||||||
|
nfs_localio_file_init(&mirror->nfl);
|
||||||
}
|
}
|
||||||
return mirror;
|
return mirror;
|
||||||
}
|
}
|
||||||
|
@ -257,6 +257,7 @@ static void ff_layout_free_mirror(struct nfs4_ff_layout_mirror *mirror)
|
||||||
|
|
||||||
ff_layout_remove_mirror(mirror);
|
ff_layout_remove_mirror(mirror);
|
||||||
kfree(mirror->fh_versions);
|
kfree(mirror->fh_versions);
|
||||||
|
nfs_close_local_fh(&mirror->nfl);
|
||||||
cred = rcu_access_pointer(mirror->ro_cred);
|
cred = rcu_access_pointer(mirror->ro_cred);
|
||||||
put_cred(cred);
|
put_cred(cred);
|
||||||
cred = rcu_access_pointer(mirror->rw_cred);
|
cred = rcu_access_pointer(mirror->rw_cred);
|
||||||
|
@ -1820,7 +1821,7 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr)
|
||||||
hdr->mds_offset = offset;
|
hdr->mds_offset = offset;
|
||||||
|
|
||||||
/* Start IO accounting for local read */
|
/* Start IO accounting for local read */
|
||||||
localio = ff_local_open_fh(ds->ds_clp, ds_cred, fh, FMODE_READ);
|
localio = ff_local_open_fh(lseg, idx, ds->ds_clp, ds_cred, fh, FMODE_READ);
|
||||||
if (localio) {
|
if (localio) {
|
||||||
hdr->task.tk_start = ktime_get();
|
hdr->task.tk_start = ktime_get();
|
||||||
ff_layout_read_record_layoutstats_start(&hdr->task, hdr);
|
ff_layout_read_record_layoutstats_start(&hdr->task, hdr);
|
||||||
|
@ -1896,7 +1897,7 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
|
||||||
hdr->args.offset = offset;
|
hdr->args.offset = offset;
|
||||||
|
|
||||||
/* Start IO accounting for local write */
|
/* Start IO accounting for local write */
|
||||||
localio = ff_local_open_fh(ds->ds_clp, ds_cred, fh,
|
localio = ff_local_open_fh(lseg, idx, ds->ds_clp, ds_cred, fh,
|
||||||
FMODE_READ|FMODE_WRITE);
|
FMODE_READ|FMODE_WRITE);
|
||||||
if (localio) {
|
if (localio) {
|
||||||
hdr->task.tk_start = ktime_get();
|
hdr->task.tk_start = ktime_get();
|
||||||
|
@ -1981,7 +1982,7 @@ static int ff_layout_initiate_commit(struct nfs_commit_data *data, int how)
|
||||||
data->args.fh = fh;
|
data->args.fh = fh;
|
||||||
|
|
||||||
/* Start IO accounting for local commit */
|
/* Start IO accounting for local commit */
|
||||||
localio = ff_local_open_fh(ds->ds_clp, ds_cred, fh,
|
localio = ff_local_open_fh(lseg, idx, ds->ds_clp, ds_cred, fh,
|
||||||
FMODE_READ|FMODE_WRITE);
|
FMODE_READ|FMODE_WRITE);
|
||||||
if (localio) {
|
if (localio) {
|
||||||
data->task.tk_start = ktime_get();
|
data->task.tk_start = ktime_get();
|
||||||
|
|
|
@ -83,6 +83,7 @@ struct nfs4_ff_layout_mirror {
|
||||||
nfs4_stateid stateid;
|
nfs4_stateid stateid;
|
||||||
const struct cred __rcu *ro_cred;
|
const struct cred __rcu *ro_cred;
|
||||||
const struct cred __rcu *rw_cred;
|
const struct cred __rcu *rw_cred;
|
||||||
|
struct nfs_file_localio nfl;
|
||||||
refcount_t ref;
|
refcount_t ref;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
|
@ -1137,6 +1137,8 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry,
|
||||||
ctx->lock_context.open_context = ctx;
|
ctx->lock_context.open_context = ctx;
|
||||||
INIT_LIST_HEAD(&ctx->list);
|
INIT_LIST_HEAD(&ctx->list);
|
||||||
ctx->mdsthreshold = NULL;
|
ctx->mdsthreshold = NULL;
|
||||||
|
nfs_localio_file_init(&ctx->nfl);
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(alloc_nfs_open_context);
|
EXPORT_SYMBOL_GPL(alloc_nfs_open_context);
|
||||||
|
@ -1168,6 +1170,7 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
|
||||||
nfs_sb_deactive(sb);
|
nfs_sb_deactive(sb);
|
||||||
put_rpccred(rcu_dereference_protected(ctx->ll_cred, 1));
|
put_rpccred(rcu_dereference_protected(ctx->ll_cred, 1));
|
||||||
kfree(ctx->mdsthreshold);
|
kfree(ctx->mdsthreshold);
|
||||||
|
nfs_close_local_fh(&ctx->nfl);
|
||||||
kfree_rcu(ctx, rcu_head);
|
kfree_rcu(ctx, rcu_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -460,6 +460,7 @@ extern void nfs_local_probe(struct nfs_client *);
|
||||||
extern struct nfsd_file *nfs_local_open_fh(struct nfs_client *,
|
extern struct nfsd_file *nfs_local_open_fh(struct nfs_client *,
|
||||||
const struct cred *,
|
const struct cred *,
|
||||||
struct nfs_fh *,
|
struct nfs_fh *,
|
||||||
|
struct nfs_file_localio *,
|
||||||
const fmode_t);
|
const fmode_t);
|
||||||
extern int nfs_local_doio(struct nfs_client *,
|
extern int nfs_local_doio(struct nfs_client *,
|
||||||
struct nfsd_file *,
|
struct nfsd_file *,
|
||||||
|
@ -475,7 +476,8 @@ static inline void nfs_local_disable(struct nfs_client *clp) {}
|
||||||
static inline void nfs_local_probe(struct nfs_client *clp) {}
|
static inline void nfs_local_probe(struct nfs_client *clp) {}
|
||||||
static inline struct nfsd_file *
|
static inline struct nfsd_file *
|
||||||
nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
|
nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
|
||||||
struct nfs_fh *fh, const fmode_t mode)
|
struct nfs_fh *fh, struct nfs_file_localio *nfl,
|
||||||
|
const fmode_t mode)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,27 +211,33 @@ void nfs_local_probe(struct nfs_client *clp)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(nfs_local_probe);
|
EXPORT_SYMBOL_GPL(nfs_local_probe);
|
||||||
|
|
||||||
|
static inline struct nfsd_file *nfs_local_file_get(struct nfsd_file *nf)
|
||||||
|
{
|
||||||
|
return nfs_to->nfsd_file_get(nf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void nfs_local_file_put(struct nfsd_file *nf)
|
||||||
|
{
|
||||||
|
nfs_to->nfsd_file_put(nf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nfs_local_open_fh - open a local filehandle in terms of nfsd_file
|
* __nfs_local_open_fh - open a local filehandle in terms of nfsd_file.
|
||||||
*
|
*
|
||||||
* Returns a pointer to a struct nfsd_file or NULL
|
* Returns a pointer to a struct nfsd_file or ERR_PTR.
|
||||||
|
* Caller must release returned nfsd_file with nfs_to_nfsd_file_put_local().
|
||||||
*/
|
*/
|
||||||
struct nfsd_file *
|
static struct nfsd_file *
|
||||||
nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
|
__nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
|
||||||
struct nfs_fh *fh, const fmode_t mode)
|
struct nfs_fh *fh, struct nfs_file_localio *nfl,
|
||||||
|
const fmode_t mode)
|
||||||
{
|
{
|
||||||
struct nfsd_file *localio;
|
struct nfsd_file *localio;
|
||||||
int status;
|
|
||||||
|
|
||||||
if (!nfs_server_is_local(clp))
|
|
||||||
return NULL;
|
|
||||||
if (mode & ~(FMODE_READ | FMODE_WRITE))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
localio = nfs_open_local_fh(&clp->cl_uuid, clp->cl_rpcclient,
|
localio = nfs_open_local_fh(&clp->cl_uuid, clp->cl_rpcclient,
|
||||||
cred, fh, mode);
|
cred, fh, nfl, mode);
|
||||||
if (IS_ERR(localio)) {
|
if (IS_ERR(localio)) {
|
||||||
status = PTR_ERR(localio);
|
int status = PTR_ERR(localio);
|
||||||
trace_nfs_local_open_fh(fh, mode, status);
|
trace_nfs_local_open_fh(fh, mode, status);
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case -ENOMEM:
|
case -ENOMEM:
|
||||||
|
@ -240,10 +246,59 @@ nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
|
||||||
/* Revalidate localio, will disable if unsupported */
|
/* Revalidate localio, will disable if unsupported */
|
||||||
nfs_local_probe(clp);
|
nfs_local_probe(clp);
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
return localio;
|
return localio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nfs_local_open_fh - open a local filehandle in terms of nfsd_file.
|
||||||
|
* First checking if the open nfsd_file is already cached, otherwise
|
||||||
|
* must __nfs_local_open_fh and insert the nfsd_file in nfs_file_localio.
|
||||||
|
*
|
||||||
|
* Returns a pointer to a struct nfsd_file or NULL.
|
||||||
|
*/
|
||||||
|
struct nfsd_file *
|
||||||
|
nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
|
||||||
|
struct nfs_fh *fh, struct nfs_file_localio *nfl,
|
||||||
|
const fmode_t mode)
|
||||||
|
{
|
||||||
|
struct nfsd_file *nf, *new, __rcu **pnf;
|
||||||
|
|
||||||
|
if (!nfs_server_is_local(clp))
|
||||||
|
return NULL;
|
||||||
|
if (mode & ~(FMODE_READ | FMODE_WRITE))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (mode & FMODE_WRITE)
|
||||||
|
pnf = &nfl->rw_file;
|
||||||
|
else
|
||||||
|
pnf = &nfl->ro_file;
|
||||||
|
|
||||||
|
new = NULL;
|
||||||
|
rcu_read_lock();
|
||||||
|
nf = rcu_dereference(*pnf);
|
||||||
|
if (!nf) {
|
||||||
|
rcu_read_unlock();
|
||||||
|
new = __nfs_local_open_fh(clp, cred, fh, nfl, mode);
|
||||||
|
if (IS_ERR(new))
|
||||||
|
return NULL;
|
||||||
|
/* try to swap in the pointer */
|
||||||
|
spin_lock(&clp->cl_uuid.lock);
|
||||||
|
nf = rcu_dereference_protected(*pnf, 1);
|
||||||
|
if (!nf) {
|
||||||
|
nf = new;
|
||||||
|
new = NULL;
|
||||||
|
rcu_assign_pointer(*pnf, nf);
|
||||||
|
}
|
||||||
|
spin_unlock(&clp->cl_uuid.lock);
|
||||||
|
rcu_read_lock();
|
||||||
|
}
|
||||||
|
nf = nfs_local_file_get(nf);
|
||||||
|
rcu_read_unlock();
|
||||||
|
if (new)
|
||||||
|
nfs_to_nfsd_file_put_local(new);
|
||||||
|
return nf;
|
||||||
|
}
|
||||||
EXPORT_SYMBOL_GPL(nfs_local_open_fh);
|
EXPORT_SYMBOL_GPL(nfs_local_open_fh);
|
||||||
|
|
||||||
static struct bio_vec *
|
static struct bio_vec *
|
||||||
|
@ -347,7 +402,7 @@ nfs_local_pgio_release(struct nfs_local_kiocb *iocb)
|
||||||
{
|
{
|
||||||
struct nfs_pgio_header *hdr = iocb->hdr;
|
struct nfs_pgio_header *hdr = iocb->hdr;
|
||||||
|
|
||||||
nfs_to_nfsd_file_put_local(iocb->localio);
|
nfs_local_file_put(iocb->localio);
|
||||||
nfs_local_iocb_free(iocb);
|
nfs_local_iocb_free(iocb);
|
||||||
nfs_local_hdr_release(hdr, hdr->task.tk_ops);
|
nfs_local_hdr_release(hdr, hdr->task.tk_ops);
|
||||||
}
|
}
|
||||||
|
@ -694,7 +749,7 @@ int nfs_local_doio(struct nfs_client *clp, struct nfsd_file *localio,
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
if (status == -EAGAIN)
|
if (status == -EAGAIN)
|
||||||
nfs_local_disable(clp);
|
nfs_local_disable(clp);
|
||||||
nfs_to_nfsd_file_put_local(localio);
|
nfs_local_file_put(localio);
|
||||||
hdr->task.tk_status = status;
|
hdr->task.tk_status = status;
|
||||||
nfs_local_hdr_release(hdr, call_ops);
|
nfs_local_hdr_release(hdr, call_ops);
|
||||||
}
|
}
|
||||||
|
@ -745,7 +800,7 @@ nfs_local_release_commit_data(struct nfsd_file *localio,
|
||||||
struct nfs_commit_data *data,
|
struct nfs_commit_data *data,
|
||||||
const struct rpc_call_ops *call_ops)
|
const struct rpc_call_ops *call_ops)
|
||||||
{
|
{
|
||||||
nfs_to_nfsd_file_put_local(localio);
|
nfs_local_file_put(localio);
|
||||||
call_ops->rpc_call_done(&data->task, data);
|
call_ops->rpc_call_done(&data->task, data);
|
||||||
call_ops->rpc_release(data);
|
call_ops->rpc_release(data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -961,8 +961,9 @@ static int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc)
|
||||||
struct nfs_client *clp = NFS_SERVER(hdr->inode)->nfs_client;
|
struct nfs_client *clp = NFS_SERVER(hdr->inode)->nfs_client;
|
||||||
|
|
||||||
struct nfsd_file *localio =
|
struct nfsd_file *localio =
|
||||||
nfs_local_open_fh(clp, hdr->cred,
|
nfs_local_open_fh(clp, hdr->cred, hdr->args.fh,
|
||||||
hdr->args.fh, hdr->args.context->mode);
|
&hdr->args.context->nfl,
|
||||||
|
hdr->args.context->mode);
|
||||||
|
|
||||||
if (NFS_SERVER(hdr->inode)->nfs_client->cl_minorversion)
|
if (NFS_SERVER(hdr->inode)->nfs_client->cl_minorversion)
|
||||||
task_flags = RPC_TASK_MOVEABLE;
|
task_flags = RPC_TASK_MOVEABLE;
|
||||||
|
|
|
@ -1826,7 +1826,8 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how,
|
||||||
task_flags = RPC_TASK_MOVEABLE;
|
task_flags = RPC_TASK_MOVEABLE;
|
||||||
|
|
||||||
localio = nfs_local_open_fh(NFS_SERVER(inode)->nfs_client, data->cred,
|
localio = nfs_local_open_fh(NFS_SERVER(inode)->nfs_client, data->cred,
|
||||||
data->args.fh, data->context->mode);
|
data->args.fh, &data->context->nfl,
|
||||||
|
data->context->mode);
|
||||||
return nfs_initiate_commit(NFS_CLIENT(inode), data, NFS_PROTO(inode),
|
return nfs_initiate_commit(NFS_CLIENT(inode), data, NFS_PROTO(inode),
|
||||||
data->mds_ops, how,
|
data->mds_ops, how,
|
||||||
RPC_TASK_CRED_NOREF | task_flags, localio);
|
RPC_TASK_CRED_NOREF | task_flags, localio);
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include <linux/nfslocalio.h>
|
#include <linux/nfslocalio.h>
|
||||||
#include <linux/nfs3.h>
|
#include <linux/nfs3.h>
|
||||||
#include <linux/nfs4.h>
|
#include <linux/nfs4.h>
|
||||||
#include <linux/nfs_fs_sb.h>
|
#include <linux/nfs_fs.h>
|
||||||
#include <net/netns/generic.h>
|
#include <net/netns/generic.h>
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -151,9 +151,18 @@ void nfs_localio_invalidate_clients(struct list_head *cl_uuid_list)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(nfs_localio_invalidate_clients);
|
EXPORT_SYMBOL_GPL(nfs_localio_invalidate_clients);
|
||||||
|
|
||||||
|
static void nfs_uuid_add_file(nfs_uuid_t *nfs_uuid, struct nfs_file_localio *nfl)
|
||||||
|
{
|
||||||
|
spin_lock(&nfs_uuid_lock);
|
||||||
|
if (!nfl->nfs_uuid)
|
||||||
|
rcu_assign_pointer(nfl->nfs_uuid, nfs_uuid);
|
||||||
|
spin_unlock(&nfs_uuid_lock);
|
||||||
|
}
|
||||||
|
|
||||||
struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid,
|
struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid,
|
||||||
struct rpc_clnt *rpc_clnt, const struct cred *cred,
|
struct rpc_clnt *rpc_clnt, const struct cred *cred,
|
||||||
const struct nfs_fh *nfs_fh, const fmode_t fmode)
|
const struct nfs_fh *nfs_fh, struct nfs_file_localio *nfl,
|
||||||
|
const fmode_t fmode)
|
||||||
{
|
{
|
||||||
struct net *net;
|
struct net *net;
|
||||||
struct nfsd_file *localio;
|
struct nfsd_file *localio;
|
||||||
|
@ -180,11 +189,50 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid,
|
||||||
cred, nfs_fh, fmode);
|
cred, nfs_fh, fmode);
|
||||||
if (IS_ERR(localio))
|
if (IS_ERR(localio))
|
||||||
nfs_to_nfsd_net_put(net);
|
nfs_to_nfsd_net_put(net);
|
||||||
|
else
|
||||||
|
nfs_uuid_add_file(uuid, nfl);
|
||||||
|
|
||||||
return localio;
|
return localio;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(nfs_open_local_fh);
|
EXPORT_SYMBOL_GPL(nfs_open_local_fh);
|
||||||
|
|
||||||
|
void nfs_close_local_fh(struct nfs_file_localio *nfl)
|
||||||
|
{
|
||||||
|
struct nfsd_file *ro_nf = NULL;
|
||||||
|
struct nfsd_file *rw_nf = NULL;
|
||||||
|
nfs_uuid_t *nfs_uuid;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
nfs_uuid = rcu_dereference(nfl->nfs_uuid);
|
||||||
|
if (!nfs_uuid) {
|
||||||
|
/* regular (non-LOCALIO) NFS will hammer this */
|
||||||
|
rcu_read_unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ro_nf = rcu_access_pointer(nfl->ro_file);
|
||||||
|
rw_nf = rcu_access_pointer(nfl->rw_file);
|
||||||
|
if (ro_nf || rw_nf) {
|
||||||
|
spin_lock(&nfs_uuid_lock);
|
||||||
|
if (ro_nf)
|
||||||
|
ro_nf = rcu_dereference_protected(xchg(&nfl->ro_file, NULL), 1);
|
||||||
|
if (rw_nf)
|
||||||
|
rw_nf = rcu_dereference_protected(xchg(&nfl->rw_file, NULL), 1);
|
||||||
|
|
||||||
|
rcu_assign_pointer(nfl->nfs_uuid, NULL);
|
||||||
|
spin_unlock(&nfs_uuid_lock);
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
if (ro_nf)
|
||||||
|
nfs_to_nfsd_file_put_local(ro_nf);
|
||||||
|
if (rw_nf)
|
||||||
|
nfs_to_nfsd_file_put_local(rw_nf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(nfs_close_local_fh);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The NFS LOCALIO code needs to call into NFSD using various symbols,
|
* The NFS LOCALIO code needs to call into NFSD using various symbols,
|
||||||
* but cannot be statically linked, because that will make the NFS
|
* but cannot be statically linked, because that will make the NFS
|
||||||
|
|
|
@ -77,6 +77,23 @@ struct nfs_lock_context {
|
||||||
struct rcu_head rcu_head;
|
struct rcu_head rcu_head;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct nfs_file_localio {
|
||||||
|
struct nfsd_file __rcu *ro_file;
|
||||||
|
struct nfsd_file __rcu *rw_file;
|
||||||
|
struct list_head list;
|
||||||
|
void __rcu *nfs_uuid; /* opaque pointer to 'nfs_uuid_t' */
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void nfs_localio_file_init(struct nfs_file_localio *nfl)
|
||||||
|
{
|
||||||
|
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
|
||||||
|
nfl->ro_file = NULL;
|
||||||
|
nfl->rw_file = NULL;
|
||||||
|
INIT_LIST_HEAD(&nfl->list);
|
||||||
|
nfl->nfs_uuid = NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
struct nfs4_state;
|
struct nfs4_state;
|
||||||
struct nfs_open_context {
|
struct nfs_open_context {
|
||||||
struct nfs_lock_context lock_context;
|
struct nfs_lock_context lock_context;
|
||||||
|
@ -87,15 +104,16 @@ struct nfs_open_context {
|
||||||
struct nfs4_state *state;
|
struct nfs4_state *state;
|
||||||
fmode_t mode;
|
fmode_t mode;
|
||||||
|
|
||||||
|
int error;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
#define NFS_CONTEXT_BAD (2)
|
#define NFS_CONTEXT_BAD (2)
|
||||||
#define NFS_CONTEXT_UNLOCK (3)
|
#define NFS_CONTEXT_UNLOCK (3)
|
||||||
#define NFS_CONTEXT_FILE_OPEN (4)
|
#define NFS_CONTEXT_FILE_OPEN (4)
|
||||||
int error;
|
|
||||||
|
|
||||||
struct list_head list;
|
|
||||||
struct nfs4_threshold *mdsthreshold;
|
struct nfs4_threshold *mdsthreshold;
|
||||||
|
struct list_head list;
|
||||||
struct rcu_head rcu_head;
|
struct rcu_head rcu_head;
|
||||||
|
struct nfs_file_localio nfl;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nfs_open_dir_context {
|
struct nfs_open_dir_context {
|
||||||
|
|
|
@ -6,10 +6,6 @@
|
||||||
#ifndef __LINUX_NFSLOCALIO_H
|
#ifndef __LINUX_NFSLOCALIO_H
|
||||||
#define __LINUX_NFSLOCALIO_H
|
#define __LINUX_NFSLOCALIO_H
|
||||||
|
|
||||||
|
|
||||||
/* nfsd_file structure is purposely kept opaque to NFS client */
|
|
||||||
struct nfsd_file;
|
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
|
#if IS_ENABLED(CONFIG_NFS_LOCALIO)
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -21,6 +17,7 @@ struct nfsd_file;
|
||||||
#include <net/net_namespace.h>
|
#include <net/net_namespace.h>
|
||||||
|
|
||||||
struct nfs_client;
|
struct nfs_client;
|
||||||
|
struct nfs_file_localio;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Useful to allow a client to negotiate if localio
|
* Useful to allow a client to negotiate if localio
|
||||||
|
@ -52,6 +49,7 @@ extern struct nfsd_file *
|
||||||
nfsd_open_local_fh(struct net *, struct auth_domain *, struct rpc_clnt *,
|
nfsd_open_local_fh(struct net *, struct auth_domain *, struct rpc_clnt *,
|
||||||
const struct cred *, const struct nfs_fh *,
|
const struct cred *, const struct nfs_fh *,
|
||||||
const fmode_t) __must_hold(rcu);
|
const fmode_t) __must_hold(rcu);
|
||||||
|
void nfs_close_local_fh(struct nfs_file_localio *);
|
||||||
|
|
||||||
struct nfsd_localio_operations {
|
struct nfsd_localio_operations {
|
||||||
bool (*nfsd_serv_try_get)(struct net *);
|
bool (*nfsd_serv_try_get)(struct net *);
|
||||||
|
@ -73,7 +71,8 @@ extern const struct nfsd_localio_operations *nfs_to;
|
||||||
|
|
||||||
struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *,
|
struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *,
|
||||||
struct rpc_clnt *, const struct cred *,
|
struct rpc_clnt *, const struct cred *,
|
||||||
const struct nfs_fh *, const fmode_t);
|
const struct nfs_fh *, struct nfs_file_localio *,
|
||||||
|
const fmode_t);
|
||||||
|
|
||||||
static inline void nfs_to_nfsd_net_put(struct net *net)
|
static inline void nfs_to_nfsd_net_put(struct net *net)
|
||||||
{
|
{
|
||||||
|
@ -100,12 +99,15 @@ static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio)
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* CONFIG_NFS_LOCALIO */
|
#else /* CONFIG_NFS_LOCALIO */
|
||||||
|
|
||||||
|
struct nfs_file_localio;
|
||||||
|
static inline void nfs_close_local_fh(struct nfs_file_localio *nfl)
|
||||||
|
{
|
||||||
|
}
|
||||||
static inline void nfsd_localio_ops_init(void)
|
static inline void nfsd_localio_ops_init(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static inline void nfs_to_nfsd_file_put_local(struct nfsd_file *localio)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_NFS_LOCALIO */
|
#endif /* CONFIG_NFS_LOCALIO */
|
||||||
|
|
||||||
#endif /* __LINUX_NFSLOCALIO_H */
|
#endif /* __LINUX_NFSLOCALIO_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue