Skip to content

Commit 243a526

Browse files
jtlaytonchucklever
authored andcommitted
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>
1 parent 8d0d254 commit 243a526

File tree

1 file changed

+22
-30
lines changed

1 file changed

+22
-30
lines changed

fs/nfsd/filecache.c

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,9 +1042,10 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
10421042
.need = may_flags & NFSD_FILE_MAY_MASK,
10431043
.net = SVC_NET(rqstp),
10441044
};
1045-
struct nfsd_file *nf, *new;
1046-
bool retry = true;
1045+
bool open_retry = true;
1046+
struct nfsd_file *nf;
10471047
__be32 status;
1048+
int ret;
10481049

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

10561057
retry:
1057-
/* Avoid allocation if the item is already in cache */
1058-
nf = rhashtable_lookup_fast(&nfsd_file_rhash_tbl, &key,
1059-
nfsd_file_rhash_params);
1058+
rcu_read_lock();
1059+
nf = rhashtable_lookup(&nfsd_file_rhash_tbl, &key,
1060+
nfsd_file_rhash_params);
10601061
if (nf)
10611062
nf = nfsd_file_get(nf);
1063+
rcu_read_unlock();
10621064
if (nf)
10631065
goto wait_for_construction;
10641066

1065-
new = nfsd_file_alloc(&key, may_flags);
1066-
if (!new) {
1067+
nf = nfsd_file_alloc(&key, may_flags);
1068+
if (!nf) {
10671069
status = nfserr_jukebox;
10681070
goto out_status;
10691071
}
10701072

1071-
nf = rhashtable_lookup_get_insert_key(&nfsd_file_rhash_tbl,
1072-
&key, &new->nf_rhash,
1073-
nfsd_file_rhash_params);
1074-
if (!nf) {
1075-
nf = new;
1076-
goto open_file;
1077-
}
1078-
if (IS_ERR(nf))
1079-
goto insert_err;
1080-
nf = nfsd_file_get(nf);
1081-
if (nf == NULL) {
1082-
nf = new;
1073+
ret = rhashtable_lookup_insert_key(&nfsd_file_rhash_tbl,
1074+
&key, &nf->nf_rhash,
1075+
nfsd_file_rhash_params);
1076+
if (likely(ret == 0))
10831077
goto open_file;
1084-
}
1085-
nfsd_file_slab_free(&new->nf_rcu);
1078+
1079+
nfsd_file_slab_free(&nf->nf_rcu);
1080+
if (ret == -EEXIST)
1081+
goto retry;
1082+
trace_nfsd_file_insert_err(rqstp, key.inode, may_flags, ret);
1083+
status = nfserr_jukebox;
1084+
goto out_status;
10861085

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

10901089
/* Did construction of this file fail? */
10911090
if (!test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
10921091
trace_nfsd_file_cons_err(rqstp, key.inode, may_flags, nf);
1093-
if (!retry) {
1092+
if (!open_retry) {
10941093
status = nfserr_jukebox;
10951094
goto out;
10961095
}
1097-
retry = false;
1096+
open_retry = false;
10981097
nfsd_file_put_noref(nf);
10991098
goto retry;
11001099
}
@@ -1142,13 +1141,6 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
11421141
smp_mb__after_atomic();
11431142
wake_up_bit(&nf->nf_flags, NFSD_FILE_PENDING);
11441143
goto out;
1145-
1146-
insert_err:
1147-
nfsd_file_slab_free(&new->nf_rcu);
1148-
trace_nfsd_file_insert_err(rqstp, key.inode, may_flags, PTR_ERR(nf));
1149-
nf = NULL;
1150-
status = nfserr_jukebox;
1151-
goto out_status;
11521144
}
11531145

11541146
/**

0 commit comments

Comments
 (0)