diff options
| -rw-r--r-- | fs/cifs/readdir.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 770d5a9781c1..94d620198209 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -126,6 +126,22 @@ out: | |||
| 126 | dput(dentry); | 126 | dput(dentry); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | /* | ||
| 130 | * Is it possible that this directory might turn out to be a DFS referral | ||
| 131 | * once we go to try and use it? | ||
| 132 | */ | ||
| 133 | static bool | ||
| 134 | cifs_dfs_is_possible(struct cifs_sb_info *cifs_sb) | ||
| 135 | { | ||
| 136 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
| 137 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); | ||
| 138 | |||
| 139 | if (tcon->Flags & SMB_SHARE_IS_IN_DFS) | ||
| 140 | return true; | ||
| 141 | #endif | ||
| 142 | return false; | ||
| 143 | } | ||
| 144 | |||
| 129 | static void | 145 | static void |
| 130 | cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) | 146 | cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) |
| 131 | { | 147 | { |
| @@ -135,6 +151,19 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) | |||
| 135 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { | 151 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { |
| 136 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; | 152 | fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; |
| 137 | fattr->cf_dtype = DT_DIR; | 153 | fattr->cf_dtype = DT_DIR; |
| 154 | /* | ||
| 155 | * Windows CIFS servers generally make DFS referrals look | ||
| 156 | * like directories in FIND_* responses with the reparse | ||
| 157 | * attribute flag also set (since DFS junctions are | ||
| 158 | * reparse points). We must revalidate at least these | ||
| 159 | * directory inodes before trying to use them (if | ||
| 160 | * they are DFS we will get PATH_NOT_COVERED back | ||
| 161 | * when queried directly and can then try to connect | ||
| 162 | * to the DFS target) | ||
| 163 | */ | ||
| 164 | if (cifs_dfs_is_possible(cifs_sb) && | ||
| 165 | (fattr->cf_cifsattrs & ATTR_REPARSE)) | ||
| 166 | fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; | ||
| 138 | } else { | 167 | } else { |
| 139 | fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; | 168 | fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; |
| 140 | fattr->cf_dtype = DT_REG; | 169 | fattr->cf_dtype = DT_REG; |
