@@ -568,6 +568,53 @@ static void free_cached_dir(struct cached_fid *cfid)
568
568
kfree (cfid );
569
569
}
570
570
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
+
571
618
struct cached_fids * init_cached_dirs (void )
572
619
{
573
620
struct cached_fids * cfids ;
@@ -577,6 +624,20 @@ struct cached_fids *init_cached_dirs(void)
577
624
return NULL ;
578
625
spin_lock_init (& cfids -> cfid_list_lock );
579
626
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
+ }
580
641
return cfids ;
581
642
}
582
643
@@ -589,6 +650,12 @@ void free_cached_dirs(struct cached_fids *cfids)
589
650
struct cached_fid * cfid , * q ;
590
651
LIST_HEAD (entry );
591
652
653
+ if (cfids -> laundromat ) {
654
+ kthread_stop (cfids -> laundromat );
655
+ cfids -> laundromat = NULL ;
656
+ module_put (THIS_MODULE );
657
+ }
658
+
592
659
spin_lock (& cfids -> cfid_list_lock );
593
660
list_for_each_entry_safe (cfid , q , & cfids -> entries , entry ) {
594
661
cfid -> on_list = false;
0 commit comments