@@ -405,22 +405,15 @@ nfsd_file_unhash(struct nfsd_file *nf)
405
405
return false;
406
406
}
407
407
408
- /*
409
- * Return true if the file was unhashed.
410
- */
411
- static bool
408
+ static void
412
409
nfsd_file_unhash_and_dispose (struct nfsd_file * nf , struct list_head * dispose )
413
410
{
414
411
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
+ }
424
417
}
425
418
426
419
static void
@@ -562,8 +555,6 @@ nfsd_file_dispose_list_delayed(struct list_head *dispose)
562
555
* @lock: LRU list lock (unused)
563
556
* @arg: dispose list
564
557
*
565
- * Note this can deadlock with nfsd_file_cache_purge.
566
- *
567
558
* Return values:
568
559
* %LRU_REMOVED: @item was removed from the LRU
569
560
* %LRU_ROTATE: @item is to be moved to the LRU tail
@@ -748,8 +739,6 @@ nfsd_file_close_inode(struct inode *inode)
748
739
*
749
740
* Walk the LRU list and close any entries that have not been used since
750
741
* the last scan.
751
- *
752
- * Note this can deadlock with nfsd_file_cache_purge.
753
742
*/
754
743
static void
755
744
nfsd_file_delayed_close (struct work_struct * work )
@@ -891,16 +880,12 @@ nfsd_file_cache_init(void)
891
880
goto out ;
892
881
}
893
882
894
- /*
895
- * Note this can deadlock with nfsd_file_lru_cb.
896
- */
897
883
static void
898
884
__nfsd_file_cache_purge (struct net * net )
899
885
{
900
886
struct rhashtable_iter iter ;
901
887
struct nfsd_file * nf ;
902
888
LIST_HEAD (dispose );
903
- bool del ;
904
889
905
890
rhashtable_walk_enter (& nfsd_file_rhash_tbl , & iter );
906
891
do {
@@ -910,14 +895,7 @@ __nfsd_file_cache_purge(struct net *net)
910
895
while (!IS_ERR_OR_NULL (nf )) {
911
896
if (net && nf -> nf_net != net )
912
897
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 );
921
899
nf = rhashtable_walk_next (& iter );
922
900
}
923
901
@@ -1064,9 +1042,10 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
1064
1042
.need = may_flags & NFSD_FILE_MAY_MASK ,
1065
1043
.net = SVC_NET (rqstp ),
1066
1044
};
1067
- struct nfsd_file * nf , * new ;
1068
- bool retry = true ;
1045
+ bool open_retry = true ;
1046
+ struct nfsd_file * nf ;
1069
1047
__be32 status ;
1048
+ int ret ;
1070
1049
1071
1050
status = fh_verify (rqstp , fhp , S_IFREG ,
1072
1051
may_flags |NFSD_MAY_OWNER_OVERRIDE );
@@ -1076,47 +1055,45 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
1076
1055
key .cred = get_current_cred ();
1077
1056
1078
1057
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 );
1082
1061
if (nf )
1083
1062
nf = nfsd_file_get (nf );
1063
+ rcu_read_unlock ();
1084
1064
if (nf )
1085
1065
goto wait_for_construction ;
1086
1066
1087
- new = nfsd_file_alloc (& key , may_flags );
1088
- if (!new ) {
1067
+ nf = nfsd_file_alloc (& key , may_flags );
1068
+ if (!nf ) {
1089
1069
status = nfserr_jukebox ;
1090
1070
goto out_status ;
1091
1071
}
1092
1072
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 ))
1105
1077
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 ;
1108
1085
1109
1086
wait_for_construction :
1110
1087
wait_on_bit (& nf -> nf_flags , NFSD_FILE_PENDING , TASK_UNINTERRUPTIBLE );
1111
1088
1112
1089
/* Did construction of this file fail? */
1113
1090
if (!test_bit (NFSD_FILE_HASHED , & nf -> nf_flags )) {
1114
1091
trace_nfsd_file_cons_err (rqstp , key .inode , may_flags , nf );
1115
- if (!retry ) {
1092
+ if (!open_retry ) {
1116
1093
status = nfserr_jukebox ;
1117
1094
goto out ;
1118
1095
}
1119
- retry = false;
1096
+ open_retry = false;
1120
1097
nfsd_file_put_noref (nf );
1121
1098
goto retry ;
1122
1099
}
@@ -1164,13 +1141,6 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
1164
1141
smp_mb__after_atomic ();
1165
1142
wake_up_bit (& nf -> nf_flags , NFSD_FILE_PENDING );
1166
1143
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 ;
1174
1144
}
1175
1145
1176
1146
/**
0 commit comments