diff options
| author | Enzo Matsumiya <ematsumiya@suse.de> | 2025-09-15 13:01:36 -0300 |
|---|---|---|
| committer | Enzo Matsumiya <ematsumiya@suse.de> | 2025-09-26 19:06:55 -0300 |
| commit | 4b714a42755b80baff3fefc2705f983423c3edbf (patch) | |
| tree | cc1c3fc8e316e3cfc4368cfaebe69585fbb982f1 | |
| parent | 16542cb85ddb9bccd6d12368484b277edda9180d (diff) | |
| download | linux-4b714a42755b80baff3fefc2705f983423c3edbf.tar.gz linux-4b714a42755b80baff3fefc2705f983423c3edbf.tar.bz2 linux-4b714a42755b80baff3fefc2705f983423c3edbf.zip | |
smb: client: split find_or_create_cached_dir()
This patch splits the function into 2 separate ones; it not only makes
the code clearer, but also allows further and easier enhancements to
both.
So move the initialization part into init_cached_dir() and add
find_cached_dir() for lookups.
Other:
- drop_cached_dir_by_name():
* use find_cached_dir()
* remove no longer used args
Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
| -rw-r--r-- | fs/smb/client/cached_dir.c | 95 | ||||
| -rw-r--r-- | fs/smb/client/cached_dir.h | 5 | ||||
| -rw-r--r-- | fs/smb/client/inode.c | 2 | ||||
| -rw-r--r-- | fs/smb/client/smb2inode.c | 6 |
4 files changed, 53 insertions, 55 deletions
diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c index 8c8ead6e96bd..92898880d20f 100644 --- a/fs/smb/client/cached_dir.c +++ b/fs/smb/client/cached_dir.c @@ -54,10 +54,7 @@ static inline void drop_cfid(struct cached_fid *cfid) } } -static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, - const char *path, - bool lookup_only, - __u32 max_cached_dirs) +static struct cached_fid *find_cached_dir(struct cached_fids *cfids, const char *path) { struct cached_fid *cfid; @@ -71,35 +68,13 @@ static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, if (!cfid_is_valid(cfid)) return NULL; + cfid->last_access_time = jiffies; kref_get(&cfid->refcount); return cfid; } } - if (lookup_only) { - return NULL; - } - if (cfids->num_entries >= max_cached_dirs) { - return NULL; - } - cfid = init_cached_dir(path); - if (cfid == NULL) { - return NULL; - } - cfid->cfids = cfids; - cfids->num_entries++; - list_add(&cfid->entry, &cfids->entries); - kref_get(&cfid->refcount); - /* - * Set @cfid->has_lease to true during construction so that the lease - * reference can be put in cached_dir_lease_break() due to a potential - * lease break right after the request is sent or while @cfid is still - * being cached, or if a reconnection is triggered during construction. - * Concurrent processes won't be to use it yet due to @cfid->time being - * zero. - */ - cfid->has_lease = true; - return cfid; + return NULL; } static struct dentry * @@ -197,9 +172,8 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, ses = tcon->ses; cfids = tcon->cfids; - if (cfids == NULL) + if (!cfids) return -EOPNOTSUPP; - replay_again: /* reinitialize for possible replay */ flags = 0; @@ -214,24 +188,31 @@ replay_again: return -ENOMEM; spin_lock(&cfids->cfid_list_lock); - cfid = find_or_create_cached_dir(cfids, path, lookup_only, tcon->max_cached_dirs); - if (cfid == NULL) { + if (cfids->num_entries >= tcon->max_cached_dirs) { spin_unlock(&cfids->cfid_list_lock); kfree(utf16_path); return -ENOENT; } - /* - * Return cached fid if it is valid (has a lease and has a time). - * Otherwise, it is either a new entry or laundromat worker removed it - * from @cfids->entries. Caller will put last reference if the latter. - */ - if (cfid->has_lease && cfid->time) { - cfid->last_access_time = jiffies; - spin_unlock(&cfids->cfid_list_lock); + + /* find_cached_dir() already checks if has_lease and time, so no need to check here */ + cfid = find_cached_dir(cfids, path); + if (cfid || lookup_only) { *ret_cfid = cfid; + spin_unlock(&cfids->cfid_list_lock); + kfree(utf16_path); + return cfid ? 0 : -ENOENT; + } + + cfid = init_cached_dir(path); + if (!cfid) { + spin_unlock(&cfids->cfid_list_lock); kfree(utf16_path); - return 0; + return -ENOMEM; } + + cfid->cfids = cfids; + cfids->num_entries++; + list_add(&cfid->entry, &cfids->entries); spin_unlock(&cfids->cfid_list_lock); pfid = &cfid->fid; @@ -487,19 +468,22 @@ smb2_close_cached_fid(struct kref *ref) kfree(cfid); } -void drop_cached_dir_by_name(const unsigned int xid, struct cifs_tcon *tcon, - const char *name, struct cifs_sb_info *cifs_sb) +void drop_cached_dir_by_name(struct cached_fids *cfids, const char *name) { - struct cached_fid *cfid = NULL; - int rc; + struct cached_fid *cfid; - rc = open_cached_dir(xid, tcon, name, cifs_sb, true, &cfid); - if (rc) { + if (!cfids) + return; + + cfid = find_cached_dir(cfids, name); + if (!cfid) { cifs_dbg(FYI, "no cached dir found for rmdir(%s)\n", name); return; } drop_cfid(cfid); + + /* put lookup ref */ kref_put(&cfid->refcount, smb2_close_cached_fid); } @@ -609,6 +593,7 @@ static struct cached_fid *init_cached_dir(const char *path) cfid = kzalloc(sizeof(*cfid), GFP_ATOMIC); if (!cfid) return NULL; + cfid->path = kstrdup(path, GFP_ATOMIC); if (!cfid->path) { kfree(cfid); @@ -619,7 +604,23 @@ static struct cached_fid *init_cached_dir(const char *path) INIT_LIST_HEAD(&cfid->dirents.entries); mutex_init(&cfid->dirents.de_mutex); spin_lock_init(&cfid->fid_lock); + + /* this is our ref */ kref_init(&cfid->refcount); + + /* this is caller/lease ref */ + kref_get(&cfid->refcount); + + /* + * Set @cfid->has_lease to true during construction so that the lease + * reference can be put in cached_dir_lease_break() due to a potential + * lease break right after the request is sent or while @cfid is still + * being cached, or if a reconnection is triggered during construction. + * Concurrent processes won't be to use it yet due to @cfid->time being + * zero. + */ + cfid->has_lease = true; + return cfid; } diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h index 47c0404ba84a..4bc93131275e 100644 --- a/fs/smb/client/cached_dir.h +++ b/fs/smb/client/cached_dir.h @@ -79,10 +79,7 @@ extern int open_cached_dir_by_dentry(struct cifs_tcon *tcon, struct dentry *dentry, struct cached_fid **cfid); extern void close_cached_dir(struct cached_fid *cfid); -extern void drop_cached_dir_by_name(const unsigned int xid, - struct cifs_tcon *tcon, - const char *name, - struct cifs_sb_info *cifs_sb); +extern void drop_cached_dir_by_name(struct cached_fids *cfids, const char *name); extern void close_all_cached_dirs(struct cifs_sb_info *cifs_sb); extern void invalidate_all_cached_dirs(struct cached_fids *cfids); extern bool cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]); diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index e80bf55765b6..9344a86f6d46 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -2615,7 +2615,7 @@ unlink_target: * ->i_nlink and then mark it as delete pending. */ if (S_ISDIR(inode->i_mode)) { - drop_cached_dir_by_name(xid, tcon, to_name, cifs_sb); + drop_cached_dir_by_name(tcon->cfids, to_name); spin_lock(&inode->i_lock); i_size_write(inode, 0); clear_nlink(inode); diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c index 7cadc8ca4f55..f462845dd167 100644 --- a/fs/smb/client/smb2inode.c +++ b/fs/smb/client/smb2inode.c @@ -1162,7 +1162,7 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, { struct cifs_open_parms oparms; - drop_cached_dir_by_name(xid, tcon, name, cifs_sb); + drop_cached_dir_by_name(tcon->cfids, name); oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE, FILE_OPEN, CREATE_NOT_FILE, ACL_NO_MODE); return smb2_compound_op(xid, tcon, cifs_sb, @@ -1240,7 +1240,7 @@ int smb2_rename_path(const unsigned int xid, struct cifsFileInfo *cfile; __u32 co = file_create_options(source_dentry); - drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb); + drop_cached_dir_by_name(tcon->cfids, from_name); cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile); int rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, @@ -1522,7 +1522,7 @@ int smb2_rename_pending_delete(const char *full_path, goto out; } - drop_cached_dir_by_name(xid, tcon, full_path, cifs_sb); + drop_cached_dir_by_name(tcon->cfids, full_path); oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, DELETE | FILE_WRITE_ATTRIBUTES, FILE_OPEN, co, ACL_NO_MODE); |
