@@ -568,6 +568,53 @@ static void free_cached_dir(struct cached_fid *cfid)
568568 kfree (cfid );
569569}
570570
571+ static int
572+ cifs_cfids_laundromat_thread (void * p )
573+ {
574+ struct cached_fids * cfids = p ;
575+ struct cached_fid * cfid , * q ;
576+ struct list_head entry ;
577+
578+ while (!kthread_should_stop ()) {
579+ ssleep (1 );
580+ INIT_LIST_HEAD (& entry );
581+ if (kthread_should_stop ())
582+ return 0 ;
583+ spin_lock (& cfids -> cfid_list_lock );
584+ list_for_each_entry_safe (cfid , q , & cfids -> entries , entry ) {
585+ if (time_after (jiffies , cfid -> time + HZ * 30 )) {
586+ list_del (& cfid -> entry );
587+ list_add (& cfid -> entry , & entry );
588+ cfids -> num_entries -- ;
589+ }
590+ }
591+ spin_unlock (& cfids -> cfid_list_lock );
592+
593+ list_for_each_entry_safe (cfid , q , & entry , entry ) {
594+ cfid -> on_list = false;
595+ list_del (& cfid -> entry );
596+ /*
597+ * Cancel, and wait for the work to finish in
598+ * case we are racing with it.
599+ */
600+ cancel_work_sync (& cfid -> lease_break );
601+ if (cfid -> has_lease ) {
602+ /*
603+ * We lease has not yet been cancelled from
604+ * the server so we need to drop the reference.
605+ */
606+ spin_lock (& cfids -> cfid_list_lock );
607+ cfid -> has_lease = false;
608+ spin_unlock (& cfids -> cfid_list_lock );
609+ kref_put (& cfid -> refcount , smb2_close_cached_fid );
610+ }
611+ }
612+ }
613+
614+ return 0 ;
615+ }
616+
617+
571618struct cached_fids * init_cached_dirs (void )
572619{
573620 struct cached_fids * cfids ;
@@ -577,6 +624,20 @@ struct cached_fids *init_cached_dirs(void)
577624 return NULL ;
578625 spin_lock_init (& cfids -> cfid_list_lock );
579626 INIT_LIST_HEAD (& cfids -> entries );
627+
628+ /*
629+ * since we're in a cifs function already, we know that
630+ * this will succeed. No need for try_module_get().
631+ */
632+ __module_get (THIS_MODULE );
633+ cfids -> laundromat = kthread_run (cifs_cfids_laundromat_thread ,
634+ cfids , "cifsd-cfid-laundromat" );
635+ if (IS_ERR (cfids -> laundromat )) {
636+ cifs_dbg (VFS , "Failed to start cfids laundromat thread.\n" );
637+ kfree (cfids );
638+ module_put (THIS_MODULE );
639+ return NULL ;
640+ }
580641 return cfids ;
581642}
582643
@@ -589,6 +650,12 @@ void free_cached_dirs(struct cached_fids *cfids)
589650 struct cached_fid * cfid , * q ;
590651 LIST_HEAD (entry );
591652
653+ if (cfids -> laundromat ) {
654+ kthread_stop (cfids -> laundromat );
655+ cfids -> laundromat = NULL ;
656+ module_put (THIS_MODULE );
657+ }
658+
592659 spin_lock (& cfids -> cfid_list_lock );
593660 list_for_each_entry_safe (cfid , q , & cfids -> entries , entry ) {
594661 cfid -> on_list = false;
0 commit comments