Skip to content

Commit d14de80

Browse files
Ronnie SahlbergSteve French
authored andcommitted
cifs: Add a laundromat thread for cached directories
and drop cached directories after 30 seconds Signed-off-by: Ronnie Sahlberg <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent dfbf0ee commit d14de80

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

fs/smb/client/cached_dir.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
571618
struct 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;

fs/smb/client/cached_dir.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ struct cached_fids {
5757
spinlock_t cfid_list_lock;
5858
int num_entries;
5959
struct list_head entries;
60+
struct task_struct *laundromat;
6061
};
6162

6263
extern struct cached_fids *init_cached_dirs(void);

0 commit comments

Comments
 (0)