@@ -661,6 +661,39 @@ static struct shrinker nfsd_file_shrinker = {
661661 .seeks = 1 ,
662662};
663663
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+
664697/**
665698 * nfsd_file_queue_for_close: try to close out any open nfsd_files for an inode
666699 * @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)
688721
689722 rcu_read_lock ();
690723 do {
691- int decrement = 1 ;
692-
693724 nf = rhashtable_lookup (& nfsd_file_rhash_tbl , & key ,
694725 nfsd_file_rhash_params );
695726 if (!nf )
696727 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 );
715729 } while (1 );
716730 rcu_read_unlock ();
717731}
@@ -928,11 +942,8 @@ __nfsd_file_cache_purge(struct net *net)
928942
929943 nf = rhashtable_walk_next (& iter );
930944 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 );
936947 nf = rhashtable_walk_next (& iter );
937948 }
938949
0 commit comments