diff options
Diffstat (limited to 'fs/smb/client/readdir.c')
-rw-r--r-- | fs/smb/client/readdir.c | 39 |
1 files changed, 13 insertions, 26 deletions
diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c index 94255401b38d..ebe1cb30e18e 100644 --- a/fs/smb/client/readdir.c +++ b/fs/smb/client/readdir.c @@ -22,6 +22,7 @@ #include "smb2proto.h" #include "fs_context.h" #include "cached_dir.h" +#include "reparse.h" /* * To be safe - for UCS to UTF-8 with strings loaded with the rare long @@ -56,23 +57,6 @@ static inline void dump_cifs_file_struct(struct file *file, char *label) #endif /* DEBUG2 */ /* - * Match a reparse point inode if reparse tag and ctime haven't changed. - * - * Windows Server updates ctime of reparse points when their data have changed. - * The server doesn't allow changing reparse tags from existing reparse points, - * though it's worth checking. - */ -static inline bool reparse_inode_match(struct inode *inode, - struct cifs_fattr *fattr) -{ - struct timespec64 ctime = inode_get_ctime(inode); - - return (CIFS_I(inode)->cifsAttrs & ATTR_REPARSE) && - CIFS_I(inode)->reparse_tag == fattr->cf_cifstag && - timespec64_equal(&ctime, &fattr->cf_ctime); -} - -/* * Attempt to preload the dcache with the results from the FIND_FIRST/NEXT * * Find the dentry that matches "name". If there isn't one, create one. If it's @@ -141,14 +125,16 @@ retry: if (likely(reparse_inode_match(inode, fattr))) { fattr->cf_mode = inode->i_mode; fattr->cf_rdev = inode->i_rdev; - fattr->cf_eof = CIFS_I(inode)->server_eof; + fattr->cf_uid = inode->i_uid; + fattr->cf_gid = inode->i_gid; + fattr->cf_eof = CIFS_I(inode)->netfs.remote_i_size; fattr->cf_symlink_target = NULL; } else { CIFS_I(inode)->time = 0; rc = -ESTALE; } } - if (!rc && !cifs_fattr_to_inode(inode, fattr)) { + if (!rc && !cifs_fattr_to_inode(inode, fattr, true)) { dput(dentry); return; } @@ -307,14 +293,16 @@ cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, } static void cifs_fulldir_info_to_fattr(struct cifs_fattr *fattr, - SEARCH_ID_FULL_DIR_INFO *info, + const void *info, struct cifs_sb_info *cifs_sb) { + const FILE_FULL_DIRECTORY_INFO *di = info; + __dir_info_to_fattr(fattr, info); - /* See MS-FSCC 2.4.19 FileIdFullDirectoryInformation */ + /* See MS-FSCC 2.4.14, 2.4.19 */ if (fattr->cf_cifsattrs & ATTR_REPARSE) - fattr->cf_cifstag = le32_to_cpu(info->EaSize); + fattr->cf_cifstag = le32_to_cpu(di->EaSize); cifs_fill_common_info(fattr, cifs_sb); } @@ -396,7 +384,7 @@ ffirst_retry: } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; } else /* not srvinos - BB fixme add check for backlevel? */ { - cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; + cifsFile->srch_inf.info_level = SMB_FIND_FILE_FULL_DIRECTORY_INFO; } search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; @@ -987,10 +975,9 @@ static int cifs_filldir(char *find_entry, struct file *file, (FIND_FILE_STANDARD_INFO *)find_entry, cifs_sb); break; + case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_ID_FULL_DIR_INFO: - cifs_fulldir_info_to_fattr(&fattr, - (SEARCH_ID_FULL_DIR_INFO *)find_entry, - cifs_sb); + cifs_fulldir_info_to_fattr(&fattr, find_entry, cifs_sb); break; default: cifs_dir_info_to_fattr(&fattr, |