diff options
| author | Enzo Matsumiya <ematsumiya@suse.de> | 2025-09-24 19:38:17 -0300 |
|---|---|---|
| committer | Enzo Matsumiya <ematsumiya@suse.de> | 2025-10-07 10:30:17 -0300 |
| commit | 35a67a33bbcb95654d0056f9a95c1b93c397da6f (patch) | |
| tree | bde1953ee624fb80abfc92753d22c4a416858065 | |
| parent | 070411753afc005251f8cfc6eef26c6f3fec565c (diff) | |
| download | linux-35a67a33bbcb95654d0056f9a95c1b93c397da6f.tar.gz linux-35a67a33bbcb95654d0056f9a95c1b93c397da6f.tar.bz2 linux-35a67a33bbcb95654d0056f9a95c1b93c397da6f.zip | |
smb: client: merge {close,invalidate}_all_cached_dirs()
close_all_cached_dirs(), invalidate_all_cached_dirs() and
free_cached_dirs() have become too similar now, merge their
functionality in a single static invalidate_all_cfids() function.
This also allows removing free_cached_dirs() altogether as it only
requires cancelling the work afterwards (done directly in
tconInfoFree()).
Other changes:
- remove struct cached_dir_dentry
Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
| -rw-r--r-- | fs/smb/client/cached_dir.c | 113 | ||||
| -rw-r--r-- | fs/smb/client/cached_dir.h | 4 | ||||
| -rw-r--r-- | fs/smb/client/cifsfs.c | 2 | ||||
| -rw-r--r-- | fs/smb/client/file.c | 2 | ||||
| -rw-r--r-- | fs/smb/client/misc.c | 9 | ||||
| -rw-r--r-- | fs/smb/client/smb2pdu.c | 2 |
6 files changed, 36 insertions, 96 deletions
diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c index f72890786423..e86c86643379 100644 --- a/fs/smb/client/cached_dir.c +++ b/fs/smb/client/cached_dir.c @@ -16,11 +16,6 @@ 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); -struct cached_dir_dentry { - struct list_head entry; - struct dentry *dentry; -}; - static inline void invalidate_cfid(struct cached_fid *cfid) { /* callers must hold the list lock and do any list operations (del/move) themselves */ @@ -506,6 +501,27 @@ void close_cached_dir(struct cached_fid *cfid) kref_put(&cfid->refcount, smb2_close_cached_fid); } +static void invalidate_all_cfids(struct cached_fids *cfids, bool closed) +{ + struct cached_fid *cfid, *q; + + if (!cfids) + return; + + /* 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) { + invalidate_cfid(cfid); + cfid->has_lease = false; + if (closed) + cfid->is_open = false; + } + spin_unlock(&cfids->cfid_list_lock); + + /* run laundromat unconditionally now as there might have been previously queued work */ + mod_delayed_work(cfid_put_wq, &cfids->laundromat_work, 0); +} + /* * Called from cifs_kill_sb when we unmount a share */ @@ -513,12 +529,8 @@ void close_all_cached_dirs(struct cifs_sb_info *cifs_sb) { struct rb_root *root = &cifs_sb->tlink_tree; struct rb_node *node; - struct cached_fid *cfid; struct cifs_tcon *tcon; struct tcon_link *tlink; - struct cached_fids *cfids; - struct cached_dir_dentry *tmp_list, *q; - LIST_HEAD(entry); spin_lock(&cifs_sb->tlink_tree_lock); for (node = rb_first(root); node; node = rb_next(node)) { @@ -526,45 +538,11 @@ void close_all_cached_dirs(struct cifs_sb_info *cifs_sb) tcon = tlink_tcon(tlink); if (IS_ERR(tcon)) continue; - cfids = tcon->cfids; - if (cfids == NULL) - continue; - spin_lock(&cfids->cfid_list_lock); - list_for_each_entry(cfid, &cfids->entries, entry) { - invalidate_cfid(cfid); - - tmp_list = kmalloc(sizeof(*tmp_list), GFP_ATOMIC); - if (tmp_list == NULL) { - /* - * If the malloc() fails, we won't drop all - * dentries, and unmounting is likely to trigger - * a 'Dentry still in use' error. - */ - cifs_tcon_dbg(VFS, "Out of memory while dropping dentries\n"); - spin_unlock(&cfids->cfid_list_lock); - spin_unlock(&cifs_sb->tlink_tree_lock); - goto done; - } - - tmp_list->dentry = cfid->dentry; - cfid->dentry = NULL; - list_add_tail(&tmp_list->entry, &entry); - } - spin_unlock(&cfids->cfid_list_lock); - - /* run laundromat now as it might not have been queued */ - mod_delayed_work(cfid_put_wq, &cfids->laundromat_work, 0); + invalidate_all_cfids(tcon->cfids, false); } spin_unlock(&cifs_sb->tlink_tree_lock); -done: - list_for_each_entry_safe(tmp_list, q, &entry, entry) { - list_del(&tmp_list->entry); - dput(tmp_list->dentry); - kfree(tmp_list); - } - /* Flush any pending work that will drop dentries */ flush_workqueue(cfid_put_wq); } @@ -573,24 +551,12 @@ done: * Invalidate all cached dirs when a TCON has been reset * due to a session loss. */ -void invalidate_all_cached_dirs(struct cifs_tcon *tcon) +void invalidate_all_cached_dirs(struct cached_fids *cfids) { - struct cached_fids *cfids = tcon->cfids; - struct cached_fid *cfid; - if (!cfids) return; - /* mark all the cfids as closed and invalidate them for laundromat cleanup */ - spin_lock(&cfids->cfid_list_lock); - list_for_each_entry(cfid, &cfids->entries, entry) { - invalidate_cfid(cfid); - cfid->is_open = false; - } - spin_unlock(&cfids->cfid_list_lock); - - /* run laundromat unconditionally now as there might have been previously queued work */ - mod_delayed_work(cfid_put_wq, &cfids->laundromat_work, 0); + invalidate_all_cfids(cfids, true); flush_delayed_work(&cfids->laundromat_work); } @@ -738,34 +704,3 @@ struct cached_fids *init_cached_dirs(void) return cfids; } - -/* - * Called from tconInfoFree when we are tearing down the tcon. - * There are no active users or open files/directories at this point. - */ -void free_cached_dirs(struct cached_fids *cfids) -{ - struct cached_fid *cfid, *q; - LIST_HEAD(entry); - - if (cfids == NULL) - return; - - cancel_delayed_work_sync(&cfids->laundromat_work); - - spin_lock(&cfids->cfid_list_lock); - list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { - invalidate_cfid(cfid); - cfid->is_open = false; - list_move(&cfid->entry, &entry); - } - spin_unlock(&cfids->cfid_list_lock); - - list_for_each_entry_safe(cfid, q, &entry, entry) { - list_del(&cfid->entry); - drop_cfid(cfid); - free_cached_dir(cfid); - } - - kfree(cfids); -} diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h index f9cb94c7f8d2..be115116c33c 100644 --- a/fs/smb/client/cached_dir.h +++ b/fs/smb/client/cached_dir.h @@ -78,7 +78,6 @@ static inline bool is_valid_cached_dir(struct cached_fid *cfid) /* Module-wide directory cache accounting (defined in cifsfs.c) */ extern atomic64_t cifs_dircache_bytes_used; /* bytes across all mounts */ extern struct cached_fids *init_cached_dirs(void); -extern void free_cached_dirs(struct cached_fids *cfids); extern int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, const char *path, struct cifs_sb_info *cifs_sb, @@ -92,7 +91,6 @@ extern void drop_cached_dir_by_name(const unsigned int xid, const char *name, struct cifs_sb_info *cifs_sb); extern void close_all_cached_dirs(struct cifs_sb_info *cifs_sb); -extern void invalidate_all_cached_dirs(struct cifs_tcon *tcon); +extern void invalidate_all_cached_dirs(struct cached_fids *cfids); extern bool cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]); - #endif /* _CACHED_DIR_H */ diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index 1775c2b7528f..54a19bfc6170 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -140,7 +140,7 @@ static void cifs_drop_all_dir_caches(void) if (cifs_ses_exiting(ses)) continue; list_for_each_entry(tcon, &ses->tcon_list, tcon_list) - invalidate_all_cached_dirs(tcon); + invalidate_all_cached_dirs(tcon->cfids); } } spin_unlock(&cifs_tcp_ses_lock); diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index a5ed742afa00..0731d2369ab6 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -394,7 +394,7 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon) } spin_unlock(&tcon->open_file_lock); - invalidate_all_cached_dirs(tcon); + invalidate_all_cached_dirs(tcon->cfids); spin_lock(&tcon->tc_lock); if (tcon->status == TID_IN_FILES_INVALIDATE) tcon->status = TID_NEED_TCON; diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index dda6dece802a..0c6da3d7047f 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -169,7 +169,14 @@ tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace) return; } trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, trace); - free_cached_dirs(tcon->cfids); + + if (tcon->cfids) { + invalidate_all_cached_dirs(tcon->cfids); + cancel_delayed_work_sync(&tcon->cfids->laundromat_work); + kfree(tcon->cfids); + tcon->cfids = NULL; + } + atomic_dec(&tconInfoAllocCount); kfree(tcon->nativeFileSystem); kfree_sensitive(tcon->password); diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 42e2d4ea344d..acbfbb40932a 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -2197,7 +2197,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon) } spin_unlock(&ses->chan_lock); - invalidate_all_cached_dirs(tcon); + invalidate_all_cached_dirs(tcon->cfids); rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, server, (void **) &req, |
