[CIFS][PATCH] cifs: fallback to older infolevels on findfirst queryinfo retry

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In cases where queryinfo fails, we have cases in cifs (vers=1.0)
where with backupuid mounts we retry the query info with findfirst.
This doesn't work to some NetApp servers which don't support
WindowsXP (and later) infolevel 261 (SMB_FIND_FILE_ID_FULL_DIR_INFO)
so in this case use other info levels (in this case it will usually
be level 257, SMB_FIND_FILE_DIRECTORY_INFO).

Also fixes indentation.

See kernel bugzilla 201435

Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx>
---
 fs/cifs/inode.c | 67 +++++++++++++++++++++++++++----------------------
 1 file changed, 37 insertions(+), 30 deletions(-)

diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 7483c09317b9..1023d78673fb 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -784,43 +784,50 @@ cifs_get_inode_info(struct inode **inode, const
char *full_path,
     } else if ((rc == -EACCES) && backup_cred(cifs_sb) &&
            (strcmp(server->vals->version_string, SMB1_VERSION_STRING)
               == 0)) {
-            /*
-             * For SMB2 and later the backup intent flag is already
-             * sent if needed on open and there is no path based
-             * FindFirst operation to use to retry with
-             */
+        /*
+         * For SMB2 and later the backup intent flag is already
+         * sent if needed on open and there is no path based
+         * FindFirst operation to use to retry with
+         */

-            srchinf = kzalloc(sizeof(struct cifs_search_info),
-                        GFP_KERNEL);
-            if (srchinf == NULL) {
-                rc = -ENOMEM;
-                goto cgii_exit;
-            }
+        srchinf = kzalloc(sizeof(struct cifs_search_info),
+                    GFP_KERNEL);
+        if (srchinf == NULL) {
+            rc = -ENOMEM;
+            goto cgii_exit;
+        }

-            srchinf->endOfSearch = false;
+        srchinf->endOfSearch = false;
+        if (tcon->unix_ext)
+            srchinf->info_level = SMB_FIND_FILE_UNIX;
+        else if ((tcon->ses->capabilities &
+             tcon->ses->server->vals->cap_nt_find) == 0)
+            srchinf->info_level = SMB_FIND_FILE_INFO_STANDARD;
+        else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
             srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
+        else /* no srvino useful for fallback to some netapp */
+            srchinf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;

-            srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
-                    CIFS_SEARCH_CLOSE_AT_END |
-                    CIFS_SEARCH_BACKUP_SEARCH;
+        srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
+                CIFS_SEARCH_CLOSE_AT_END |
+                CIFS_SEARCH_BACKUP_SEARCH;

-            rc = CIFSFindFirst(xid, tcon, full_path,
-                cifs_sb, NULL, srchflgs, srchinf, false);
-            if (!rc) {
-                data =
-                (FILE_ALL_INFO *)srchinf->srch_entries_start;
+        rc = CIFSFindFirst(xid, tcon, full_path,
+            cifs_sb, NULL, srchflgs, srchinf, false);
+        if (!rc) {
+            data = (FILE_ALL_INFO *)srchinf->srch_entries_start;

-                cifs_dir_info_to_fattr(&fattr,
-                (FILE_DIRECTORY_INFO *)data, cifs_sb);
-                fattr.cf_uniqueid = le64_to_cpu(
-                ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
-                validinum = true;
+            cifs_dir_info_to_fattr(&fattr,
+            (FILE_DIRECTORY_INFO *)data, cifs_sb);
+            fattr.cf_uniqueid = le64_to_cpu(
+            ((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
+            validinum = true;

-                cifs_buf_release(srchinf->ntwrk_buf_start);
-            }
-            kfree(srchinf);
-            if (rc)
-                goto cgii_exit;
+            cifs_buf_release(srchinf->ntwrk_buf_start);
+        }
+        kfree(srchinf);
+        if (rc)
+            goto cgii_exit;
     } else
         goto cgii_exit;

-- 
Thanks,

Steve
From ee68033e78aaaf0b15b2361346bdcc0d132edc7c Mon Sep 17 00:00:00 2001
From: Steve French <stfrench@xxxxxxxxxxxxx>
Date: Fri, 19 Oct 2018 01:58:22 -0500
Subject: [PATCH 2/2] cifs: fallback to older infolevels on findfirst queryinfo
 retry

In cases where queryinfo fails, we have cases in cifs (vers=1.0)
where with backupuid mounts we retry the query info with findfirst.
This doesn't work to some NetApp servers which don't support
WindowsXP (and later) infolevel 261 (SMB_FIND_FILE_ID_FULL_DIR_INFO)
so in this case use other info levels (in this case it will usually
be level 257, SMB_FIND_FILE_DIRECTORY_INFO).

See kernel bugzilla 201435

Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx>
---
 fs/cifs/inode.c | 67 +++++++++++++++++++++++++++----------------------
 1 file changed, 37 insertions(+), 30 deletions(-)

diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 7483c09317b9..1023d78673fb 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -784,43 +784,50 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
 	} else if ((rc == -EACCES) && backup_cred(cifs_sb) &&
 		   (strcmp(server->vals->version_string, SMB1_VERSION_STRING)
 		      == 0)) {
-			/*
-			 * For SMB2 and later the backup intent flag is already
-			 * sent if needed on open and there is no path based
-			 * FindFirst operation to use to retry with
-			 */
+		/*
+		 * For SMB2 and later the backup intent flag is already
+		 * sent if needed on open and there is no path based
+		 * FindFirst operation to use to retry with
+		 */
 
-			srchinf = kzalloc(sizeof(struct cifs_search_info),
-						GFP_KERNEL);
-			if (srchinf == NULL) {
-				rc = -ENOMEM;
-				goto cgii_exit;
-			}
+		srchinf = kzalloc(sizeof(struct cifs_search_info),
+					GFP_KERNEL);
+		if (srchinf == NULL) {
+			rc = -ENOMEM;
+			goto cgii_exit;
+		}
 
-			srchinf->endOfSearch = false;
+		srchinf->endOfSearch = false;
+		if (tcon->unix_ext)
+			srchinf->info_level = SMB_FIND_FILE_UNIX;
+		else if ((tcon->ses->capabilities &
+			 tcon->ses->server->vals->cap_nt_find) == 0)
+			srchinf->info_level = SMB_FIND_FILE_INFO_STANDARD;
+		else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
 			srchinf->info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
+		else /* no srvino useful for fallback to some netapp */
+			srchinf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
 
-			srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
-					CIFS_SEARCH_CLOSE_AT_END |
-					CIFS_SEARCH_BACKUP_SEARCH;
+		srchflgs = CIFS_SEARCH_CLOSE_ALWAYS |
+				CIFS_SEARCH_CLOSE_AT_END |
+				CIFS_SEARCH_BACKUP_SEARCH;
 
-			rc = CIFSFindFirst(xid, tcon, full_path,
-				cifs_sb, NULL, srchflgs, srchinf, false);
-			if (!rc) {
-				data =
-				(FILE_ALL_INFO *)srchinf->srch_entries_start;
+		rc = CIFSFindFirst(xid, tcon, full_path,
+			cifs_sb, NULL, srchflgs, srchinf, false);
+		if (!rc) {
+			data = (FILE_ALL_INFO *)srchinf->srch_entries_start;
 
-				cifs_dir_info_to_fattr(&fattr,
-				(FILE_DIRECTORY_INFO *)data, cifs_sb);
-				fattr.cf_uniqueid = le64_to_cpu(
-				((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
-				validinum = true;
+			cifs_dir_info_to_fattr(&fattr,
+			(FILE_DIRECTORY_INFO *)data, cifs_sb);
+			fattr.cf_uniqueid = le64_to_cpu(
+			((SEARCH_ID_FULL_DIR_INFO *)data)->UniqueId);
+			validinum = true;
 
-				cifs_buf_release(srchinf->ntwrk_buf_start);
-			}
-			kfree(srchinf);
-			if (rc)
-				goto cgii_exit;
+			cifs_buf_release(srchinf->ntwrk_buf_start);
+		}
+		kfree(srchinf);
+		if (rc)
+			goto cgii_exit;
 	} else
 		goto cgii_exit;
 
-- 
2.17.1


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux