Skip to content

Commit

Permalink
nfsd: rework hashtable handling in nfsd_do_file_acquire
Browse files Browse the repository at this point in the history
nfsd_file is RCU-freed, so we need to hold the rcu_read_lock long enough
to get a reference after finding it in the hash. Take the
rcu_read_lock() and call rhashtable_lookup directly.

Switch to using rhashtable_lookup_insert_key as well, and use the usual
retry mechanism if we hit an -EEXIST. Rename the "retry" bool to
open_retry, and eliminiate the insert_err goto target.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
  • Loading branch information
Jeff Layton authored and Chuck Lever committed Oct 5, 2022
1 parent 8d0d254 commit 243a526
Showing 1 changed file with 22 additions and 30 deletions.
52 changes: 22 additions & 30 deletions fs/nfsd/filecache.c
Original file line number Diff line number Diff line change
Expand Up @@ -1042,9 +1042,10 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
.need = may_flags & NFSD_FILE_MAY_MASK,
.net = SVC_NET(rqstp),
};
struct nfsd_file *nf, *new;
bool retry = true;
bool open_retry = true;
struct nfsd_file *nf;
__be32 status;
int ret;

status = fh_verify(rqstp, fhp, S_IFREG,
may_flags|NFSD_MAY_OWNER_OVERRIDE);
Expand All @@ -1054,47 +1055,45 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
key.cred = get_current_cred();

retry:
/* Avoid allocation if the item is already in cache */
nf = rhashtable_lookup_fast(&nfsd_file_rhash_tbl, &key,
nfsd_file_rhash_params);
rcu_read_lock();
nf = rhashtable_lookup(&nfsd_file_rhash_tbl, &key,
nfsd_file_rhash_params);
if (nf)
nf = nfsd_file_get(nf);
rcu_read_unlock();
if (nf)
goto wait_for_construction;

new = nfsd_file_alloc(&key, may_flags);
if (!new) {
nf = nfsd_file_alloc(&key, may_flags);
if (!nf) {
status = nfserr_jukebox;
goto out_status;
}

nf = rhashtable_lookup_get_insert_key(&nfsd_file_rhash_tbl,
&key, &new->nf_rhash,
nfsd_file_rhash_params);
if (!nf) {
nf = new;
goto open_file;
}
if (IS_ERR(nf))
goto insert_err;
nf = nfsd_file_get(nf);
if (nf == NULL) {
nf = new;
ret = rhashtable_lookup_insert_key(&nfsd_file_rhash_tbl,
&key, &nf->nf_rhash,
nfsd_file_rhash_params);
if (likely(ret == 0))
goto open_file;
}
nfsd_file_slab_free(&new->nf_rcu);

nfsd_file_slab_free(&nf->nf_rcu);
if (ret == -EEXIST)
goto retry;
trace_nfsd_file_insert_err(rqstp, key.inode, may_flags, ret);
status = nfserr_jukebox;
goto out_status;

wait_for_construction:
wait_on_bit(&nf->nf_flags, NFSD_FILE_PENDING, TASK_UNINTERRUPTIBLE);

/* Did construction of this file fail? */
if (!test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
trace_nfsd_file_cons_err(rqstp, key.inode, may_flags, nf);
if (!retry) {
if (!open_retry) {
status = nfserr_jukebox;
goto out;
}
retry = false;
open_retry = false;
nfsd_file_put_noref(nf);
goto retry;
}
Expand Down Expand Up @@ -1142,13 +1141,6 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
smp_mb__after_atomic();
wake_up_bit(&nf->nf_flags, NFSD_FILE_PENDING);
goto out;

insert_err:
nfsd_file_slab_free(&new->nf_rcu);
trace_nfsd_file_insert_err(rqstp, key.inode, may_flags, PTR_ERR(nf));
nf = NULL;
status = nfserr_jukebox;
goto out_status;
}

/**
Expand Down

0 comments on commit 243a526

Please sign in to comment.