@@ -661,6 +661,39 @@ static struct shrinker nfsd_file_shrinker = {
661
661
.seeks = 1 ,
662
662
};
663
663
664
+ /**
665
+ * nfsd_file_cond_queue - conditionally unhash and queue a nfsd_file
666
+ * @nf: nfsd_file to attempt to queue
667
+ * @dispose: private list to queue successfully-put objects
668
+ *
669
+ * Unhash an nfsd_file, try to get a reference to it, and then put that
670
+ * reference. If it's the last reference, queue it to the dispose list.
671
+ */
672
+ static void
673
+ nfsd_file_cond_queue (struct nfsd_file * nf , struct list_head * dispose )
674
+ __must_hold (RCU )
675
+ {
676
+ int decrement = 1 ;
677
+
678
+ /* If we raced with someone else unhashing, ignore it */
679
+ if (!nfsd_file_unhash (nf ))
680
+ return ;
681
+
682
+ /* If we can't get a reference, ignore it */
683
+ if (!nfsd_file_get (nf ))
684
+ return ;
685
+
686
+ /* Extra decrement if we remove from the LRU */
687
+ if (nfsd_file_lru_remove (nf ))
688
+ ++ decrement ;
689
+
690
+ /* If refcount goes to 0, then put on the dispose list */
691
+ if (refcount_sub_and_test (decrement , & nf -> nf_ref )) {
692
+ list_add (& nf -> nf_lru , dispose );
693
+ trace_nfsd_file_closing (nf );
694
+ }
695
+ }
696
+
664
697
/**
665
698
* nfsd_file_queue_for_close: try to close out any open nfsd_files for an inode
666
699
* @inode: inode on which to close out nfsd_files
@@ -688,30 +721,11 @@ nfsd_file_queue_for_close(struct inode *inode, struct list_head *dispose)
688
721
689
722
rcu_read_lock ();
690
723
do {
691
- int decrement = 1 ;
692
-
693
724
nf = rhashtable_lookup (& nfsd_file_rhash_tbl , & key ,
694
725
nfsd_file_rhash_params );
695
726
if (!nf )
696
727
break ;
697
-
698
- /* If we raced with someone else unhashing, ignore it */
699
- if (!nfsd_file_unhash (nf ))
700
- continue ;
701
-
702
- /* If we can't get a reference, ignore it */
703
- if (!nfsd_file_get (nf ))
704
- continue ;
705
-
706
- /* Extra decrement if we remove from the LRU */
707
- if (nfsd_file_lru_remove (nf ))
708
- ++ decrement ;
709
-
710
- /* If refcount goes to 0, then put on the dispose list */
711
- if (refcount_sub_and_test (decrement , & nf -> nf_ref )) {
712
- list_add (& nf -> nf_lru , dispose );
713
- trace_nfsd_file_closing (nf );
714
- }
728
+ nfsd_file_cond_queue (nf , dispose );
715
729
} while (1 );
716
730
rcu_read_unlock ();
717
731
}
@@ -928,11 +942,8 @@ __nfsd_file_cache_purge(struct net *net)
928
942
929
943
nf = rhashtable_walk_next (& iter );
930
944
while (!IS_ERR_OR_NULL (nf )) {
931
- if (!net || nf -> nf_net == net ) {
932
- nfsd_file_unhash (nf );
933
- nfsd_file_lru_remove (nf );
934
- list_add (& nf -> nf_lru , & dispose );
935
- }
945
+ if (!net || nf -> nf_net == net )
946
+ nfsd_file_cond_queue (nf , & dispose );
936
947
nf = rhashtable_walk_next (& iter );
937
948
}
938
949
0 commit comments