nfsd: rework hashtable handling in nfsd_do_file_acquire
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>
This commit is contained in:
parent
8d0d254b15
commit
243a526301
@ -1042,9 +1042,10 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|||||||
.need = may_flags & NFSD_FILE_MAY_MASK,
|
.need = may_flags & NFSD_FILE_MAY_MASK,
|
||||||
.net = SVC_NET(rqstp),
|
.net = SVC_NET(rqstp),
|
||||||
};
|
};
|
||||||
struct nfsd_file *nf, *new;
|
bool open_retry = true;
|
||||||
bool retry = true;
|
struct nfsd_file *nf;
|
||||||
__be32 status;
|
__be32 status;
|
||||||
|
int ret;
|
||||||
|
|
||||||
status = fh_verify(rqstp, fhp, S_IFREG,
|
status = fh_verify(rqstp, fhp, S_IFREG,
|
||||||
may_flags|NFSD_MAY_OWNER_OVERRIDE);
|
may_flags|NFSD_MAY_OWNER_OVERRIDE);
|
||||||
@ -1054,35 +1055,33 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|||||||
key.cred = get_current_cred();
|
key.cred = get_current_cred();
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
/* Avoid allocation if the item is already in cache */
|
rcu_read_lock();
|
||||||
nf = rhashtable_lookup_fast(&nfsd_file_rhash_tbl, &key,
|
nf = rhashtable_lookup(&nfsd_file_rhash_tbl, &key,
|
||||||
nfsd_file_rhash_params);
|
nfsd_file_rhash_params);
|
||||||
if (nf)
|
if (nf)
|
||||||
nf = nfsd_file_get(nf);
|
nf = nfsd_file_get(nf);
|
||||||
|
rcu_read_unlock();
|
||||||
if (nf)
|
if (nf)
|
||||||
goto wait_for_construction;
|
goto wait_for_construction;
|
||||||
|
|
||||||
new = nfsd_file_alloc(&key, may_flags);
|
nf = nfsd_file_alloc(&key, may_flags);
|
||||||
if (!new) {
|
if (!nf) {
|
||||||
status = nfserr_jukebox;
|
status = nfserr_jukebox;
|
||||||
goto out_status;
|
goto out_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
nf = rhashtable_lookup_get_insert_key(&nfsd_file_rhash_tbl,
|
ret = rhashtable_lookup_insert_key(&nfsd_file_rhash_tbl,
|
||||||
&key, &new->nf_rhash,
|
&key, &nf->nf_rhash,
|
||||||
nfsd_file_rhash_params);
|
nfsd_file_rhash_params);
|
||||||
if (!nf) {
|
if (likely(ret == 0))
|
||||||
nf = new;
|
|
||||||
goto open_file;
|
goto open_file;
|
||||||
}
|
|
||||||
if (IS_ERR(nf))
|
nfsd_file_slab_free(&nf->nf_rcu);
|
||||||
goto insert_err;
|
if (ret == -EEXIST)
|
||||||
nf = nfsd_file_get(nf);
|
goto retry;
|
||||||
if (nf == NULL) {
|
trace_nfsd_file_insert_err(rqstp, key.inode, may_flags, ret);
|
||||||
nf = new;
|
status = nfserr_jukebox;
|
||||||
goto open_file;
|
goto out_status;
|
||||||
}
|
|
||||||
nfsd_file_slab_free(&new->nf_rcu);
|
|
||||||
|
|
||||||
wait_for_construction:
|
wait_for_construction:
|
||||||
wait_on_bit(&nf->nf_flags, NFSD_FILE_PENDING, TASK_UNINTERRUPTIBLE);
|
wait_on_bit(&nf->nf_flags, NFSD_FILE_PENDING, TASK_UNINTERRUPTIBLE);
|
||||||
@ -1090,11 +1089,11 @@ wait_for_construction:
|
|||||||
/* Did construction of this file fail? */
|
/* Did construction of this file fail? */
|
||||||
if (!test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
|
if (!test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
|
||||||
trace_nfsd_file_cons_err(rqstp, key.inode, may_flags, nf);
|
trace_nfsd_file_cons_err(rqstp, key.inode, may_flags, nf);
|
||||||
if (!retry) {
|
if (!open_retry) {
|
||||||
status = nfserr_jukebox;
|
status = nfserr_jukebox;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
retry = false;
|
open_retry = false;
|
||||||
nfsd_file_put_noref(nf);
|
nfsd_file_put_noref(nf);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
@ -1142,13 +1141,6 @@ open_file:
|
|||||||
smp_mb__after_atomic();
|
smp_mb__after_atomic();
|
||||||
wake_up_bit(&nf->nf_flags, NFSD_FILE_PENDING);
|
wake_up_bit(&nf->nf_flags, NFSD_FILE_PENDING);
|
||||||
goto out;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user