CIFS QPathInfo fallback to buggy servers
diff mbox

Message ID CAH2r5msRRdnLhWu8rUuF2GTainxkcVw-uwXJMSOkVfay=hQw5Q@mail.gmail.com
State New
Headers show

Commit Message

Steve French June 23, 2015, 6:31 a.m. UTC
In cleaning out old email found some older patches of yours that
implemented a fall back on QueryPathInfo to older QueryInfo levels for
mounts to NetApp CIFS servers.

I cleaned up (correcting some things Jeff Layton had pointed out on
the mailing list)
and combined patches 2 through 4 of your series which is attached but
untested since I don't have a NetApp filer.  I did merge the first one
of the series (which
was harmless) but was holding off on the remaining till they were
cleaned up and tested.

If you still have access to test these, I can consider them.

Patch
diff mbox

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(-)

diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index c63fd1d..5372046 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -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);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 672ef35..f87e85f 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -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