Skip to content

Commit

Permalink
smb: client: make laundromat a delayed worker
Browse files Browse the repository at this point in the history
By having laundromat kthread processing cached directories on every
second turned out to be overkill, especially when having multiple SMB
mounts.

Relax it by using a delayed worker instead that gets scheduled on
every @dir_cache_timeout (default=30) seconds per tcon.

This also fixes the 1s delay when tearing down tcon.

Signed-off-by: Paulo Alcantara (SUSE) <[email protected]>
Reviewed-by: Shyam Prasad N <[email protected]>
Signed-off-by: Steve French <[email protected]>
  • Loading branch information
pcacjr authored and Steve French committed Oct 12, 2023
1 parent 94f6f05 commit e95f3f7
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 55 deletions.
89 changes: 35 additions & 54 deletions fs/smb/client/cached_dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
static struct cached_fid *init_cached_dir(const char *path);
static void free_cached_dir(struct cached_fid *cfid);
static void smb2_close_cached_fid(struct kref *ref);
static void cfids_laundromat_worker(struct work_struct *work);

static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
const char *path,
Expand Down Expand Up @@ -572,53 +573,46 @@ static void free_cached_dir(struct cached_fid *cfid)
kfree(cfid);
}

static int
cifs_cfids_laundromat_thread(void *p)
static void cfids_laundromat_worker(struct work_struct *work)
{
struct cached_fids *cfids = p;
struct cached_fids *cfids;
struct cached_fid *cfid, *q;
struct list_head entry;
LIST_HEAD(entry);

while (!kthread_should_stop()) {
ssleep(1);
INIT_LIST_HEAD(&entry);
if (kthread_should_stop())
return 0;
spin_lock(&cfids->cfid_list_lock);
list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
if (time_after(jiffies, cfid->time + HZ * dir_cache_timeout)) {
list_del(&cfid->entry);
list_add(&cfid->entry, &entry);
cfids->num_entries--;
}
cfids = container_of(work, struct cached_fids, laundromat_work.work);

spin_lock(&cfids->cfid_list_lock);
list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
if (time_after(jiffies, cfid->time + HZ * dir_cache_timeout)) {
list_move(&cfid->entry, &entry);
cfids->num_entries--;
}
spin_unlock(&cfids->cfid_list_lock);
}
spin_unlock(&cfids->cfid_list_lock);

list_for_each_entry_safe(cfid, q, &entry, entry) {
cfid->on_list = false;
list_del(&cfid->entry);
list_for_each_entry_safe(cfid, q, &entry, entry) {
cfid->on_list = false;
list_del(&cfid->entry);
/*
* Cancel and wait for the work to finish in case we are racing
* with it.
*/
cancel_work_sync(&cfid->lease_break);
if (cfid->has_lease) {
/*
* Cancel, and wait for the work to finish in
* case we are racing with it.
* Our lease has not yet been cancelled from the server
* so we need to drop the reference.
*/
cancel_work_sync(&cfid->lease_break);
if (cfid->has_lease) {
/*
* We lease has not yet been cancelled from
* the server so we need to drop the reference.
*/
spin_lock(&cfids->cfid_list_lock);
cfid->has_lease = false;
spin_unlock(&cfids->cfid_list_lock);
kref_put(&cfid->refcount, smb2_close_cached_fid);
}
spin_lock(&cfids->cfid_list_lock);
cfid->has_lease = false;
spin_unlock(&cfids->cfid_list_lock);
kref_put(&cfid->refcount, smb2_close_cached_fid);
}
}

return 0;
queue_delayed_work(cifsiod_wq, &cfids->laundromat_work,
dir_cache_timeout * HZ);
}


struct cached_fids *init_cached_dirs(void)
{
struct cached_fids *cfids;
Expand All @@ -629,19 +623,10 @@ struct cached_fids *init_cached_dirs(void)
spin_lock_init(&cfids->cfid_list_lock);
INIT_LIST_HEAD(&cfids->entries);

/*
* since we're in a cifs function already, we know that
* this will succeed. No need for try_module_get().
*/
__module_get(THIS_MODULE);
cfids->laundromat = kthread_run(cifs_cfids_laundromat_thread,
cfids, "cifsd-cfid-laundromat");
if (IS_ERR(cfids->laundromat)) {
cifs_dbg(VFS, "Failed to start cfids laundromat thread.\n");
kfree(cfids);
module_put(THIS_MODULE);
return NULL;
}
INIT_DELAYED_WORK(&cfids->laundromat_work, cfids_laundromat_worker);
queue_delayed_work(cifsiod_wq, &cfids->laundromat_work,
dir_cache_timeout * HZ);

return cfids;
}

Expand All @@ -657,11 +642,7 @@ void free_cached_dirs(struct cached_fids *cfids)
if (cfids == NULL)
return;

if (cfids->laundromat) {
kthread_stop(cfids->laundromat);
cfids->laundromat = NULL;
module_put(THIS_MODULE);
}
cancel_delayed_work_sync(&cfids->laundromat_work);

spin_lock(&cfids->cfid_list_lock);
list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
Expand Down
2 changes: 1 addition & 1 deletion fs/smb/client/cached_dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ struct cached_fids {
spinlock_t cfid_list_lock;
int num_entries;
struct list_head entries;
struct task_struct *laundromat;
struct delayed_work laundromat_work;
};

extern struct cached_fids *init_cached_dirs(void);
Expand Down

0 comments on commit e95f3f7

Please sign in to comment.