cifs: fallback to older infolevels on findfirst queryinfo retry

[ Upstream commit 3b7960cace ]

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 some indentation)

See kernel bugzilla 201435

Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Steve French 2018-10-19 01:58:22 -05:00 committed by Greg Kroah-Hartman
parent 82017e26e5
commit 1d41cd1230

View File

@ -779,43 +779,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;