diff options
| author | Enzo Matsumiya <ematsumiya@suse.de> | 2025-09-08 15:29:31 -0300 |
|---|---|---|
| committer | Enzo Matsumiya <ematsumiya@suse.de> | 2025-09-08 15:40:47 -0300 |
| commit | 3340c6434cd8928eaef51662f47b1f27d730428c (patch) | |
| tree | 85ce62479562eeb65cb992ef525ff2b4186de3d7 | |
| parent | db28092064f679cdbe1bb0a4228a62918190bf96 (diff) | |
| download | linux-3340c6434cd8928eaef51662f47b1f27d730428c.tar.gz linux-3340c6434cd8928eaef51662f47b1f27d730428c.tar.bz2 linux-3340c6434cd8928eaef51662f47b1f27d730428c.zip | |
smb: client: remove cached_fids->dying list
Since any cleanup is done on laundromat, the dying list can be removed.
- entries stays on the main list until they're schedule for cleanup
(->last_access_time = 1)
- cached_fids->num_entries is decremented only when cfid transitions
from on_list true -> false
cached_fid lifecycle on the list becomes:
- list_add() on find_or_create_cached_dir()
- list_move() to local list on laundromat
- list_del_init() from local list
- list_del() on release callback
Other changes:
- add invalidate_cfid() helper to centralize cfid invalidation criteria
Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
| -rw-r--r-- | fs/smb/client/cached_dir.c | 83 | ||||
| -rw-r--r-- | fs/smb/client/cached_dir.h | 3 |
2 files changed, 28 insertions, 58 deletions
diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c index 8912c27cbc23..af2fe416ddcf 100644 --- a/fs/smb/client/cached_dir.c +++ b/fs/smb/client/cached_dir.c @@ -22,6 +22,18 @@ struct cached_dir_dentry { struct dentry *dentry; }; +static inline void invalidate_cfid(struct cached_fid *cfid, bool force_expire) +{ + if (cfid->on_list) + cfid->cfids->num_entries--; + + /* do not change other fields here! */ + cfid->on_list = false; + cfid->time = 0; + if (force_expire) + cfid->last_access_time = 1; +} + static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, const char *path, bool lookup_only, @@ -437,11 +449,8 @@ smb2_close_cached_fid(struct kref *ref) struct cached_fid *cfid = container_of(ref, struct cached_fid, refcount); spin_lock(&cfid->cfids->cfid_list_lock); - if (cfid->on_list) { - list_del(&cfid->entry); - cfid->on_list = false; - cfid->cfids->num_entries--; - } + list_del(&cfid->entry); + invalidate_cfid(cfid, true); spin_unlock(&cfid->cfids->cfid_list_lock); dput(cfid->dentry); @@ -461,15 +470,13 @@ void drop_cached_dir_by_name(const unsigned int xid, struct cifs_tcon *tcon, cifs_dbg(FYI, "no cached dir found for rmdir(%s)\n", name); return; } + spin_lock(&cfid->cfids->cfid_list_lock); - if (cfid->has_lease) { - cfid->has_lease = false; - kref_put(&cfid->refcount, smb2_close_cached_fid); - } + invalidate_cfid(cfid, false); spin_unlock(&cfid->cfids->cfid_list_lock); - close_cached_dir(cfid); -} + kref_put(&cfid->refcount, smb2_close_cached_fid); +} void close_cached_dir(struct cached_fid *cfid) { @@ -550,25 +557,11 @@ void invalidate_all_cached_dirs(struct cifs_tcon *tcon) if (!cfids) return; - /* - * Mark all the cfids as closed, and move them to the cfids->dying list. - * They'll be cleaned up by laundromat. Take a reference to each cfid - * during this process. - */ + /* Mark all the cfids as closed, and invalidate them for laundromat cleanup. */ spin_lock(&cfids->cfid_list_lock); list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { - list_move(&cfid->entry, &cfids->dying); - cfids->num_entries--; + invalidate_cfid(cfid, true); cfid->is_open = false; - cfid->on_list = false; - if (cfid->has_lease) { - /* - * The lease was never cancelled from the server, - * so steal that reference. - */ - cfid->has_lease = false; - } else - kref_get(&cfid->refcount); } spin_unlock(&cfids->cfid_list_lock); @@ -592,17 +585,13 @@ bool cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]) !memcmp(lease_key, cfid->fid.lease_key, SMB2_LEASE_KEY_SIZE)) { - cfid->has_lease = false; - cfid->time = 0; - /* - * We found a lease, move it to the dying list and schedule immediate - * cleanup on laundromat. + * We found a lease, invalidate cfid and schedule immediate cleanup on + * laundromat. * No need to take a ref here, as we still hold our initial one. */ - list_move(&cfid->entry, &cfids->dying); - cfids->num_entries--; - cfid->on_list = false; + invalidate_cfid(cfid, true); + cfid->has_lease = false; found = true; break; } @@ -667,29 +656,17 @@ static void cfids_laundromat_worker(struct work_struct *work) cfids = container_of(work, struct cached_fids, laundromat_work.work); spin_lock(&cfids->cfid_list_lock); - /* move cfids->dying to the local list */ - list_cut_before(&entry, &cfids->dying, &cfids->dying); - list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { if (cfid->last_access_time && time_after(jiffies, cfid->last_access_time + HZ * dir_cache_timeout)) { - cfid->on_list = false; + invalidate_cfid(cfid, true); list_move(&cfid->entry, &entry); - cfids->num_entries--; - if (cfid->has_lease) { - /* - * Our lease has not yet been cancelled from the - * server. Steal that reference. - */ - cfid->has_lease = false; - } else - kref_get(&cfid->refcount); } } spin_unlock(&cfids->cfid_list_lock); list_for_each_entry_safe(cfid, q, &entry, entry) { - list_del(&cfid->entry); + list_del_init(&cfid->entry); /* * If a cfid reached here, we must cleanup anything unrelated to it, i.e. dentry and @@ -732,7 +709,6 @@ struct cached_fids *init_cached_dirs(void) return NULL; spin_lock_init(&cfids->cfid_list_lock); INIT_LIST_HEAD(&cfids->entries); - INIT_LIST_HEAD(&cfids->dying); INIT_DELAYED_WORK(&cfids->laundromat_work, cfids_laundromat_worker); queue_delayed_work(cfid_put_wq, &cfids->laundromat_work, @@ -757,12 +733,7 @@ void free_cached_dirs(struct cached_fids *cfids) spin_lock(&cfids->cfid_list_lock); list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { - cfid->on_list = false; - cfid->is_open = false; - list_move(&cfid->entry, &entry); - } - list_for_each_entry_safe(cfid, q, &cfids->dying, entry) { - cfid->on_list = false; + invalidate_cfid(cfid, false); cfid->is_open = false; list_move(&cfid->entry, &entry); } diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h index 5e892d53a67a..e549f019b923 100644 --- a/fs/smb/client/cached_dir.h +++ b/fs/smb/client/cached_dir.h @@ -52,12 +52,11 @@ struct cached_fid { struct cached_fids { /* Must be held when: * - accessing the cfids->entries list - * - accessing the cfids->dying list + * - accessing cfids->num_entries */ spinlock_t cfid_list_lock; int num_entries; struct list_head entries; - struct list_head dying; struct delayed_work laundromat_work; }; |
