summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnzo Matsumiya <ematsumiya@suse.de>2025-09-08 18:12:40 -0300
committerEnzo Matsumiya <ematsumiya@suse.de>2025-09-12 17:27:38 -0300
commit48e413d9e73badac50d6cc0fe2b10808c9d56f3a (patch)
treec09735fc18f7fdd503bf63e9dcac920e87a60cc8
parentd5db635bbcf732be94e0808f74e00a9476509ed0 (diff)
downloadlinux-48e413d9e73badac50d6cc0fe2b10808c9d56f3a.tar.gz
linux-48e413d9e73badac50d6cc0fe2b10808c9d56f3a.tar.bz2
linux-48e413d9e73badac50d6cc0fe2b10808c9d56f3a.zip
smb: client: use cached dir on queryfs/smb2_compound_op
A dentry is passed to cifs_statfs(), so pass down d_is_dir() to smb2_queryfs() so we can cache/reuse this dir. Other: - make smb2_compound_op a static function, as it's not used anywhere else Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
-rw-r--r--fs/smb/client/cifsfs.c2
-rw-r--r--fs/smb/client/cifsglob.h2
-rw-r--r--fs/smb/client/smb1ops.c2
-rw-r--r--fs/smb/client/smb2ops.c32
-rw-r--r--fs/smb/client/smb2proto.h6
5 files changed, 20 insertions, 24 deletions
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index e1848276bab4..a2ecc5649860 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -339,7 +339,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_ffree = 0; /* unlimited */
if (server->ops->queryfs)
- rc = server->ops->queryfs(xid, tcon, full_path, cifs_sb, buf);
+ rc = server->ops->queryfs(xid, tcon, full_path, cifs_sb, buf, d_is_dir(dentry));
statfs_out:
free_dentry_path(page);
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 08c8131c8018..dddac55abd6f 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -519,7 +519,7 @@ struct smb_version_operations {
__u16 net_fid, struct cifsInodeInfo *cifs_inode);
/* query remote filesystem */
int (*queryfs)(const unsigned int, struct cifs_tcon *,
- const char *, struct cifs_sb_info *, struct kstatfs *);
+ const char *, struct cifs_sb_info *, struct kstatfs *, bool);
/* send mandatory brlock to the server */
int (*mand_lock)(const unsigned int, struct cifsFileInfo *, __u64,
__u64, __u32, int, int, bool);
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index d964bc9c2823..9fa1ff9ea70d 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -1105,7 +1105,7 @@ cifs_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid,
static int
cifs_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
- const char *path, struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
+ const char *path, struct cifs_sb_info *cifs_sb, struct kstatfs *buf, bool is_dir)
{
int rc = -EOPNOTSUPP;
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 8842315d2526..f691271463b5 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -1110,6 +1110,11 @@ out:
return (ssize_t)rc;
}
+static int smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *path, u32 desired_access, u32 class, u32 type,
+ u32 output_len, struct kvec *rsp, int *buftype,
+ struct cifs_sb_info *cifs_sb, bool is_dir);
+
static ssize_t
smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
const unsigned char *path, const unsigned char *ea_name,
@@ -1129,7 +1134,7 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
CIFSMaxBufSize -
MAX_SMB2_CREATE_RESPONSE_SIZE -
MAX_SMB2_CLOSE_RESPONSE_SIZE,
- &rsp_iov, &buftype, cifs_sb);
+ &rsp_iov, &buftype, cifs_sb, false);
if (rc) {
/*
* If ea_name is NULL (listxattr) and there are no EAs,
@@ -1231,7 +1236,7 @@ replay_again:
CIFSMaxBufSize -
MAX_SMB2_CREATE_RESPONSE_SIZE -
MAX_SMB2_CLOSE_RESPONSE_SIZE,
- &rsp_iov[1], &resp_buftype[1], cifs_sb);
+ &rsp_iov[1], &resp_buftype[1], cifs_sb, false);
if (rc == 0) {
rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base;
used_len = le32_to_cpu(rsp->OutputBufferLength);
@@ -2694,12 +2699,10 @@ bool smb2_should_replay(struct cifs_tcon *tcon,
* Passes the query info response back to the caller on success.
* Caller need to free this with free_rsp_buf().
*/
-int
-smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
- const char *path, u32 desired_access,
- u32 class, u32 type, u32 output_len,
- struct kvec *rsp, int *buftype,
- struct cifs_sb_info *cifs_sb)
+static int smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *path, u32 desired_access, u32 class, u32 type,
+ u32 output_len, struct kvec *rsp, int *buftype,
+ struct cifs_sb_info *cifs_sb, bool is_dir)
{
struct smb2_compound_vars *vars;
struct cifs_ses *ses = tcon->ses;
@@ -2741,9 +2744,9 @@ replay_again:
rsp_iov = vars->rsp_iov;
/*
- * We can only call this for things we know are directories.
+ * We can only open + cache paths we know are directories.
*/
- if (!strcmp(path, ""))
+ if (is_dir)
/* cfid null if open dir failed */
open_cached_dir(xid, tcon, path, cifs_sb, &cfid);
@@ -2852,7 +2855,7 @@ out_free_path:
static int
smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
- const char *path, struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
+ const char *path, struct cifs_sb_info *cifs_sb, struct kstatfs *buf, bool is_dir)
{
struct smb2_query_info_rsp *rsp;
struct smb2_fs_full_size_info *info = NULL;
@@ -2860,13 +2863,12 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
int buftype = CIFS_NO_BUFFER;
int rc;
-
rc = smb2_query_info_compound(xid, tcon, path,
FILE_READ_ATTRIBUTES,
FS_FULL_SIZE_INFORMATION,
SMB2_O_INFO_FILESYSTEM,
sizeof(struct smb2_fs_full_size_info),
- &rsp_iov, &buftype, cifs_sb);
+ &rsp_iov, &buftype, cifs_sb, is_dir);
if (rc)
goto qfs_exit;
@@ -2889,7 +2891,7 @@ qfs_exit:
static int
smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
- const char *path, struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
+ const char *path, struct cifs_sb_info *cifs_sb, struct kstatfs *buf, bool is_dir)
{
int rc;
__le16 *utf16_path = NULL;
@@ -2898,7 +2900,7 @@ smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_fid fid;
if (!tcon->posix_extensions)
- return smb2_queryfs(xid, tcon, path, cifs_sb, buf);
+ return smb2_queryfs(xid, tcon, path, cifs_sb, buf, is_dir);
oparms = (struct cifs_open_parms) {
.tcon = tcon,
diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h
index 3e3faa7cf633..99326810a159 100644
--- a/fs/smb/client/smb2proto.h
+++ b/fs/smb/client/smb2proto.h
@@ -299,12 +299,6 @@ extern int smb311_crypto_shash_allocate(struct TCP_Server_Info *server);
extern int smb311_update_preauth_hash(struct cifs_ses *ses,
struct TCP_Server_Info *server,
struct kvec *iov, int nvec);
-extern int smb2_query_info_compound(const unsigned int xid,
- struct cifs_tcon *tcon,
- const char *path, u32 desired_access,
- u32 class, u32 type, u32 output_len,
- struct kvec *rsp, int *buftype,
- struct cifs_sb_info *cifs_sb);
/* query path info from the server using SMB311 POSIX extensions*/
int smb311_posix_query_path_info(const unsigned int xid,
struct cifs_tcon *tcon,