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