NFS: Convert lookups of the open context to RCU

Reduce contention on the inode->i_lock by ensuring that we use RCU
when looking up the NFS open context.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
Trond Myklebust
2018-09-02 15:57:01 -04:00
parent 6ba0c4e5bb
commit 0de43976fb
6 changed files with 57 additions and 39 deletions

View File

@@ -1933,23 +1933,41 @@ nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
return ret;
}
static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state)
static struct nfs_open_context *
nfs4_state_find_open_context_mode(struct nfs4_state *state, fmode_t mode)
{
struct nfs_inode *nfsi = NFS_I(state->inode);
struct nfs_open_context *ctx;
spin_lock(&state->inode->i_lock);
list_for_each_entry(ctx, &nfsi->open_files, list) {
rcu_read_lock();
list_for_each_entry_rcu(ctx, &nfsi->open_files, list) {
if (ctx->state != state)
continue;
get_nfs_open_context(ctx);
spin_unlock(&state->inode->i_lock);
if ((ctx->mode & mode) != mode)
continue;
if (!get_nfs_open_context(ctx))
continue;
rcu_read_unlock();
return ctx;
}
spin_unlock(&state->inode->i_lock);
rcu_read_unlock();
return ERR_PTR(-ENOENT);
}
static struct nfs_open_context *
nfs4_state_find_open_context(struct nfs4_state *state)
{
struct nfs_open_context *ctx;
ctx = nfs4_state_find_open_context_mode(state, FMODE_READ|FMODE_WRITE);
if (!IS_ERR(ctx))
return ctx;
ctx = nfs4_state_find_open_context_mode(state, FMODE_WRITE);
if (!IS_ERR(ctx))
return ctx;
return nfs4_state_find_open_context_mode(state, FMODE_READ);
}
static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context *ctx,
struct nfs4_state *state, enum open_claim_type4 claim)
{