Commit cc2f36ec authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '5.5-rc3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "One performance fix for large directory searches, and one minor style
  cleanup noticed by Clang"

* tag '5.5-rc3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: Optimize readdir on reparse points
  cifs: Adjust indentation in smb2_open_file
parents bf8d1cd4 046aca3c
...@@ -1693,6 +1693,7 @@ struct cifs_fattr { ...@@ -1693,6 +1693,7 @@ struct cifs_fattr {
struct timespec64 cf_atime; struct timespec64 cf_atime;
struct timespec64 cf_mtime; struct timespec64 cf_mtime;
struct timespec64 cf_ctime; struct timespec64 cf_ctime;
u32 cf_cifstag;
}; };
static inline void free_dfs_info_param(struct dfs_info3_param *param) static inline void free_dfs_info_param(struct dfs_info3_param *param)
......
...@@ -139,6 +139,28 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name, ...@@ -139,6 +139,28 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
dput(dentry); dput(dentry);
} }
static bool reparse_file_needs_reval(const struct cifs_fattr *fattr)
{
if (!(fattr->cf_cifsattrs & ATTR_REPARSE))
return false;
/*
* The DFS tags should be only intepreted by server side as per
* MS-FSCC 2.1.2.1, but let's include them anyway.
*
* Besides, if cf_cifstag is unset (0), then we still need it to be
* revalidated to know exactly what reparse point it is.
*/
switch (fattr->cf_cifstag) {
case IO_REPARSE_TAG_DFS:
case IO_REPARSE_TAG_DFSR:
case IO_REPARSE_TAG_SYMLINK:
case IO_REPARSE_TAG_NFS:
case 0:
return true;
}
return false;
}
static void static void
cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
{ {
...@@ -158,7 +180,7 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) ...@@ -158,7 +180,7 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
* is a symbolic link, DFS referral or a reparse point with a direct * is a symbolic link, DFS referral or a reparse point with a direct
* access like junctions, deduplicated files, NFS symlinks. * access like junctions, deduplicated files, NFS symlinks.
*/ */
if (fattr->cf_cifsattrs & ATTR_REPARSE) if (reparse_file_needs_reval(fattr))
fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
/* non-unix readdir doesn't provide nlink */ /* non-unix readdir doesn't provide nlink */
...@@ -194,19 +216,37 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) ...@@ -194,19 +216,37 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
} }
} }
static void __dir_info_to_fattr(struct cifs_fattr *fattr, const void *info)
{
const FILE_DIRECTORY_INFO *fi = info;
memset(fattr, 0, sizeof(*fattr));
fattr->cf_cifsattrs = le32_to_cpu(fi->ExtFileAttributes);
fattr->cf_eof = le64_to_cpu(fi->EndOfFile);
fattr->cf_bytes = le64_to_cpu(fi->AllocationSize);
fattr->cf_createtime = le64_to_cpu(fi->CreationTime);
fattr->cf_atime = cifs_NTtimeToUnix(fi->LastAccessTime);
fattr->cf_ctime = cifs_NTtimeToUnix(fi->ChangeTime);
fattr->cf_mtime = cifs_NTtimeToUnix(fi->LastWriteTime);
}
void void
cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
struct cifs_sb_info *cifs_sb) struct cifs_sb_info *cifs_sb)
{ {
memset(fattr, 0, sizeof(*fattr)); __dir_info_to_fattr(fattr, info);
fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes); cifs_fill_common_info(fattr, cifs_sb);
fattr->cf_eof = le64_to_cpu(info->EndOfFile); }
fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
fattr->cf_createtime = le64_to_cpu(info->CreationTime);
fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
static void cifs_fulldir_info_to_fattr(struct cifs_fattr *fattr,
SEARCH_ID_FULL_DIR_INFO *info,
struct cifs_sb_info *cifs_sb)
{
__dir_info_to_fattr(fattr, info);
/* See MS-FSCC 2.4.18 FileIdFullDirectoryInformation */
if (fattr->cf_cifsattrs & ATTR_REPARSE)
fattr->cf_cifstag = le32_to_cpu(info->EaSize);
cifs_fill_common_info(fattr, cifs_sb); cifs_fill_common_info(fattr, cifs_sb);
} }
...@@ -755,6 +795,11 @@ static int cifs_filldir(char *find_entry, struct file *file, ...@@ -755,6 +795,11 @@ static int cifs_filldir(char *find_entry, struct file *file,
(FIND_FILE_STANDARD_INFO *)find_entry, (FIND_FILE_STANDARD_INFO *)find_entry,
cifs_sb); cifs_sb);
break; break;
case SMB_FIND_FILE_ID_FULL_DIR_INFO:
cifs_fulldir_info_to_fattr(&fattr,
(SEARCH_ID_FULL_DIR_INFO *)find_entry,
cifs_sb);
break;
default: default:
cifs_dir_info_to_fattr(&fattr, cifs_dir_info_to_fattr(&fattr,
(FILE_DIRECTORY_INFO *)find_entry, (FILE_DIRECTORY_INFO *)find_entry,
......
...@@ -67,7 +67,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, ...@@ -67,7 +67,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
goto out; goto out;
if (oparms->tcon->use_resilient) { if (oparms->tcon->use_resilient) {
/* default timeout is 0, servers pick default (120 seconds) */ /* default timeout is 0, servers pick default (120 seconds) */
nr_ioctl_req.Timeout = nr_ioctl_req.Timeout =
cpu_to_le32(oparms->tcon->handle_timeout); cpu_to_le32(oparms->tcon->handle_timeout);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment