From c32e6f2ee387ccf4a7db34128662a870e413edad Mon Sep 17 00:00:00 2001
From: Steve French <smfrench@gmail.com>
Date: Tue, 23 Jun 2015 01:25:12 -0500
Subject: [PATCH] [CIFS] add functions for cifs query info to fall back to
Some servers such as NetApp didn't support the normal info levels
Signed-off-by: Gregor Beck <gbeck@sernet.de>
---
fs/cifs/cifsproto.h | 6 ++++
fs/cifs/cifssmb.c | 87 ++++++++++++++++++++++++++++++++++++-----------------
2 files changed, 66 insertions(+), 27 deletions(-)
@@ -249,6 +249,12 @@ extern int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
const char *search_Name, FILE_ALL_INFO *data,
int legacy /* whether to use old info level */,
const struct nls_table *nls_codepage, int remap);
+extern int CIFSSMBQPathInfoBasic(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *search_name, FILE_BASIC_INFO *data,
+ const struct nls_table *nls_codepage, int remap);
+extern int CIFSSMBQPathInfoStandard(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *search_name, FILE_STANDARD_INFO *data,
+ const struct nls_table *nls_codepage, int remap);
extern int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
const char *search_name, FILE_ALL_INFO *data,
const struct nls_table *nls_codepage, int remap);
@@ -4089,13 +4089,13 @@ QFileInfoRetry:
return rc;
}
-int
-CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
- const char *search_name, FILE_ALL_INFO *data,
- int legacy /* old style infolevel */,
- const struct nls_table *nls_codepage, int remap)
+static int
+CIFSSMBQPathInfoImpl(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *search_name,
+ void *data, int size,
+ __u16 level, __u16 bcc,
+ const struct nls_table *nls_codepage, int remap)
{
- /* level 263 SMB_QUERY_FILE_ALL_INFO */
TRANSACTION2_QPI_REQ *pSMB = NULL;
TRANSACTION2_QPI_RSP *pSMBr = NULL;
int rc = 0;
@@ -4103,7 +4103,7 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
int name_len;
__u16 params, byte_count;
- /* cifs_dbg(FYI, "In QPathInfo path %s\n", search_name); */
+ cifs_dbg(FYI, "In QPathInfo level %u path %s", level, search_name);
QPathInfoRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr);
@@ -4142,10 +4142,7 @@ QPathInfoRetry:
byte_count = params + 1 /* pad */ ;
pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
- if (legacy)
- pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
- else
- pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
+ pSMB->InformationLevel = cpu_to_le16(level);
pSMB->Reserved4 = 0;
inc_rfc1001_len(pSMB, byte_count);
pSMB->ByteCount = cpu_to_le16(byte_count);
@@ -4159,25 +4156,10 @@ QPathInfoRetry:
if (rc) /* BB add auto retry on EOPNOTSUPP? */
rc = -EIO;
- else if (!legacy && get_bcc(&pSMBr->hdr) < 40)
+ else if (get_bcc(&pSMBr->hdr) < bcc)
rc = -EIO; /* bad smb */
- else if (legacy && get_bcc(&pSMBr->hdr) < 24)
- rc = -EIO; /* 24 or 26 expected but we do not read
- last field */
else if (data) {
- int size;
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
-
- /*
- * On legacy responses we do not read the last field,
- * EAsize, fortunately since it varies by subdialect and
- * also note it differs on Set vs Get, ie two bytes or 4
- * bytes depending but we don't care here.
- */
- if (legacy)
- size = sizeof(FILE_INFO_STANDARD);
- else
- size = sizeof(FILE_ALL_INFO);
memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
data_offset, size);
} else
@@ -4191,6 +4173,57 @@ QPathInfoRetry:
}
int
+CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *search_name, FILE_ALL_INFO *data,
+ int legacy /* old style infolevel */,
+ const struct nls_table *nls_codepage, int remap)
+{
+ if (legacy) {
+ /*
+ * 24 or 26 expected but on legacy responses we do not read the
+ * last field, EAsize, fortunately since it varies by subdialect
+ * and also note it differs on Set vs. Get, ie two bytes or 4
+ * bytes depending but we don't care here
+ */
+ return CIFSSMBQPathInfoImpl(xid, tcon, search_name,
+ data, sizeof(FILE_INFO_STANDARD),
+ SMB_INFO_STANDARD,
+ sizeof(FILE_INFO_STANDARD),
+ nls_codepage, remap);
+ } else {
+ return CIFSSMBQPathInfoImpl(xid, tcon, search_name,
+ data, sizeof(FILE_ALL_INFO),
+ SMB_QUERY_FILE_ALL_INFO,
+ sizeof(FILE_ALL_INFO),
+ nls_codepage, remap);
+ }
+}
+
+int
+CIFSSMBQPathInfoBasic(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *search_name, FILE_BASIC_INFO *data,
+ const struct nls_table *nls_codepage, int remap)
+{
+ return CIFSSMBQPathInfoImpl(xid, tcon, search_name,
+ data, sizeof(FILE_BASIC_INFO),
+ SMB_QUERY_FILE_BASIC_INFO,
+ sizeof(FILE_BASIC_INFO),
+ nls_codepage, remap);
+}
+
+int
+CIFSSMBQPathInfoStandard(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *search_name, FILE_STANDARD_INFO *data,
+ const struct nls_table *nls_codepage, int remap)
+{
+ return CIFSSMBQPathInfoImpl(xid, tcon, search_name,
+ data, sizeof(FILE_STANDARD_INFO),
+ SMB_QUERY_FILE_STANDARD_INFO,
+ sizeof(FILE_STANDARD_INFO),
+ nls_codepage, remap);
+}
+
+int
CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
u16 netfid, FILE_UNIX_BASIC_INFO *pFindData)
{
--
1.9.1