Commit 2f2591a34db6c9361faa316c91a6e320cb4e6aee

Authored by Jeff Layton
Committed by Steve French
1 parent 8367224b2e

cifs: don't compare uniqueids in cifs_prime_dcache unless server inode numbers are in use

Oliver reported that commit cd60042c caused his cifs mounts to
continually thrash through new inodes on readdir. His servers are not
sending inode numbers (or he's not using them), and the new test in
that function doesn't account for that sort of setup correctly.

If we're not using server inode numbers, then assume that the inode
attached to the dentry hasn't changed. Go ahead and update the
attributes in place, but keep the same inode number.

Cc: <stable@vger.kernel.org> # v3.5+
Reported-and-Tested-by: Oliver Mössinger <Oliver.Moessinger@ichaus.de>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>

Showing 1 changed file with 15 additions and 4 deletions Inline Diff

1 /* 1 /*
2 * fs/cifs/readdir.c 2 * fs/cifs/readdir.c
3 * 3 *
4 * Directory search handling 4 * Directory search handling
5 * 5 *
6 * Copyright (C) International Business Machines Corp., 2004, 2008 6 * Copyright (C) International Business Machines Corp., 2004, 2008
7 * Copyright (C) Red Hat, Inc., 2011 7 * Copyright (C) Red Hat, Inc., 2011
8 * Author(s): Steve French (sfrench@us.ibm.com) 8 * Author(s): Steve French (sfrench@us.ibm.com)
9 * 9 *
10 * This library is free software; you can redistribute it and/or modify 10 * This library is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published 11 * it under the terms of the GNU Lesser General Public License as published
12 * by the Free Software Foundation; either version 2.1 of the License, or 12 * by the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version. 13 * (at your option) any later version.
14 * 14 *
15 * This library is distributed in the hope that it will be useful, 15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
18 * the GNU Lesser General Public License for more details. 18 * the GNU Lesser General Public License for more details.
19 * 19 *
20 * You should have received a copy of the GNU Lesser General Public License 20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this library; if not, write to the Free Software 21 * along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */ 23 */
24 #include <linux/fs.h> 24 #include <linux/fs.h>
25 #include <linux/pagemap.h> 25 #include <linux/pagemap.h>
26 #include <linux/slab.h> 26 #include <linux/slab.h>
27 #include <linux/stat.h> 27 #include <linux/stat.h>
28 #include "cifspdu.h" 28 #include "cifspdu.h"
29 #include "cifsglob.h" 29 #include "cifsglob.h"
30 #include "cifsproto.h" 30 #include "cifsproto.h"
31 #include "cifs_unicode.h" 31 #include "cifs_unicode.h"
32 #include "cifs_debug.h" 32 #include "cifs_debug.h"
33 #include "cifs_fs_sb.h" 33 #include "cifs_fs_sb.h"
34 #include "cifsfs.h" 34 #include "cifsfs.h"
35 35
36 /* 36 /*
37 * To be safe - for UCS to UTF-8 with strings loaded with the rare long 37 * To be safe - for UCS to UTF-8 with strings loaded with the rare long
38 * characters alloc more to account for such multibyte target UTF-8 38 * characters alloc more to account for such multibyte target UTF-8
39 * characters. 39 * characters.
40 */ 40 */
41 #define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2) 41 #define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2)
42 42
43 #ifdef CONFIG_CIFS_DEBUG2 43 #ifdef CONFIG_CIFS_DEBUG2
44 static void dump_cifs_file_struct(struct file *file, char *label) 44 static void dump_cifs_file_struct(struct file *file, char *label)
45 { 45 {
46 struct cifsFileInfo *cf; 46 struct cifsFileInfo *cf;
47 47
48 if (file) { 48 if (file) {
49 cf = file->private_data; 49 cf = file->private_data;
50 if (cf == NULL) { 50 if (cf == NULL) {
51 cFYI(1, "empty cifs private file data"); 51 cFYI(1, "empty cifs private file data");
52 return; 52 return;
53 } 53 }
54 if (cf->invalidHandle) 54 if (cf->invalidHandle)
55 cFYI(1, "invalid handle"); 55 cFYI(1, "invalid handle");
56 if (cf->srch_inf.endOfSearch) 56 if (cf->srch_inf.endOfSearch)
57 cFYI(1, "end of search"); 57 cFYI(1, "end of search");
58 if (cf->srch_inf.emptyDir) 58 if (cf->srch_inf.emptyDir)
59 cFYI(1, "empty dir"); 59 cFYI(1, "empty dir");
60 } 60 }
61 } 61 }
62 #else 62 #else
63 static inline void dump_cifs_file_struct(struct file *file, char *label) 63 static inline void dump_cifs_file_struct(struct file *file, char *label)
64 { 64 {
65 } 65 }
66 #endif /* DEBUG2 */ 66 #endif /* DEBUG2 */
67 67
68 /* 68 /*
69 * Attempt to preload the dcache with the results from the FIND_FIRST/NEXT 69 * Attempt to preload the dcache with the results from the FIND_FIRST/NEXT
70 * 70 *
71 * Find the dentry that matches "name". If there isn't one, create one. If it's 71 * Find the dentry that matches "name". If there isn't one, create one. If it's
72 * a negative dentry or the uniqueid changed, then drop it and recreate it. 72 * a negative dentry or the uniqueid changed, then drop it and recreate it.
73 */ 73 */
74 static void 74 static void
75 cifs_prime_dcache(struct dentry *parent, struct qstr *name, 75 cifs_prime_dcache(struct dentry *parent, struct qstr *name,
76 struct cifs_fattr *fattr) 76 struct cifs_fattr *fattr)
77 { 77 {
78 struct dentry *dentry, *alias; 78 struct dentry *dentry, *alias;
79 struct inode *inode; 79 struct inode *inode;
80 struct super_block *sb = parent->d_inode->i_sb; 80 struct super_block *sb = parent->d_inode->i_sb;
81 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
81 82
82 cFYI(1, "%s: for %s", __func__, name->name); 83 cFYI(1, "%s: for %s", __func__, name->name);
83 84
84 if (parent->d_op && parent->d_op->d_hash) 85 if (parent->d_op && parent->d_op->d_hash)
85 parent->d_op->d_hash(parent, parent->d_inode, name); 86 parent->d_op->d_hash(parent, parent->d_inode, name);
86 else 87 else
87 name->hash = full_name_hash(name->name, name->len); 88 name->hash = full_name_hash(name->name, name->len);
88 89
89 dentry = d_lookup(parent, name); 90 dentry = d_lookup(parent, name);
90 if (dentry) { 91 if (dentry) {
91 int err; 92 int err;
92 93
93 inode = dentry->d_inode; 94 inode = dentry->d_inode;
94 /* update inode in place if i_ino didn't change */ 95 if (inode) {
95 if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) { 96 /*
96 cifs_fattr_to_inode(inode, fattr); 97 * If we're generating inode numbers, then we don't
97 goto out; 98 * want to clobber the existing one with the one that
99 * the readdir code created.
100 */
101 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
102 fattr->cf_uniqueid = CIFS_I(inode)->uniqueid;
103
104 /* update inode in place if i_ino didn't change */
105 if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
106 cifs_fattr_to_inode(inode, fattr);
107 goto out;
108 }
98 } 109 }
99 err = d_invalidate(dentry); 110 err = d_invalidate(dentry);
100 dput(dentry); 111 dput(dentry);
101 if (err) 112 if (err)
102 return; 113 return;
103 } 114 }
104 115
105 dentry = d_alloc(parent, name); 116 dentry = d_alloc(parent, name);
106 if (!dentry) 117 if (!dentry)
107 return; 118 return;
108 119
109 inode = cifs_iget(sb, fattr); 120 inode = cifs_iget(sb, fattr);
110 if (!inode) 121 if (!inode)
111 goto out; 122 goto out;
112 123
113 alias = d_materialise_unique(dentry, inode); 124 alias = d_materialise_unique(dentry, inode);
114 if (alias && !IS_ERR(alias)) 125 if (alias && !IS_ERR(alias))
115 dput(alias); 126 dput(alias);
116 out: 127 out:
117 dput(dentry); 128 dput(dentry);
118 } 129 }
119 130
120 static void 131 static void
121 cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) 132 cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
122 { 133 {
123 fattr->cf_uid = cifs_sb->mnt_uid; 134 fattr->cf_uid = cifs_sb->mnt_uid;
124 fattr->cf_gid = cifs_sb->mnt_gid; 135 fattr->cf_gid = cifs_sb->mnt_gid;
125 136
126 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { 137 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
127 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; 138 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
128 fattr->cf_dtype = DT_DIR; 139 fattr->cf_dtype = DT_DIR;
129 } else { 140 } else {
130 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; 141 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
131 fattr->cf_dtype = DT_REG; 142 fattr->cf_dtype = DT_REG;
132 } 143 }
133 144
134 if (fattr->cf_cifsattrs & ATTR_READONLY) 145 if (fattr->cf_cifsattrs & ATTR_READONLY)
135 fattr->cf_mode &= ~S_IWUGO; 146 fattr->cf_mode &= ~S_IWUGO;
136 147
137 /* 148 /*
138 * We of course don't get ACL info in FIND_FIRST/NEXT results, so 149 * We of course don't get ACL info in FIND_FIRST/NEXT results, so
139 * mark it for revalidation so that "ls -l" will look right. It might 150 * mark it for revalidation so that "ls -l" will look right. It might
140 * be super-slow, but if we don't do this then the ownership of files 151 * be super-slow, but if we don't do this then the ownership of files
141 * may look wrong since the inodes may not have timed out by the time 152 * may look wrong since the inodes may not have timed out by the time
142 * "ls" does a stat() call on them. 153 * "ls" does a stat() call on them.
143 */ 154 */
144 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) 155 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
145 fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; 156 fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
146 157
147 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL && 158 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
148 fattr->cf_cifsattrs & ATTR_SYSTEM) { 159 fattr->cf_cifsattrs & ATTR_SYSTEM) {
149 if (fattr->cf_eof == 0) { 160 if (fattr->cf_eof == 0) {
150 fattr->cf_mode &= ~S_IFMT; 161 fattr->cf_mode &= ~S_IFMT;
151 fattr->cf_mode |= S_IFIFO; 162 fattr->cf_mode |= S_IFIFO;
152 fattr->cf_dtype = DT_FIFO; 163 fattr->cf_dtype = DT_FIFO;
153 } else { 164 } else {
154 /* 165 /*
155 * trying to get the type and mode via SFU can be slow, 166 * trying to get the type and mode via SFU can be slow,
156 * so just call those regular files for now, and mark 167 * so just call those regular files for now, and mark
157 * for reval 168 * for reval
158 */ 169 */
159 fattr->cf_flags |= CIFS_FATTR_NEED_REVAL; 170 fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
160 } 171 }
161 } 172 }
162 } 173 }
163 174
164 void 175 void
165 cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info, 176 cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
166 struct cifs_sb_info *cifs_sb) 177 struct cifs_sb_info *cifs_sb)
167 { 178 {
168 memset(fattr, 0, sizeof(*fattr)); 179 memset(fattr, 0, sizeof(*fattr));
169 fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes); 180 fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes);
170 fattr->cf_eof = le64_to_cpu(info->EndOfFile); 181 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
171 fattr->cf_bytes = le64_to_cpu(info->AllocationSize); 182 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
172 fattr->cf_createtime = le64_to_cpu(info->CreationTime); 183 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
173 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime); 184 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
174 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime); 185 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
175 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime); 186 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
176 187
177 cifs_fill_common_info(fattr, cifs_sb); 188 cifs_fill_common_info(fattr, cifs_sb);
178 } 189 }
179 190
180 static void 191 static void
181 cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info, 192 cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
182 struct cifs_sb_info *cifs_sb) 193 struct cifs_sb_info *cifs_sb)
183 { 194 {
184 int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj; 195 int offset = cifs_sb_master_tcon(cifs_sb)->ses->server->timeAdj;
185 196
186 memset(fattr, 0, sizeof(*fattr)); 197 memset(fattr, 0, sizeof(*fattr));
187 fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate, 198 fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
188 info->LastAccessTime, offset); 199 info->LastAccessTime, offset);
189 fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate, 200 fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate,
190 info->LastWriteTime, offset); 201 info->LastWriteTime, offset);
191 fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate, 202 fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate,
192 info->LastWriteTime, offset); 203 info->LastWriteTime, offset);
193 204
194 fattr->cf_cifsattrs = le16_to_cpu(info->Attributes); 205 fattr->cf_cifsattrs = le16_to_cpu(info->Attributes);
195 fattr->cf_bytes = le32_to_cpu(info->AllocationSize); 206 fattr->cf_bytes = le32_to_cpu(info->AllocationSize);
196 fattr->cf_eof = le32_to_cpu(info->DataSize); 207 fattr->cf_eof = le32_to_cpu(info->DataSize);
197 208
198 cifs_fill_common_info(fattr, cifs_sb); 209 cifs_fill_common_info(fattr, cifs_sb);
199 } 210 }
200 211
201 /* BB eventually need to add the following helper function to 212 /* BB eventually need to add the following helper function to
202 resolve NT_STATUS_STOPPED_ON_SYMLINK return code when 213 resolve NT_STATUS_STOPPED_ON_SYMLINK return code when
203 we try to do FindFirst on (NTFS) directory symlinks */ 214 we try to do FindFirst on (NTFS) directory symlinks */
204 /* 215 /*
205 int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, 216 int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
206 unsigned int xid) 217 unsigned int xid)
207 { 218 {
208 __u16 fid; 219 __u16 fid;
209 int len; 220 int len;
210 int oplock = 0; 221 int oplock = 0;
211 int rc; 222 int rc;
212 struct cifs_tcon *ptcon = cifs_sb_tcon(cifs_sb); 223 struct cifs_tcon *ptcon = cifs_sb_tcon(cifs_sb);
213 char *tmpbuffer; 224 char *tmpbuffer;
214 225
215 rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ, 226 rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
216 OPEN_REPARSE_POINT, &fid, &oplock, NULL, 227 OPEN_REPARSE_POINT, &fid, &oplock, NULL,
217 cifs_sb->local_nls, 228 cifs_sb->local_nls,
218 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 229 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
219 if (!rc) { 230 if (!rc) {
220 tmpbuffer = kmalloc(maxpath); 231 tmpbuffer = kmalloc(maxpath);
221 rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path, 232 rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path,
222 tmpbuffer, 233 tmpbuffer,
223 maxpath -1, 234 maxpath -1,
224 fid, 235 fid,
225 cifs_sb->local_nls); 236 cifs_sb->local_nls);
226 if (CIFSSMBClose(xid, ptcon, fid)) { 237 if (CIFSSMBClose(xid, ptcon, fid)) {
227 cFYI(1, "Error closing temporary reparsepoint open"); 238 cFYI(1, "Error closing temporary reparsepoint open");
228 } 239 }
229 } 240 }
230 } 241 }
231 */ 242 */
232 243
233 static int 244 static int
234 initiate_cifs_search(const unsigned int xid, struct file *file) 245 initiate_cifs_search(const unsigned int xid, struct file *file)
235 { 246 {
236 __u16 search_flags; 247 __u16 search_flags;
237 int rc = 0; 248 int rc = 0;
238 char *full_path = NULL; 249 char *full_path = NULL;
239 struct cifsFileInfo *cifsFile; 250 struct cifsFileInfo *cifsFile;
240 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 251 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
241 struct tcon_link *tlink = NULL; 252 struct tcon_link *tlink = NULL;
242 struct cifs_tcon *tcon; 253 struct cifs_tcon *tcon;
243 struct TCP_Server_Info *server; 254 struct TCP_Server_Info *server;
244 255
245 if (file->private_data == NULL) { 256 if (file->private_data == NULL) {
246 tlink = cifs_sb_tlink(cifs_sb); 257 tlink = cifs_sb_tlink(cifs_sb);
247 if (IS_ERR(tlink)) 258 if (IS_ERR(tlink))
248 return PTR_ERR(tlink); 259 return PTR_ERR(tlink);
249 260
250 cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 261 cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
251 if (cifsFile == NULL) { 262 if (cifsFile == NULL) {
252 rc = -ENOMEM; 263 rc = -ENOMEM;
253 goto error_exit; 264 goto error_exit;
254 } 265 }
255 file->private_data = cifsFile; 266 file->private_data = cifsFile;
256 cifsFile->tlink = cifs_get_tlink(tlink); 267 cifsFile->tlink = cifs_get_tlink(tlink);
257 tcon = tlink_tcon(tlink); 268 tcon = tlink_tcon(tlink);
258 } else { 269 } else {
259 cifsFile = file->private_data; 270 cifsFile = file->private_data;
260 tcon = tlink_tcon(cifsFile->tlink); 271 tcon = tlink_tcon(cifsFile->tlink);
261 } 272 }
262 273
263 server = tcon->ses->server; 274 server = tcon->ses->server;
264 275
265 if (!server->ops->query_dir_first) { 276 if (!server->ops->query_dir_first) {
266 rc = -ENOSYS; 277 rc = -ENOSYS;
267 goto error_exit; 278 goto error_exit;
268 } 279 }
269 280
270 cifsFile->invalidHandle = true; 281 cifsFile->invalidHandle = true;
271 cifsFile->srch_inf.endOfSearch = false; 282 cifsFile->srch_inf.endOfSearch = false;
272 283
273 full_path = build_path_from_dentry(file->f_path.dentry); 284 full_path = build_path_from_dentry(file->f_path.dentry);
274 if (full_path == NULL) { 285 if (full_path == NULL) {
275 rc = -ENOMEM; 286 rc = -ENOMEM;
276 goto error_exit; 287 goto error_exit;
277 } 288 }
278 289
279 cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos); 290 cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos);
280 291
281 ffirst_retry: 292 ffirst_retry:
282 /* test for Unix extensions */ 293 /* test for Unix extensions */
283 /* but now check for them on the share/mount not on the SMB session */ 294 /* but now check for them on the share/mount not on the SMB session */
284 /* if (cap_unix(tcon->ses) { */ 295 /* if (cap_unix(tcon->ses) { */
285 if (tcon->unix_ext) 296 if (tcon->unix_ext)
286 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; 297 cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
287 else if ((tcon->ses->capabilities & 298 else if ((tcon->ses->capabilities &
288 tcon->ses->server->vals->cap_nt_find) == 0) { 299 tcon->ses->server->vals->cap_nt_find) == 0) {
289 cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD; 300 cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
290 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 301 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
291 cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO; 302 cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
292 } else /* not srvinos - BB fixme add check for backlevel? */ { 303 } else /* not srvinos - BB fixme add check for backlevel? */ {
293 cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; 304 cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO;
294 } 305 }
295 306
296 search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; 307 search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
297 if (backup_cred(cifs_sb)) 308 if (backup_cred(cifs_sb))
298 search_flags |= CIFS_SEARCH_BACKUP_SEARCH; 309 search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
299 310
300 rc = server->ops->query_dir_first(xid, tcon, full_path, cifs_sb, 311 rc = server->ops->query_dir_first(xid, tcon, full_path, cifs_sb,
301 &cifsFile->fid, search_flags, 312 &cifsFile->fid, search_flags,
302 &cifsFile->srch_inf); 313 &cifsFile->srch_inf);
303 314
304 if (rc == 0) 315 if (rc == 0)
305 cifsFile->invalidHandle = false; 316 cifsFile->invalidHandle = false;
306 /* BB add following call to handle readdir on new NTFS symlink errors 317 /* BB add following call to handle readdir on new NTFS symlink errors
307 else if STATUS_STOPPED_ON_SYMLINK 318 else if STATUS_STOPPED_ON_SYMLINK
308 call get_symlink_reparse_path and retry with new path */ 319 call get_symlink_reparse_path and retry with new path */
309 else if ((rc == -EOPNOTSUPP) && 320 else if ((rc == -EOPNOTSUPP) &&
310 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { 321 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
311 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; 322 cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
312 goto ffirst_retry; 323 goto ffirst_retry;
313 } 324 }
314 error_exit: 325 error_exit:
315 kfree(full_path); 326 kfree(full_path);
316 cifs_put_tlink(tlink); 327 cifs_put_tlink(tlink);
317 return rc; 328 return rc;
318 } 329 }
319 330
320 /* return length of unicode string in bytes */ 331 /* return length of unicode string in bytes */
321 static int cifs_unicode_bytelen(const char *str) 332 static int cifs_unicode_bytelen(const char *str)
322 { 333 {
323 int len; 334 int len;
324 const __le16 *ustr = (const __le16 *)str; 335 const __le16 *ustr = (const __le16 *)str;
325 336
326 for (len = 0; len <= PATH_MAX; len++) { 337 for (len = 0; len <= PATH_MAX; len++) {
327 if (ustr[len] == 0) 338 if (ustr[len] == 0)
328 return len << 1; 339 return len << 1;
329 } 340 }
330 cFYI(1, "Unicode string longer than PATH_MAX found"); 341 cFYI(1, "Unicode string longer than PATH_MAX found");
331 return len << 1; 342 return len << 1;
332 } 343 }
333 344
334 static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level) 345 static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
335 { 346 {
336 char *new_entry; 347 char *new_entry;
337 FILE_DIRECTORY_INFO *pDirInfo = (FILE_DIRECTORY_INFO *)old_entry; 348 FILE_DIRECTORY_INFO *pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
338 349
339 if (level == SMB_FIND_FILE_INFO_STANDARD) { 350 if (level == SMB_FIND_FILE_INFO_STANDARD) {
340 FIND_FILE_STANDARD_INFO *pfData; 351 FIND_FILE_STANDARD_INFO *pfData;
341 pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo; 352 pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
342 353
343 new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) + 354 new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
344 pfData->FileNameLength; 355 pfData->FileNameLength;
345 } else 356 } else
346 new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset); 357 new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
347 cFYI(1, "new entry %p old entry %p", new_entry, old_entry); 358 cFYI(1, "new entry %p old entry %p", new_entry, old_entry);
348 /* validate that new_entry is not past end of SMB */ 359 /* validate that new_entry is not past end of SMB */
349 if (new_entry >= end_of_smb) { 360 if (new_entry >= end_of_smb) {
350 cERROR(1, "search entry %p began after end of SMB %p old entry %p", 361 cERROR(1, "search entry %p began after end of SMB %p old entry %p",
351 new_entry, end_of_smb, old_entry); 362 new_entry, end_of_smb, old_entry);
352 return NULL; 363 return NULL;
353 } else if (((level == SMB_FIND_FILE_INFO_STANDARD) && 364 } else if (((level == SMB_FIND_FILE_INFO_STANDARD) &&
354 (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) 365 (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb))
355 || ((level != SMB_FIND_FILE_INFO_STANDARD) && 366 || ((level != SMB_FIND_FILE_INFO_STANDARD) &&
356 (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) { 367 (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) {
357 cERROR(1, "search entry %p extends after end of SMB %p", 368 cERROR(1, "search entry %p extends after end of SMB %p",
358 new_entry, end_of_smb); 369 new_entry, end_of_smb);
359 return NULL; 370 return NULL;
360 } else 371 } else
361 return new_entry; 372 return new_entry;
362 373
363 } 374 }
364 375
365 struct cifs_dirent { 376 struct cifs_dirent {
366 const char *name; 377 const char *name;
367 size_t namelen; 378 size_t namelen;
368 u32 resume_key; 379 u32 resume_key;
369 u64 ino; 380 u64 ino;
370 }; 381 };
371 382
372 static void cifs_fill_dirent_unix(struct cifs_dirent *de, 383 static void cifs_fill_dirent_unix(struct cifs_dirent *de,
373 const FILE_UNIX_INFO *info, bool is_unicode) 384 const FILE_UNIX_INFO *info, bool is_unicode)
374 { 385 {
375 de->name = &info->FileName[0]; 386 de->name = &info->FileName[0];
376 if (is_unicode) 387 if (is_unicode)
377 de->namelen = cifs_unicode_bytelen(de->name); 388 de->namelen = cifs_unicode_bytelen(de->name);
378 else 389 else
379 de->namelen = strnlen(de->name, PATH_MAX); 390 de->namelen = strnlen(de->name, PATH_MAX);
380 de->resume_key = info->ResumeKey; 391 de->resume_key = info->ResumeKey;
381 de->ino = le64_to_cpu(info->basic.UniqueId); 392 de->ino = le64_to_cpu(info->basic.UniqueId);
382 } 393 }
383 394
384 static void cifs_fill_dirent_dir(struct cifs_dirent *de, 395 static void cifs_fill_dirent_dir(struct cifs_dirent *de,
385 const FILE_DIRECTORY_INFO *info) 396 const FILE_DIRECTORY_INFO *info)
386 { 397 {
387 de->name = &info->FileName[0]; 398 de->name = &info->FileName[0];
388 de->namelen = le32_to_cpu(info->FileNameLength); 399 de->namelen = le32_to_cpu(info->FileNameLength);
389 de->resume_key = info->FileIndex; 400 de->resume_key = info->FileIndex;
390 } 401 }
391 402
392 static void cifs_fill_dirent_full(struct cifs_dirent *de, 403 static void cifs_fill_dirent_full(struct cifs_dirent *de,
393 const FILE_FULL_DIRECTORY_INFO *info) 404 const FILE_FULL_DIRECTORY_INFO *info)
394 { 405 {
395 de->name = &info->FileName[0]; 406 de->name = &info->FileName[0];
396 de->namelen = le32_to_cpu(info->FileNameLength); 407 de->namelen = le32_to_cpu(info->FileNameLength);
397 de->resume_key = info->FileIndex; 408 de->resume_key = info->FileIndex;
398 } 409 }
399 410
400 static void cifs_fill_dirent_search(struct cifs_dirent *de, 411 static void cifs_fill_dirent_search(struct cifs_dirent *de,
401 const SEARCH_ID_FULL_DIR_INFO *info) 412 const SEARCH_ID_FULL_DIR_INFO *info)
402 { 413 {
403 de->name = &info->FileName[0]; 414 de->name = &info->FileName[0];
404 de->namelen = le32_to_cpu(info->FileNameLength); 415 de->namelen = le32_to_cpu(info->FileNameLength);
405 de->resume_key = info->FileIndex; 416 de->resume_key = info->FileIndex;
406 de->ino = le64_to_cpu(info->UniqueId); 417 de->ino = le64_to_cpu(info->UniqueId);
407 } 418 }
408 419
409 static void cifs_fill_dirent_both(struct cifs_dirent *de, 420 static void cifs_fill_dirent_both(struct cifs_dirent *de,
410 const FILE_BOTH_DIRECTORY_INFO *info) 421 const FILE_BOTH_DIRECTORY_INFO *info)
411 { 422 {
412 de->name = &info->FileName[0]; 423 de->name = &info->FileName[0];
413 de->namelen = le32_to_cpu(info->FileNameLength); 424 de->namelen = le32_to_cpu(info->FileNameLength);
414 de->resume_key = info->FileIndex; 425 de->resume_key = info->FileIndex;
415 } 426 }
416 427
417 static void cifs_fill_dirent_std(struct cifs_dirent *de, 428 static void cifs_fill_dirent_std(struct cifs_dirent *de,
418 const FIND_FILE_STANDARD_INFO *info) 429 const FIND_FILE_STANDARD_INFO *info)
419 { 430 {
420 de->name = &info->FileName[0]; 431 de->name = &info->FileName[0];
421 /* one byte length, no endianess conversion */ 432 /* one byte length, no endianess conversion */
422 de->namelen = info->FileNameLength; 433 de->namelen = info->FileNameLength;
423 de->resume_key = info->ResumeKey; 434 de->resume_key = info->ResumeKey;
424 } 435 }
425 436
426 static int cifs_fill_dirent(struct cifs_dirent *de, const void *info, 437 static int cifs_fill_dirent(struct cifs_dirent *de, const void *info,
427 u16 level, bool is_unicode) 438 u16 level, bool is_unicode)
428 { 439 {
429 memset(de, 0, sizeof(*de)); 440 memset(de, 0, sizeof(*de));
430 441
431 switch (level) { 442 switch (level) {
432 case SMB_FIND_FILE_UNIX: 443 case SMB_FIND_FILE_UNIX:
433 cifs_fill_dirent_unix(de, info, is_unicode); 444 cifs_fill_dirent_unix(de, info, is_unicode);
434 break; 445 break;
435 case SMB_FIND_FILE_DIRECTORY_INFO: 446 case SMB_FIND_FILE_DIRECTORY_INFO:
436 cifs_fill_dirent_dir(de, info); 447 cifs_fill_dirent_dir(de, info);
437 break; 448 break;
438 case SMB_FIND_FILE_FULL_DIRECTORY_INFO: 449 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
439 cifs_fill_dirent_full(de, info); 450 cifs_fill_dirent_full(de, info);
440 break; 451 break;
441 case SMB_FIND_FILE_ID_FULL_DIR_INFO: 452 case SMB_FIND_FILE_ID_FULL_DIR_INFO:
442 cifs_fill_dirent_search(de, info); 453 cifs_fill_dirent_search(de, info);
443 break; 454 break;
444 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: 455 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
445 cifs_fill_dirent_both(de, info); 456 cifs_fill_dirent_both(de, info);
446 break; 457 break;
447 case SMB_FIND_FILE_INFO_STANDARD: 458 case SMB_FIND_FILE_INFO_STANDARD:
448 cifs_fill_dirent_std(de, info); 459 cifs_fill_dirent_std(de, info);
449 break; 460 break;
450 default: 461 default:
451 cFYI(1, "Unknown findfirst level %d", level); 462 cFYI(1, "Unknown findfirst level %d", level);
452 return -EINVAL; 463 return -EINVAL;
453 } 464 }
454 465
455 return 0; 466 return 0;
456 } 467 }
457 468
458 #define UNICODE_DOT cpu_to_le16(0x2e) 469 #define UNICODE_DOT cpu_to_le16(0x2e)
459 470
460 /* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */ 471 /* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */
461 static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode) 472 static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode)
462 { 473 {
463 int rc = 0; 474 int rc = 0;
464 475
465 if (!de->name) 476 if (!de->name)
466 return 0; 477 return 0;
467 478
468 if (is_unicode) { 479 if (is_unicode) {
469 __le16 *ufilename = (__le16 *)de->name; 480 __le16 *ufilename = (__le16 *)de->name;
470 if (de->namelen == 2) { 481 if (de->namelen == 2) {
471 /* check for . */ 482 /* check for . */
472 if (ufilename[0] == UNICODE_DOT) 483 if (ufilename[0] == UNICODE_DOT)
473 rc = 1; 484 rc = 1;
474 } else if (de->namelen == 4) { 485 } else if (de->namelen == 4) {
475 /* check for .. */ 486 /* check for .. */
476 if (ufilename[0] == UNICODE_DOT && 487 if (ufilename[0] == UNICODE_DOT &&
477 ufilename[1] == UNICODE_DOT) 488 ufilename[1] == UNICODE_DOT)
478 rc = 2; 489 rc = 2;
479 } 490 }
480 } else /* ASCII */ { 491 } else /* ASCII */ {
481 if (de->namelen == 1) { 492 if (de->namelen == 1) {
482 if (de->name[0] == '.') 493 if (de->name[0] == '.')
483 rc = 1; 494 rc = 1;
484 } else if (de->namelen == 2) { 495 } else if (de->namelen == 2) {
485 if (de->name[0] == '.' && de->name[1] == '.') 496 if (de->name[0] == '.' && de->name[1] == '.')
486 rc = 2; 497 rc = 2;
487 } 498 }
488 } 499 }
489 500
490 return rc; 501 return rc;
491 } 502 }
492 503
493 /* Check if directory that we are searching has changed so we can decide 504 /* Check if directory that we are searching has changed so we can decide
494 whether we can use the cached search results from the previous search */ 505 whether we can use the cached search results from the previous search */
495 static int is_dir_changed(struct file *file) 506 static int is_dir_changed(struct file *file)
496 { 507 {
497 struct inode *inode = file->f_path.dentry->d_inode; 508 struct inode *inode = file->f_path.dentry->d_inode;
498 struct cifsInodeInfo *cifsInfo = CIFS_I(inode); 509 struct cifsInodeInfo *cifsInfo = CIFS_I(inode);
499 510
500 if (cifsInfo->time == 0) 511 if (cifsInfo->time == 0)
501 return 1; /* directory was changed, perhaps due to unlink */ 512 return 1; /* directory was changed, perhaps due to unlink */
502 else 513 else
503 return 0; 514 return 0;
504 515
505 } 516 }
506 517
507 static int cifs_save_resume_key(const char *current_entry, 518 static int cifs_save_resume_key(const char *current_entry,
508 struct cifsFileInfo *file_info) 519 struct cifsFileInfo *file_info)
509 { 520 {
510 struct cifs_dirent de; 521 struct cifs_dirent de;
511 int rc; 522 int rc;
512 523
513 rc = cifs_fill_dirent(&de, current_entry, file_info->srch_inf.info_level, 524 rc = cifs_fill_dirent(&de, current_entry, file_info->srch_inf.info_level,
514 file_info->srch_inf.unicode); 525 file_info->srch_inf.unicode);
515 if (!rc) { 526 if (!rc) {
516 file_info->srch_inf.presume_name = de.name; 527 file_info->srch_inf.presume_name = de.name;
517 file_info->srch_inf.resume_name_len = de.namelen; 528 file_info->srch_inf.resume_name_len = de.namelen;
518 file_info->srch_inf.resume_key = de.resume_key; 529 file_info->srch_inf.resume_key = de.resume_key;
519 } 530 }
520 return rc; 531 return rc;
521 } 532 }
522 533
523 /* 534 /*
524 * Find the corresponding entry in the search. Note that the SMB server returns 535 * Find the corresponding entry in the search. Note that the SMB server returns
525 * search entries for . and .. which complicates logic here if we choose to 536 * search entries for . and .. which complicates logic here if we choose to
526 * parse for them and we do not assume that they are located in the findfirst 537 * parse for them and we do not assume that they are located in the findfirst
527 * return buffer. We start counting in the buffer with entry 2 and increment for 538 * return buffer. We start counting in the buffer with entry 2 and increment for
528 * every entry (do not increment for . or .. entry). 539 * every entry (do not increment for . or .. entry).
529 */ 540 */
530 static int 541 static int
531 find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, 542 find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon,
532 struct file *file, char **current_entry, int *num_to_ret) 543 struct file *file, char **current_entry, int *num_to_ret)
533 { 544 {
534 __u16 search_flags; 545 __u16 search_flags;
535 int rc = 0; 546 int rc = 0;
536 int pos_in_buf = 0; 547 int pos_in_buf = 0;
537 loff_t first_entry_in_buffer; 548 loff_t first_entry_in_buffer;
538 loff_t index_to_find = file->f_pos; 549 loff_t index_to_find = file->f_pos;
539 struct cifsFileInfo *cfile = file->private_data; 550 struct cifsFileInfo *cfile = file->private_data;
540 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 551 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
541 struct TCP_Server_Info *server = tcon->ses->server; 552 struct TCP_Server_Info *server = tcon->ses->server;
542 /* check if index in the buffer */ 553 /* check if index in the buffer */
543 554
544 if (!server->ops->query_dir_first || !server->ops->query_dir_next) 555 if (!server->ops->query_dir_first || !server->ops->query_dir_next)
545 return -ENOSYS; 556 return -ENOSYS;
546 557
547 if ((cfile == NULL) || (current_entry == NULL) || (num_to_ret == NULL)) 558 if ((cfile == NULL) || (current_entry == NULL) || (num_to_ret == NULL))
548 return -ENOENT; 559 return -ENOENT;
549 560
550 *current_entry = NULL; 561 *current_entry = NULL;
551 first_entry_in_buffer = cfile->srch_inf.index_of_last_entry - 562 first_entry_in_buffer = cfile->srch_inf.index_of_last_entry -
552 cfile->srch_inf.entries_in_buffer; 563 cfile->srch_inf.entries_in_buffer;
553 564
554 /* 565 /*
555 * If first entry in buf is zero then is first buffer 566 * If first entry in buf is zero then is first buffer
556 * in search response data which means it is likely . and .. 567 * in search response data which means it is likely . and ..
557 * will be in this buffer, although some servers do not return 568 * will be in this buffer, although some servers do not return
558 * . and .. for the root of a drive and for those we need 569 * . and .. for the root of a drive and for those we need
559 * to start two entries earlier. 570 * to start two entries earlier.
560 */ 571 */
561 572
562 dump_cifs_file_struct(file, "In fce "); 573 dump_cifs_file_struct(file, "In fce ");
563 if (((index_to_find < cfile->srch_inf.index_of_last_entry) && 574 if (((index_to_find < cfile->srch_inf.index_of_last_entry) &&
564 is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) { 575 is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) {
565 /* close and restart search */ 576 /* close and restart search */
566 cFYI(1, "search backing up - close and restart search"); 577 cFYI(1, "search backing up - close and restart search");
567 spin_lock(&cifs_file_list_lock); 578 spin_lock(&cifs_file_list_lock);
568 if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) { 579 if (!cfile->srch_inf.endOfSearch && !cfile->invalidHandle) {
569 cfile->invalidHandle = true; 580 cfile->invalidHandle = true;
570 spin_unlock(&cifs_file_list_lock); 581 spin_unlock(&cifs_file_list_lock);
571 if (server->ops->close) 582 if (server->ops->close)
572 server->ops->close(xid, tcon, &cfile->fid); 583 server->ops->close(xid, tcon, &cfile->fid);
573 } else 584 } else
574 spin_unlock(&cifs_file_list_lock); 585 spin_unlock(&cifs_file_list_lock);
575 if (cfile->srch_inf.ntwrk_buf_start) { 586 if (cfile->srch_inf.ntwrk_buf_start) {
576 cFYI(1, "freeing SMB ff cache buf on search rewind"); 587 cFYI(1, "freeing SMB ff cache buf on search rewind");
577 if (cfile->srch_inf.smallBuf) 588 if (cfile->srch_inf.smallBuf)
578 cifs_small_buf_release(cfile->srch_inf. 589 cifs_small_buf_release(cfile->srch_inf.
579 ntwrk_buf_start); 590 ntwrk_buf_start);
580 else 591 else
581 cifs_buf_release(cfile->srch_inf. 592 cifs_buf_release(cfile->srch_inf.
582 ntwrk_buf_start); 593 ntwrk_buf_start);
583 cfile->srch_inf.ntwrk_buf_start = NULL; 594 cfile->srch_inf.ntwrk_buf_start = NULL;
584 } 595 }
585 rc = initiate_cifs_search(xid, file); 596 rc = initiate_cifs_search(xid, file);
586 if (rc) { 597 if (rc) {
587 cFYI(1, "error %d reinitiating a search on rewind", 598 cFYI(1, "error %d reinitiating a search on rewind",
588 rc); 599 rc);
589 return rc; 600 return rc;
590 } 601 }
591 /* FindFirst/Next set last_entry to NULL on malformed reply */ 602 /* FindFirst/Next set last_entry to NULL on malformed reply */
592 if (cfile->srch_inf.last_entry) 603 if (cfile->srch_inf.last_entry)
593 cifs_save_resume_key(cfile->srch_inf.last_entry, cfile); 604 cifs_save_resume_key(cfile->srch_inf.last_entry, cfile);
594 } 605 }
595 606
596 search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; 607 search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME;
597 if (backup_cred(cifs_sb)) 608 if (backup_cred(cifs_sb))
598 search_flags |= CIFS_SEARCH_BACKUP_SEARCH; 609 search_flags |= CIFS_SEARCH_BACKUP_SEARCH;
599 610
600 while ((index_to_find >= cfile->srch_inf.index_of_last_entry) && 611 while ((index_to_find >= cfile->srch_inf.index_of_last_entry) &&
601 (rc == 0) && !cfile->srch_inf.endOfSearch) { 612 (rc == 0) && !cfile->srch_inf.endOfSearch) {
602 cFYI(1, "calling findnext2"); 613 cFYI(1, "calling findnext2");
603 rc = server->ops->query_dir_next(xid, tcon, &cfile->fid, 614 rc = server->ops->query_dir_next(xid, tcon, &cfile->fid,
604 search_flags, 615 search_flags,
605 &cfile->srch_inf); 616 &cfile->srch_inf);
606 /* FindFirst/Next set last_entry to NULL on malformed reply */ 617 /* FindFirst/Next set last_entry to NULL on malformed reply */
607 if (cfile->srch_inf.last_entry) 618 if (cfile->srch_inf.last_entry)
608 cifs_save_resume_key(cfile->srch_inf.last_entry, cfile); 619 cifs_save_resume_key(cfile->srch_inf.last_entry, cfile);
609 if (rc) 620 if (rc)
610 return -ENOENT; 621 return -ENOENT;
611 } 622 }
612 if (index_to_find < cfile->srch_inf.index_of_last_entry) { 623 if (index_to_find < cfile->srch_inf.index_of_last_entry) {
613 /* we found the buffer that contains the entry */ 624 /* we found the buffer that contains the entry */
614 /* scan and find it */ 625 /* scan and find it */
615 int i; 626 int i;
616 char *cur_ent; 627 char *cur_ent;
617 char *end_of_smb = cfile->srch_inf.ntwrk_buf_start + 628 char *end_of_smb = cfile->srch_inf.ntwrk_buf_start +
618 server->ops->calc_smb_size( 629 server->ops->calc_smb_size(
619 cfile->srch_inf.ntwrk_buf_start); 630 cfile->srch_inf.ntwrk_buf_start);
620 631
621 cur_ent = cfile->srch_inf.srch_entries_start; 632 cur_ent = cfile->srch_inf.srch_entries_start;
622 first_entry_in_buffer = cfile->srch_inf.index_of_last_entry 633 first_entry_in_buffer = cfile->srch_inf.index_of_last_entry
623 - cfile->srch_inf.entries_in_buffer; 634 - cfile->srch_inf.entries_in_buffer;
624 pos_in_buf = index_to_find - first_entry_in_buffer; 635 pos_in_buf = index_to_find - first_entry_in_buffer;
625 cFYI(1, "found entry - pos_in_buf %d", pos_in_buf); 636 cFYI(1, "found entry - pos_in_buf %d", pos_in_buf);
626 637
627 for (i = 0; (i < (pos_in_buf)) && (cur_ent != NULL); i++) { 638 for (i = 0; (i < (pos_in_buf)) && (cur_ent != NULL); i++) {
628 /* go entry by entry figuring out which is first */ 639 /* go entry by entry figuring out which is first */
629 cur_ent = nxt_dir_entry(cur_ent, end_of_smb, 640 cur_ent = nxt_dir_entry(cur_ent, end_of_smb,
630 cfile->srch_inf.info_level); 641 cfile->srch_inf.info_level);
631 } 642 }
632 if ((cur_ent == NULL) && (i < pos_in_buf)) { 643 if ((cur_ent == NULL) && (i < pos_in_buf)) {
633 /* BB fixme - check if we should flag this error */ 644 /* BB fixme - check if we should flag this error */
634 cERROR(1, "reached end of buf searching for pos in buf" 645 cERROR(1, "reached end of buf searching for pos in buf"
635 " %d index to find %lld rc %d", pos_in_buf, 646 " %d index to find %lld rc %d", pos_in_buf,
636 index_to_find, rc); 647 index_to_find, rc);
637 } 648 }
638 rc = 0; 649 rc = 0;
639 *current_entry = cur_ent; 650 *current_entry = cur_ent;
640 } else { 651 } else {
641 cFYI(1, "index not in buffer - could not findnext into it"); 652 cFYI(1, "index not in buffer - could not findnext into it");
642 return 0; 653 return 0;
643 } 654 }
644 655
645 if (pos_in_buf >= cfile->srch_inf.entries_in_buffer) { 656 if (pos_in_buf >= cfile->srch_inf.entries_in_buffer) {
646 cFYI(1, "can not return entries pos_in_buf beyond last"); 657 cFYI(1, "can not return entries pos_in_buf beyond last");
647 *num_to_ret = 0; 658 *num_to_ret = 0;
648 } else 659 } else
649 *num_to_ret = cfile->srch_inf.entries_in_buffer - pos_in_buf; 660 *num_to_ret = cfile->srch_inf.entries_in_buffer - pos_in_buf;
650 661
651 return rc; 662 return rc;
652 } 663 }
653 664
654 static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, 665 static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir,
655 void *dirent, char *scratch_buf, unsigned int max_len) 666 void *dirent, char *scratch_buf, unsigned int max_len)
656 { 667 {
657 struct cifsFileInfo *file_info = file->private_data; 668 struct cifsFileInfo *file_info = file->private_data;
658 struct super_block *sb = file->f_path.dentry->d_sb; 669 struct super_block *sb = file->f_path.dentry->d_sb;
659 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 670 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
660 struct cifs_dirent de = { NULL, }; 671 struct cifs_dirent de = { NULL, };
661 struct cifs_fattr fattr; 672 struct cifs_fattr fattr;
662 struct qstr name; 673 struct qstr name;
663 int rc = 0; 674 int rc = 0;
664 ino_t ino; 675 ino_t ino;
665 676
666 rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level, 677 rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level,
667 file_info->srch_inf.unicode); 678 file_info->srch_inf.unicode);
668 if (rc) 679 if (rc)
669 return rc; 680 return rc;
670 681
671 if (de.namelen > max_len) { 682 if (de.namelen > max_len) {
672 cERROR(1, "bad search response length %zd past smb end", 683 cERROR(1, "bad search response length %zd past smb end",
673 de.namelen); 684 de.namelen);
674 return -EINVAL; 685 return -EINVAL;
675 } 686 }
676 687
677 /* skip . and .. since we added them first */ 688 /* skip . and .. since we added them first */
678 if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode)) 689 if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode))
679 return 0; 690 return 0;
680 691
681 if (file_info->srch_inf.unicode) { 692 if (file_info->srch_inf.unicode) {
682 struct nls_table *nlt = cifs_sb->local_nls; 693 struct nls_table *nlt = cifs_sb->local_nls;
683 694
684 name.name = scratch_buf; 695 name.name = scratch_buf;
685 name.len = 696 name.len =
686 cifs_from_utf16((char *)name.name, (__le16 *)de.name, 697 cifs_from_utf16((char *)name.name, (__le16 *)de.name,
687 UNICODE_NAME_MAX, 698 UNICODE_NAME_MAX,
688 min_t(size_t, de.namelen, 699 min_t(size_t, de.namelen,
689 (size_t)max_len), nlt, 700 (size_t)max_len), nlt,
690 cifs_sb->mnt_cifs_flags & 701 cifs_sb->mnt_cifs_flags &
691 CIFS_MOUNT_MAP_SPECIAL_CHR); 702 CIFS_MOUNT_MAP_SPECIAL_CHR);
692 name.len -= nls_nullsize(nlt); 703 name.len -= nls_nullsize(nlt);
693 } else { 704 } else {
694 name.name = de.name; 705 name.name = de.name;
695 name.len = de.namelen; 706 name.len = de.namelen;
696 } 707 }
697 708
698 switch (file_info->srch_inf.info_level) { 709 switch (file_info->srch_inf.info_level) {
699 case SMB_FIND_FILE_UNIX: 710 case SMB_FIND_FILE_UNIX:
700 cifs_unix_basic_to_fattr(&fattr, 711 cifs_unix_basic_to_fattr(&fattr,
701 &((FILE_UNIX_INFO *)find_entry)->basic, 712 &((FILE_UNIX_INFO *)find_entry)->basic,
702 cifs_sb); 713 cifs_sb);
703 break; 714 break;
704 case SMB_FIND_FILE_INFO_STANDARD: 715 case SMB_FIND_FILE_INFO_STANDARD:
705 cifs_std_info_to_fattr(&fattr, 716 cifs_std_info_to_fattr(&fattr,
706 (FIND_FILE_STANDARD_INFO *)find_entry, 717 (FIND_FILE_STANDARD_INFO *)find_entry,
707 cifs_sb); 718 cifs_sb);
708 break; 719 break;
709 default: 720 default:
710 cifs_dir_info_to_fattr(&fattr, 721 cifs_dir_info_to_fattr(&fattr,
711 (FILE_DIRECTORY_INFO *)find_entry, 722 (FILE_DIRECTORY_INFO *)find_entry,
712 cifs_sb); 723 cifs_sb);
713 break; 724 break;
714 } 725 }
715 726
716 if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { 727 if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
717 fattr.cf_uniqueid = de.ino; 728 fattr.cf_uniqueid = de.ino;
718 } else { 729 } else {
719 fattr.cf_uniqueid = iunique(sb, ROOT_I); 730 fattr.cf_uniqueid = iunique(sb, ROOT_I);
720 cifs_autodisable_serverino(cifs_sb); 731 cifs_autodisable_serverino(cifs_sb);
721 } 732 }
722 733
723 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && 734 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
724 CIFSCouldBeMFSymlink(&fattr)) 735 CIFSCouldBeMFSymlink(&fattr))
725 /* 736 /*
726 * trying to get the type and mode can be slow, 737 * trying to get the type and mode can be slow,
727 * so just call those regular files for now, and mark 738 * so just call those regular files for now, and mark
728 * for reval 739 * for reval
729 */ 740 */
730 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; 741 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
731 742
732 cifs_prime_dcache(file->f_dentry, &name, &fattr); 743 cifs_prime_dcache(file->f_dentry, &name, &fattr);
733 744
734 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); 745 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
735 rc = filldir(dirent, name.name, name.len, file->f_pos, ino, 746 rc = filldir(dirent, name.name, name.len, file->f_pos, ino,
736 fattr.cf_dtype); 747 fattr.cf_dtype);
737 return rc; 748 return rc;
738 } 749 }
739 750
740 751
741 int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) 752 int cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
742 { 753 {
743 int rc = 0; 754 int rc = 0;
744 unsigned int xid; 755 unsigned int xid;
745 int i; 756 int i;
746 struct cifs_tcon *tcon; 757 struct cifs_tcon *tcon;
747 struct cifsFileInfo *cifsFile = NULL; 758 struct cifsFileInfo *cifsFile = NULL;
748 char *current_entry; 759 char *current_entry;
749 int num_to_fill = 0; 760 int num_to_fill = 0;
750 char *tmp_buf = NULL; 761 char *tmp_buf = NULL;
751 char *end_of_smb; 762 char *end_of_smb;
752 unsigned int max_len; 763 unsigned int max_len;
753 764
754 xid = get_xid(); 765 xid = get_xid();
755 766
756 /* 767 /*
757 * Ensure FindFirst doesn't fail before doing filldir() for '.' and 768 * Ensure FindFirst doesn't fail before doing filldir() for '.' and
758 * '..'. Otherwise we won't be able to notify VFS in case of failure. 769 * '..'. Otherwise we won't be able to notify VFS in case of failure.
759 */ 770 */
760 if (file->private_data == NULL) { 771 if (file->private_data == NULL) {
761 rc = initiate_cifs_search(xid, file); 772 rc = initiate_cifs_search(xid, file);
762 cFYI(1, "initiate cifs search rc %d", rc); 773 cFYI(1, "initiate cifs search rc %d", rc);
763 if (rc) 774 if (rc)
764 goto rddir2_exit; 775 goto rddir2_exit;
765 } 776 }
766 777
767 switch ((int) file->f_pos) { 778 switch ((int) file->f_pos) {
768 case 0: 779 case 0:
769 if (filldir(direntry, ".", 1, file->f_pos, 780 if (filldir(direntry, ".", 1, file->f_pos,
770 file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) { 781 file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) {
771 cERROR(1, "Filldir for current dir failed"); 782 cERROR(1, "Filldir for current dir failed");
772 rc = -ENOMEM; 783 rc = -ENOMEM;
773 break; 784 break;
774 } 785 }
775 file->f_pos++; 786 file->f_pos++;
776 case 1: 787 case 1:
777 if (filldir(direntry, "..", 2, file->f_pos, 788 if (filldir(direntry, "..", 2, file->f_pos,
778 parent_ino(file->f_path.dentry), DT_DIR) < 0) { 789 parent_ino(file->f_path.dentry), DT_DIR) < 0) {
779 cERROR(1, "Filldir for parent dir failed"); 790 cERROR(1, "Filldir for parent dir failed");
780 rc = -ENOMEM; 791 rc = -ENOMEM;
781 break; 792 break;
782 } 793 }
783 file->f_pos++; 794 file->f_pos++;
784 default: 795 default:
785 /* 1) If search is active, 796 /* 1) If search is active,
786 is in current search buffer? 797 is in current search buffer?
787 if it before then restart search 798 if it before then restart search
788 if after then keep searching till find it */ 799 if after then keep searching till find it */
789 800
790 if (file->private_data == NULL) { 801 if (file->private_data == NULL) {
791 rc = -EINVAL; 802 rc = -EINVAL;
792 free_xid(xid); 803 free_xid(xid);
793 return rc; 804 return rc;
794 } 805 }
795 cifsFile = file->private_data; 806 cifsFile = file->private_data;
796 if (cifsFile->srch_inf.endOfSearch) { 807 if (cifsFile->srch_inf.endOfSearch) {
797 if (cifsFile->srch_inf.emptyDir) { 808 if (cifsFile->srch_inf.emptyDir) {
798 cFYI(1, "End of search, empty dir"); 809 cFYI(1, "End of search, empty dir");
799 rc = 0; 810 rc = 0;
800 break; 811 break;
801 } 812 }
802 } /* else { 813 } /* else {
803 cifsFile->invalidHandle = true; 814 cifsFile->invalidHandle = true;
804 tcon->ses->server->close(xid, tcon, &cifsFile->fid); 815 tcon->ses->server->close(xid, tcon, &cifsFile->fid);
805 } */ 816 } */
806 817
807 tcon = tlink_tcon(cifsFile->tlink); 818 tcon = tlink_tcon(cifsFile->tlink);
808 rc = find_cifs_entry(xid, tcon, file, &current_entry, 819 rc = find_cifs_entry(xid, tcon, file, &current_entry,
809 &num_to_fill); 820 &num_to_fill);
810 if (rc) { 821 if (rc) {
811 cFYI(1, "fce error %d", rc); 822 cFYI(1, "fce error %d", rc);
812 goto rddir2_exit; 823 goto rddir2_exit;
813 } else if (current_entry != NULL) { 824 } else if (current_entry != NULL) {
814 cFYI(1, "entry %lld found", file->f_pos); 825 cFYI(1, "entry %lld found", file->f_pos);
815 } else { 826 } else {
816 cFYI(1, "could not find entry"); 827 cFYI(1, "could not find entry");
817 goto rddir2_exit; 828 goto rddir2_exit;
818 } 829 }
819 cFYI(1, "loop through %d times filling dir for net buf %p", 830 cFYI(1, "loop through %d times filling dir for net buf %p",
820 num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); 831 num_to_fill, cifsFile->srch_inf.ntwrk_buf_start);
821 max_len = tcon->ses->server->ops->calc_smb_size( 832 max_len = tcon->ses->server->ops->calc_smb_size(
822 cifsFile->srch_inf.ntwrk_buf_start); 833 cifsFile->srch_inf.ntwrk_buf_start);
823 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; 834 end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
824 835
825 tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); 836 tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
826 if (tmp_buf == NULL) { 837 if (tmp_buf == NULL) {
827 rc = -ENOMEM; 838 rc = -ENOMEM;
828 break; 839 break;
829 } 840 }
830 841
831 for (i = 0; (i < num_to_fill) && (rc == 0); i++) { 842 for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
832 if (current_entry == NULL) { 843 if (current_entry == NULL) {
833 /* evaluate whether this case is an error */ 844 /* evaluate whether this case is an error */
834 cERROR(1, "past SMB end, num to fill %d i %d", 845 cERROR(1, "past SMB end, num to fill %d i %d",
835 num_to_fill, i); 846 num_to_fill, i);
836 break; 847 break;
837 } 848 }
838 /* 849 /*
839 * if buggy server returns . and .. late do we want to 850 * if buggy server returns . and .. late do we want to
840 * check for that here? 851 * check for that here?
841 */ 852 */
842 rc = cifs_filldir(current_entry, file, filldir, 853 rc = cifs_filldir(current_entry, file, filldir,
843 direntry, tmp_buf, max_len); 854 direntry, tmp_buf, max_len);
844 if (rc == -EOVERFLOW) { 855 if (rc == -EOVERFLOW) {
845 rc = 0; 856 rc = 0;
846 break; 857 break;
847 } 858 }
848 859
849 file->f_pos++; 860 file->f_pos++;
850 if (file->f_pos == 861 if (file->f_pos ==
851 cifsFile->srch_inf.index_of_last_entry) { 862 cifsFile->srch_inf.index_of_last_entry) {
852 cFYI(1, "last entry in buf at pos %lld %s", 863 cFYI(1, "last entry in buf at pos %lld %s",
853 file->f_pos, tmp_buf); 864 file->f_pos, tmp_buf);
854 cifs_save_resume_key(current_entry, cifsFile); 865 cifs_save_resume_key(current_entry, cifsFile);
855 break; 866 break;
856 } else 867 } else
857 current_entry = 868 current_entry =
858 nxt_dir_entry(current_entry, end_of_smb, 869 nxt_dir_entry(current_entry, end_of_smb,
859 cifsFile->srch_inf.info_level); 870 cifsFile->srch_inf.info_level);
860 } 871 }
861 kfree(tmp_buf); 872 kfree(tmp_buf);
862 break; 873 break;
863 } /* end switch */ 874 } /* end switch */
864 875
865 rddir2_exit: 876 rddir2_exit:
866 free_xid(xid); 877 free_xid(xid);
867 return rc; 878 return rc;
868 } 879 }
869 880