From 2ef78530111e0ddb55b32585c9df4cfe666fb891 Mon Sep 17 00:00:00 2001
From: Steve French <stfrench@microsoft.com>
Date: Sun, 11 Sep 2022 19:49:04 -0500
Subject: [PATCH] smb311: fallback to query fs all info if posix query fs not
supported
A version of Samba, supported POSIX extensions, but not the query fs info
level. Fall back to query fs all info if POSIX query fs info not
supported.
Also fixes the problem that compounding wasn't being used for posix
qfs info in this path (statfs) but was being used in others, so
improves performance of posix query fs info.
Signed-off-by: Steve French <stfrench@microsoft.com>
---
fs/cifs/smb2ops.c | 44 ++++++++++++++++++++++++++------------------
fs/cifs/smb2pdu.c | 2 +-
fs/cifs/smb2proto.h | 2 ++
3 files changed, 29 insertions(+), 19 deletions(-)
@@ -2557,31 +2557,39 @@ static int
smb311_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb, struct kstatfs *buf)
{
+ struct smb2_query_info_rsp *rsp;
+ struct kvec rsp_iov = {NULL, 0};
+ FILE_SYSTEM_POSIX_INFO *info = NULL;
+ int buftype = CIFS_NO_BUFFER;
int rc;
- __le16 srch_path = 0; /* Null - open root of share */
- u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
- struct cifs_open_parms oparms;
- struct cifs_fid fid;
if (!tcon->posix_extensions)
return smb2_queryfs(xid, tcon, cifs_sb, buf);
- oparms.tcon = tcon;
- oparms.desired_access = FILE_READ_ATTRIBUTES;
- oparms.disposition = FILE_OPEN;
- oparms.create_options = cifs_create_options(cifs_sb, 0);
- oparms.fid = &fid;
- oparms.reconnect = false;
-
- rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
- NULL, NULL);
- if (rc)
- return rc;
+ rc = smb2_query_info_compound(xid, tcon, "",
+ FILE_READ_ATTRIBUTES,
+ FS_POSIX_INFORMATION,
+ SMB2_O_INFO_FILESYSTEM,
+ sizeof(FILE_SYSTEM_POSIX_INFO),
+ &rsp_iov, &buftype, cifs_sb);
+ if (rc == -EIO) /* some posix servers didn't support this info level */
+ return smb2_queryfs(xid, tcon, cifs_sb, buf);
+ else if (rc)
+ goto pqfs_exit;
- rc = SMB311_posix_qfs_info(xid, tcon, fid.persistent_fid,
- fid.volatile_fid, buf);
+ rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
buf->f_type = SMB2_SUPER_MAGIC;
- SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+ info = (FILE_SYSTEM_POSIX_INFO *)(
+ le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
+ rc = smb2_validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
+ le32_to_cpu(rsp->OutputBufferLength),
+ &rsp_iov,
+ sizeof(FILE_SYSTEM_POSIX_INFO));
+ if (!rc)
+ copy_posix_fs_info_to_kstatfs(info, buf);
+
+pqfs_exit:
+ free_rsp_buf(buftype, rsp_iov.iov_base);
return rc;
}
@@ -5251,7 +5251,7 @@ smb2_copy_fs_info_to_kstatfs(struct smb2_fs_full_size_info *pfs_inf,
return;
}
-static void
+void
copy_posix_fs_info_to_kstatfs(FILE_SYSTEM_POSIX_INFO *response_data,
struct kstatfs *kst)
{
@@ -267,6 +267,8 @@ extern int smb2_validate_and_copy_iov(unsigned int offset,
extern void smb2_copy_fs_info_to_kstatfs(
struct smb2_fs_full_size_info *pfs_inf,
struct kstatfs *kst);
+extern void copy_posix_fs_info_to_kstatfs(FILE_SYSTEM_POSIX_INFO *response_data,
+ struct kstatfs *kst);
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,
--
2.34.1