diff options
| author | Enzo Matsumiya <ematsumiya@suse.de> | 2025-09-08 18:11:16 -0300 |
|---|---|---|
| committer | Enzo Matsumiya <ematsumiya@suse.de> | 2025-09-12 17:27:38 -0300 |
| commit | d5db635bbcf732be94e0808f74e00a9476509ed0 (patch) | |
| tree | 3b8212b7f2e1b1229d0a2a378e2d4ff4bd76a862 | |
| parent | da0242dd604d645a0622dcfab75573e29c986d68 (diff) | |
| download | linux-d5db635bbcf732be94e0808f74e00a9476509ed0.tar.gz linux-d5db635bbcf732be94e0808f74e00a9476509ed0.tar.bz2 linux-d5db635bbcf732be94e0808f74e00a9476509ed0.zip | |
smb: client: add is_dir argument to query_path_info
When we have an inode on upper levels, pass is_dir down to
smb2_query_path_info() so we can lookup for a cached dir there.
Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
| -rw-r--r-- | fs/smb/client/cifsglob.h | 2 | ||||
| -rw-r--r-- | fs/smb/client/inode.c | 9 | ||||
| -rw-r--r-- | fs/smb/client/smb1ops.c | 4 | ||||
| -rw-r--r-- | fs/smb/client/smb2inode.c | 18 | ||||
| -rw-r--r-- | fs/smb/client/smb2proto.h | 2 |
5 files changed, 21 insertions, 14 deletions
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 9a86efddc3c4..08c8131c8018 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -401,7 +401,7 @@ struct smb_version_operations { struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, - struct cifs_open_info_data *data); + struct cifs_open_info_data *data, bool is_dir); /* query file data from the server */ int (*query_file_info)(const unsigned int xid, struct cifs_tcon *tcon, struct cifsFileInfo *cfile, struct cifs_open_info_data *data); diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index f2eff1138ed0..35c5557d5ea1 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -1283,8 +1283,13 @@ static int cifs_get_fattr(struct cifs_open_info_data *data, */ if (!data) { + bool is_dir = false; + + if (inode && *inode) + is_dir = S_ISDIR((*inode)->i_mode); + rc = server->ops->query_path_info(xid, tcon, cifs_sb, - full_path, &tmp_data); + full_path, &tmp_data, is_dir); data = &tmp_data; } @@ -1470,7 +1475,7 @@ static int smb311_posix_get_fattr(struct cifs_open_info_data *data, */ if (!data) { rc = server->ops->query_path_info(xid, tcon, cifs_sb, - full_path, &tmp_data); + full_path, &tmp_data, false); data = &tmp_data; } diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c index a02d41d1ce4a..d964bc9c2823 100644 --- a/fs/smb/client/smb1ops.c +++ b/fs/smb/client/smb1ops.c @@ -543,7 +543,7 @@ static int cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, - struct cifs_open_info_data *data) + struct cifs_open_info_data *data, bool is_dir) { int rc = -EOPNOTSUPP; FILE_ALL_INFO fi = {}; @@ -934,7 +934,7 @@ smb_set_file_info(struct inode *inode, const char *full_path, if (!(tcon->ses->capabilities & CAP_NT_SMBS) && (!buf->CreationTime || !buf->LastAccessTime || !buf->LastWriteTime || !buf->ChangeTime)) { - rc = cifs_query_path_info(xid, tcon, cifs_sb, full_path, &query_data); + rc = cifs_query_path_info(xid, tcon, cifs_sb, full_path, &query_data, false); if (rc) { if (open_file) { cifsFileInfo_put(open_file); diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c index 192645a891c8..6127e659cb6a 100644 --- a/fs/smb/client/smb2inode.c +++ b/fs/smb/client/smb2inode.c @@ -940,10 +940,9 @@ int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, - struct cifs_open_info_data *data) + struct cifs_open_info_data *data, bool is_dir) { struct kvec in_iov[3], out_iov[5] = {}; - struct cached_fid *cfid = NULL; struct cifs_open_parms oparms; struct cifsFileInfo *cfile; __u32 create_options = 0; @@ -964,19 +963,22 @@ int smb2_query_path_info(const unsigned int xid, * is fast enough (always using the compounded version). */ if (!tcon->posix_extensions) { + struct cached_fid *cfid = NULL; + rc = -ENOENT; if (!*full_path) rc = open_cached_dir(xid, tcon, full_path, cifs_sb, &cfid); + else if (is_dir) + cfid = find_cached_dir(tcon->cfids, full_path, CFID_LOOKUP_PATH); + + if (cfid) { + rc = 0; - /* If it is a root and its handle is cached then use it */ - if (!rc) { if (cfid->info) { memcpy(&data->fi, cfid->info, sizeof(data->fi)); } else { - rc = SMB2_query_info(xid, tcon, - cfid->fid.persistent_fid, - cfid->fid.volatile_fid, - &data->fi); + rc = SMB2_query_info(xid, tcon, cfid->fid.persistent_fid, + cfid->fid.volatile_fid, &data->fi); if (!rc) { cfid->info = kmemdup(&data->fi, sizeof(data->fi), GFP_KERNEL); diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h index ac6db1f18b5b..3e3faa7cf633 100644 --- a/fs/smb/client/smb2proto.h +++ b/fs/smb/client/smb2proto.h @@ -72,7 +72,7 @@ int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path, - struct cifs_open_info_data *data); + struct cifs_open_info_data *data, bool is_dir); extern int smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon, const char *full_path, __u64 size, struct cifs_sb_info *cifs_sb, bool set_alloc, |
