Skip to content

Commit dc91485

Browse files
committed
Merge tag 'nfsd-6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
Pull more nfsd updates from Chuck Lever: - filecache code clean-ups * tag 'nfsd-6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: nfsd: rework hashtable handling in nfsd_do_file_acquire nfsd: fix nfsd_file_unhash_and_dispose
2 parents f721d24 + 243a526 commit dc91485

File tree

1 file changed

+29
-59
lines changed

1 file changed

+29
-59
lines changed

fs/nfsd/filecache.c

Lines changed: 29 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -405,22 +405,15 @@ nfsd_file_unhash(struct nfsd_file *nf)
405405
return false;
406406
}
407407

408-
/*
409-
* Return true if the file was unhashed.
410-
*/
411-
static bool
408+
static void
412409
nfsd_file_unhash_and_dispose(struct nfsd_file *nf, struct list_head *dispose)
413410
{
414411
trace_nfsd_file_unhash_and_dispose(nf);
415-
if (!nfsd_file_unhash(nf))
416-
return false;
417-
/* keep final reference for nfsd_file_lru_dispose */
418-
if (refcount_dec_not_one(&nf->nf_ref))
419-
return true;
420-
421-
nfsd_file_lru_remove(nf);
422-
list_add(&nf->nf_lru, dispose);
423-
return true;
412+
if (nfsd_file_unhash(nf)) {
413+
/* caller must call nfsd_file_dispose_list() later */
414+
nfsd_file_lru_remove(nf);
415+
list_add(&nf->nf_lru, dispose);
416+
}
424417
}
425418

426419
static void
@@ -562,8 +555,6 @@ nfsd_file_dispose_list_delayed(struct list_head *dispose)
562555
* @lock: LRU list lock (unused)
563556
* @arg: dispose list
564557
*
565-
* Note this can deadlock with nfsd_file_cache_purge.
566-
*
567558
* Return values:
568559
* %LRU_REMOVED: @item was removed from the LRU
569560
* %LRU_ROTATE: @item is to be moved to the LRU tail
@@ -748,8 +739,6 @@ nfsd_file_close_inode(struct inode *inode)
748739
*
749740
* Walk the LRU list and close any entries that have not been used since
750741
* the last scan.
751-
*
752-
* Note this can deadlock with nfsd_file_cache_purge.
753742
*/
754743
static void
755744
nfsd_file_delayed_close(struct work_struct *work)
@@ -891,16 +880,12 @@ nfsd_file_cache_init(void)
891880
goto out;
892881
}
893882

894-
/*
895-
* Note this can deadlock with nfsd_file_lru_cb.
896-
*/
897883
static void
898884
__nfsd_file_cache_purge(struct net *net)
899885
{
900886
struct rhashtable_iter iter;
901887
struct nfsd_file *nf;
902888
LIST_HEAD(dispose);
903-
bool del;
904889

905890
rhashtable_walk_enter(&nfsd_file_rhash_tbl, &iter);
906891
do {
@@ -910,14 +895,7 @@ __nfsd_file_cache_purge(struct net *net)
910895
while (!IS_ERR_OR_NULL(nf)) {
911896
if (net && nf->nf_net != net)
912897
continue;
913-
del = nfsd_file_unhash_and_dispose(nf, &dispose);
914-
915-
/*
916-
* Deadlock detected! Something marked this entry as
917-
* unhased, but hasn't removed it from the hash list.
918-
*/
919-
WARN_ON_ONCE(!del);
920-
898+
nfsd_file_unhash_and_dispose(nf, &dispose);
921899
nf = rhashtable_walk_next(&iter);
922900
}
923901

@@ -1064,9 +1042,10 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
10641042
.need = may_flags & NFSD_FILE_MAY_MASK,
10651043
.net = SVC_NET(rqstp),
10661044
};
1067-
struct nfsd_file *nf, *new;
1068-
bool retry = true;
1045+
bool open_retry = true;
1046+
struct nfsd_file *nf;
10691047
__be32 status;
1048+
int ret;
10701049

10711050
status = fh_verify(rqstp, fhp, S_IFREG,
10721051
may_flags|NFSD_MAY_OWNER_OVERRIDE);
@@ -1076,47 +1055,45 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
10761055
key.cred = get_current_cred();
10771056

10781057
retry:
1079-
/* Avoid allocation if the item is already in cache */
1080-
nf = rhashtable_lookup_fast(&nfsd_file_rhash_tbl, &key,
1081-
nfsd_file_rhash_params);
1058+
rcu_read_lock();
1059+
nf = rhashtable_lookup(&nfsd_file_rhash_tbl, &key,
1060+
nfsd_file_rhash_params);
10821061
if (nf)
10831062
nf = nfsd_file_get(nf);
1063+
rcu_read_unlock();
10841064
if (nf)
10851065
goto wait_for_construction;
10861066

1087-
new = nfsd_file_alloc(&key, may_flags);
1088-
if (!new) {
1067+
nf = nfsd_file_alloc(&key, may_flags);
1068+
if (!nf) {
10891069
status = nfserr_jukebox;
10901070
goto out_status;
10911071
}
10921072

1093-
nf = rhashtable_lookup_get_insert_key(&nfsd_file_rhash_tbl,
1094-
&key, &new->nf_rhash,
1095-
nfsd_file_rhash_params);
1096-
if (!nf) {
1097-
nf = new;
1098-
goto open_file;
1099-
}
1100-
if (IS_ERR(nf))
1101-
goto insert_err;
1102-
nf = nfsd_file_get(nf);
1103-
if (nf == NULL) {
1104-
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))
11051077
goto open_file;
1106-
}
1107-
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;
11081085

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

11121089
/* Did construction of this file fail? */
11131090
if (!test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
11141091
trace_nfsd_file_cons_err(rqstp, key.inode, may_flags, nf);
1115-
if (!retry) {
1092+
if (!open_retry) {
11161093
status = nfserr_jukebox;
11171094
goto out;
11181095
}
1119-
retry = false;
1096+
open_retry = false;
11201097
nfsd_file_put_noref(nf);
11211098
goto retry;
11221099
}
@@ -1164,13 +1141,6 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
11641141
smp_mb__after_atomic();
11651142
wake_up_bit(&nf->nf_flags, NFSD_FILE_PENDING);
11661143
goto out;
1167-
1168-
insert_err:
1169-
nfsd_file_slab_free(&new->nf_rcu);
1170-
trace_nfsd_file_insert_err(rqstp, key.inode, may_flags, PTR_ERR(nf));
1171-
nf = NULL;
1172-
status = nfserr_jukebox;
1173-
goto out_status;
11741144
}
11751145

11761146
/**

0 commit comments

Comments
 (0)