This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / fs / cifs / file.c
1 /*
2  *   fs/cifs/file.c
3  *
4  *   vfs operations that deal with files
5  * 
6  *   Copyright (C) International Business Machines  Corp., 2002,2003
7  *   Author(s): Steve French (sfrench@us.ibm.com)
8  *
9  *   This library is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU Lesser General Public License as published
11  *   by the Free Software Foundation; either version 2.1 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This library is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU Lesser General Public License for more details.
18  *
19  *   You should have received a copy of the GNU Lesser General Public License
20  *   along with this library; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23 #include <linux/fs.h>
24 #include <linux/stat.h>
25 #include <linux/fcntl.h>
26 #include <linux/pagemap.h>
27 #include <linux/pagevec.h>
28 #include <linux/smp_lock.h>
29 #include <asm/div64.h>
30 #include "cifsfs.h"
31 #include "cifspdu.h"
32 #include "cifsglob.h"
33 #include "cifsproto.h"
34 #include "cifs_unicode.h"
35 #include "cifs_debug.h"
36 #include "cifs_fs_sb.h"
37
38 int
39 cifs_open(struct inode *inode, struct file *file)
40 {
41         int rc = -EACCES;
42         int xid, oplock;
43         struct cifs_sb_info *cifs_sb;
44         struct cifsTconInfo *pTcon;
45         struct cifsFileInfo *pCifsFile;
46         struct cifsInodeInfo *pCifsInode;
47         struct list_head * tmp;
48         char *full_path = NULL;
49         int desiredAccess = 0x20197;
50         int disposition;
51         __u16 netfid;
52         FILE_ALL_INFO * buf = NULL;
53
54         xid = GetXid();
55
56         cifs_sb = CIFS_SB(inode->i_sb);
57         pTcon = cifs_sb->tcon;
58
59         if (file->f_flags & O_CREAT) {
60                 /* search inode for this file and fill in file->private_data = */
61                 pCifsInode = CIFS_I(file->f_dentry->d_inode);
62                 read_lock(&GlobalSMBSeslock);
63                 list_for_each(tmp, &pCifsInode->openFileList) {            
64                         pCifsFile = list_entry(tmp,struct cifsFileInfo, flist);           
65                         if((pCifsFile->pfile == NULL)&& (pCifsFile->pid = current->pid)){
66                         /* mode set in cifs_create */
67                                 pCifsFile->pfile = file; /* needed for writepage */
68                                 file->private_data = pCifsFile;
69                                 break;
70                         }
71                 }
72                 read_unlock(&GlobalSMBSeslock);
73                 if(file->private_data != NULL) {
74                         rc = 0;
75                         FreeXid(xid);
76                         return rc;
77                 } else {
78                         if(file->f_flags & O_EXCL)
79                                 cERROR(1,("could not find file instance for new file %p ",file));
80                 }
81         }
82
83         down(&inode->i_sb->s_vfs_rename_sem);
84         full_path = build_path_from_dentry(file->f_dentry);
85         up(&inode->i_sb->s_vfs_rename_sem);
86         if(full_path == NULL) {
87                 FreeXid(xid);
88                 return -ENOMEM;
89         }
90
91         cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
92         if ((file->f_flags & O_ACCMODE) == O_RDONLY)
93                 desiredAccess = GENERIC_READ;
94         else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
95                 desiredAccess = GENERIC_WRITE;
96         else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
97                 /* GENERIC_ALL is too much permission to request */
98                 /* can cause unnecessary access denied on create */
99                 /* desiredAccess = GENERIC_ALL; */
100                 desiredAccess = GENERIC_READ | GENERIC_WRITE;
101         }
102
103 /*********************************************************************
104  *  open flag mapping table:
105  *  
106  *      POSIX Flag            CIFS Disposition
107  *      ----------            ---------------- 
108  *      O_CREAT               FILE_OPEN_IF
109  *      O_CREAT | O_EXCL      FILE_CREATE
110  *      O_CREAT | O_TRUNC     FILE_OVERWRITE_IF
111  *      O_TRUNC               FILE_OVERWRITE
112  *      none of the above     FILE_OPEN
113  *
114  *      Note that there is not a direct match between disposition
115  *      FILE_SUPERSEDE (ie create whether or not file exists although 
116  *      O_CREAT | O_TRUNC is similar but truncates the existing
117  *      file rather than creating a new file as FILE_SUPERSEDE does
118  *      (which uses the attributes / metadata passed in on open call)
119  *?
120  *?  O_SYNC is a reasonable match to CIFS writethrough flag  
121  *?  and the read write flags match reasonably.  O_LARGEFILE
122  *?  is irrelevant because largefile support is always used
123  *?  by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
124  *       O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
125  *********************************************************************/
126
127         if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
128                 disposition = FILE_CREATE;
129         else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
130                 disposition = FILE_OVERWRITE_IF;
131         else if((file->f_flags & O_CREAT) == O_CREAT)
132                 disposition = FILE_OPEN_IF;
133         else
134                 disposition = FILE_OPEN;
135
136         if (oplockEnabled)
137                 oplock = REQ_OPLOCK;
138         else
139                 oplock = FALSE;
140
141         /* BB pass O_SYNC flag through on file attributes .. BB */
142
143         /* Also refresh inode by passing in file_info buf returned by SMBOpen 
144            and calling get_inode_info with returned buf (at least 
145            helps non-Unix server case */
146         buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
147         if(buf==0) {
148                 if (full_path)
149                         kfree(full_path);
150                 FreeXid(xid);
151                 return -ENOMEM;
152         }
153         rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
154                         CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
155         if (rc) {
156                 cFYI(1, ("cifs_open returned 0x%x ", rc));
157                 cFYI(1, ("oplock: %d ", oplock));       
158         } else {
159                 file->private_data =
160                         kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
161                 if (file->private_data) {
162                         memset(file->private_data, 0, sizeof(struct cifsFileInfo));
163                         pCifsFile = (struct cifsFileInfo *) file->private_data;
164                         pCifsFile->netfid = netfid;
165                         pCifsFile->pid = current->pid;
166                         init_MUTEX(&pCifsFile->fh_sem);
167                         pCifsFile->pfile = file; /* needed for writepage */
168                         pCifsFile->pInode = inode;
169                         pCifsFile->invalidHandle = FALSE;
170                         pCifsFile->closePend     = FALSE;
171                         write_lock(&file->f_owner.lock);
172                         write_lock(&GlobalSMBSeslock);
173                         list_add(&pCifsFile->tlist,&pTcon->openFileList);
174                         pCifsInode = CIFS_I(file->f_dentry->d_inode);
175                         if(pCifsInode) {
176                                 list_add(&pCifsFile->flist,&pCifsInode->openFileList);
177                                 write_unlock(&GlobalSMBSeslock);
178                                 write_unlock(&file->f_owner.lock);
179                                 if(pCifsInode->clientCanCacheRead) {
180                                         /* we have the inode open somewhere else
181                                            no need to discard cache data */
182                                 } else {
183                                         if(buf) {
184                                         /* BB need same check in cifs_create too? */
185
186                                         /* if not oplocked, invalidate inode pages if mtime 
187                                            or file size changed */
188                                                 struct timespec temp;
189                                                 temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
190                                                 if(timespec_equal(&file->f_dentry->d_inode->i_mtime,&temp) && 
191                                                         (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
192                                                         cFYI(1,("inode unchanged on server"));
193                                                 } else {
194                                                         if(file->f_dentry->d_inode->i_mapping) {
195                                                         /* BB no need to lock inode until after invalidate*/
196                                                         /* since namei code should already have it locked?*/
197                                                                 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
198                                                                 filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
199                                                         }
200                                                         cFYI(1,("invalidating remote inode since open detected it changed"));
201                                                         invalidate_remote_inode(file->f_dentry->d_inode);
202                                                 }
203                                         }
204                                 }
205                                 if (pTcon->ses->capabilities & CAP_UNIX)
206                                         rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
207                                                 full_path, inode->i_sb);
208                                 else
209                                         rc = cifs_get_inode_info(&file->f_dentry->d_inode,
210                                                 full_path, buf, inode->i_sb);
211
212                                 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
213                                         pCifsInode->clientCanCacheAll = TRUE;
214                                         pCifsInode->clientCanCacheRead = TRUE;
215                                         cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
216                                 } else if((oplock & 0xF) == OPLOCK_READ)
217                                         pCifsInode->clientCanCacheRead = TRUE;
218                         } else {
219                                 write_unlock(&GlobalSMBSeslock);
220                                 write_unlock(&file->f_owner.lock);
221                         }
222                         if(oplock & CIFS_CREATE_ACTION) {           
223                                 /* time to set mode which we can not set earlier due
224                                  to problems creating new read-only files */
225                                 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)                
226                                         CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
227                                                 (__u64)-1, 
228                                                 (__u64)-1,
229                                                 0 /* dev */,
230                                                 cifs_sb->local_nls);
231                                 else {/* BB implement via Windows security descriptors */
232                         /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
233                         /* in the meantime could set r/o dos attribute when perms are eg:
234                                         mode & 0222 == 0 */
235                                 }
236                         }
237                 }
238         }
239
240         if (buf)
241                 kfree(buf);
242         if (full_path)
243                 kfree(full_path);
244         FreeXid(xid);
245         return rc;
246 }
247
248 /* Try to reaquire byte range locks that were released when session */
249 /* to server was lost */
250 static int cifs_relock_file(struct cifsFileInfo * cifsFile)
251 {
252         int rc = 0;
253
254 /* BB list all locks open on this file and relock */
255
256         return rc;
257 }
258
259 static int cifs_reopen_file(struct inode *inode, struct file *file)
260 {
261         int rc = -EACCES;
262         int xid, oplock;
263         struct cifs_sb_info *cifs_sb;
264         struct cifsTconInfo *pTcon;
265         struct cifsFileInfo *pCifsFile;
266         struct cifsInodeInfo *pCifsInode;
267         char *full_path = NULL;
268         int desiredAccess = 0x20197;
269         int disposition = FILE_OPEN;
270         __u16 netfid;
271         FILE_ALL_INFO * buf = NULL;
272
273         if(inode == NULL)
274                 return -EBADF;
275         if (file->private_data) {
276                 pCifsFile = (struct cifsFileInfo *) file->private_data;
277         } else
278                 return -EBADF;
279
280         xid = GetXid();
281         down(&pCifsFile->fh_sem);
282         if(pCifsFile->invalidHandle == FALSE) {
283                 up(&pCifsFile->fh_sem);
284                 FreeXid(xid);
285                 return 0;
286         }
287
288         if(file->f_dentry == NULL) {
289                 up(&pCifsFile->fh_sem);
290                 cFYI(1,("failed file reopen, no valid name if dentry freed"));
291                 FreeXid(xid);
292                 return -EBADF;
293         }
294         cifs_sb = CIFS_SB(inode->i_sb);
295         pTcon = cifs_sb->tcon;
296 /* can not grab rename sem here because various ops, including
297 those that already have the rename sem can end up causing writepage
298 to get called and if the server was down that means we end up here,
299 and we can never tell if the caller already has the rename_sem */
300         full_path = build_path_from_dentry(file->f_dentry);
301         if(full_path == NULL) {
302                 up(&pCifsFile->fh_sem);
303                 FreeXid(xid);
304                 return -ENOMEM;
305         }
306
307         cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
308         if ((file->f_flags & O_ACCMODE) == O_RDONLY)
309                 desiredAccess = GENERIC_READ;
310         else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
311                 desiredAccess = GENERIC_WRITE;
312         else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
313                 /* GENERIC_ALL is too much permission to request */
314                 /* can cause unnecessary access denied on create */
315                 /* desiredAccess = GENERIC_ALL; */
316                 desiredAccess = GENERIC_READ | GENERIC_WRITE;
317         }
318
319         if (oplockEnabled)
320                 oplock = REQ_OPLOCK;
321         else
322                 oplock = FALSE;
323
324                 /* BB pass O_SYNC flag through on file attributes .. BB */
325
326                 /* Also refresh inode by passing in file_info buf returned by SMBOpen
327                    and calling get_inode_info with returned buf (at least
328                    helps non-Unix server case */
329         buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
330         if(buf==0) {
331                 up(&pCifsFile->fh_sem);
332                 if (full_path)
333                         kfree(full_path);
334                 FreeXid(xid);
335                 return -ENOMEM;
336         }
337         rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
338                                 CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
339         if (rc) {
340                 up(&pCifsFile->fh_sem);
341                 cFYI(1, ("cifs_open returned 0x%x ", rc));
342                 cFYI(1, ("oplock: %d ", oplock));
343         } else {
344                 pCifsFile->netfid = netfid;
345                 pCifsFile->invalidHandle = FALSE;
346                 up(&pCifsFile->fh_sem);
347                 pCifsInode = CIFS_I(inode);
348                 if(pCifsInode) {
349                         if (pTcon->ses->capabilities & CAP_UNIX)
350                                 rc = cifs_get_inode_info_unix(&inode,
351                                                 full_path, inode->i_sb);
352                         else
353                                 rc = cifs_get_inode_info(&inode,
354                                                 full_path, buf, inode->i_sb);
355
356                         if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
357                                 pCifsInode->clientCanCacheAll =  TRUE;
358                                 pCifsInode->clientCanCacheRead = TRUE;
359                                 cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
360                         } else if((oplock & 0xF) == OPLOCK_READ) {
361                                 pCifsInode->clientCanCacheRead = TRUE;
362                                 pCifsInode->clientCanCacheAll =  FALSE;
363                         } else {
364                                 pCifsInode->clientCanCacheRead = FALSE;
365                                 pCifsInode->clientCanCacheAll =  FALSE;
366                         }
367                         cifs_relock_file(pCifsFile);
368                 }
369         }
370
371         if (buf)
372                 kfree(buf);
373         if (full_path)
374                 kfree(full_path);
375         FreeXid(xid);
376         return rc;
377 }
378
379 int
380 cifs_close(struct inode *inode, struct file *file)
381 {
382         int rc = 0;
383         int xid;
384         struct cifs_sb_info *cifs_sb;
385         struct cifsTconInfo *pTcon;
386         struct cifsFileInfo *pSMBFile =
387                 (struct cifsFileInfo *) file->private_data;
388
389         xid = GetXid();
390
391         cifs_sb = CIFS_SB(inode->i_sb);
392         pTcon = cifs_sb->tcon;
393         if (pSMBFile) {
394                 pSMBFile->closePend    = TRUE;
395                 write_lock(&file->f_owner.lock);
396                 if(pTcon) {
397                         /* no sense reconnecting to close a file that is
398                                 already closed */
399                         if (pTcon->tidStatus != CifsNeedReconnect) {
400                                 write_unlock(&file->f_owner.lock);
401                                 rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
402                                 write_lock(&file->f_owner.lock);
403                         }
404                 }
405                 list_del(&pSMBFile->flist);
406                 list_del(&pSMBFile->tlist);
407                 write_unlock(&file->f_owner.lock);
408                 if(pSMBFile->search_resume_name)
409                         kfree(pSMBFile->search_resume_name);
410                 kfree(file->private_data);
411                 file->private_data = NULL;
412         } else
413                 rc = -EBADF;
414
415         if(list_empty(&(CIFS_I(inode)->openFileList))) {
416                 cFYI(1,("closing last open instance for inode %p",inode));
417                 /* if the file is not open we do not know if we can cache
418                 info on this inode, much less write behind and read ahead */
419                 CIFS_I(inode)->clientCanCacheRead = FALSE;
420                 CIFS_I(inode)->clientCanCacheAll  = FALSE;
421         }
422         if((rc ==0) && CIFS_I(inode)->write_behind_rc)
423                 rc = CIFS_I(inode)->write_behind_rc;
424         FreeXid(xid);
425         return rc;
426 }
427
428 int
429 cifs_closedir(struct inode *inode, struct file *file)
430 {
431         int rc = 0;
432         int xid;
433         struct cifsFileInfo *pSMBFileStruct =
434             (struct cifsFileInfo *) file->private_data;
435
436         cFYI(1, ("Closedir inode = 0x%p with ", inode));
437
438         xid = GetXid();
439
440         if (pSMBFileStruct) {
441                 cFYI(1, ("Freeing private data in close dir"));
442                 kfree(file->private_data);
443                 file->private_data = NULL;
444         }
445         FreeXid(xid);
446         return rc;
447 }
448
449 int
450 cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
451 {
452         int rc, xid;
453         __u32 lockType = LOCKING_ANDX_LARGE_FILES;
454         __u32 numLock = 0;
455         __u32 numUnlock = 0;
456         __u64 length;
457         int wait_flag = FALSE;
458         struct cifs_sb_info *cifs_sb;
459         struct cifsTconInfo *pTcon;
460         length = 1 + pfLock->fl_end - pfLock->fl_start;
461
462         rc = -EACCES;
463
464         xid = GetXid();
465
466         cFYI(1,
467              ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
468               cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
469               pfLock->fl_end));
470
471         if (pfLock->fl_flags & FL_POSIX)
472                 cFYI(1, ("Posix "));
473         if (pfLock->fl_flags & FL_FLOCK)
474                 cFYI(1, ("Flock "));
475         if (pfLock->fl_flags & FL_SLEEP) {
476                 cFYI(1, ("Blocking lock "));
477                 wait_flag = TRUE;
478         }
479         if (pfLock->fl_flags & FL_ACCESS)
480                 cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
481         if (pfLock->fl_flags & FL_LEASE)
482                 cFYI(1, ("Lease on file - not implemented yet"));
483         if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
484                 cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
485
486         if (pfLock->fl_type == F_WRLCK) {
487                 cFYI(1, ("F_WRLCK "));
488                 numLock = 1;
489         } else if (pfLock->fl_type == F_UNLCK) {
490                 cFYI(1, ("F_UNLCK "));
491                 numUnlock = 1;
492         } else if (pfLock->fl_type == F_RDLCK) {
493                 cFYI(1, ("F_RDLCK "));
494                 lockType |= LOCKING_ANDX_SHARED_LOCK;
495                 numLock = 1;
496         } else if (pfLock->fl_type == F_EXLCK) {
497                 cFYI(1, ("F_EXLCK "));
498                 numLock = 1;
499         } else if (pfLock->fl_type == F_SHLCK) {
500                 cFYI(1, ("F_SHLCK "));
501                 lockType |= LOCKING_ANDX_SHARED_LOCK;
502                 numLock = 1;
503         } else
504                 cFYI(1, ("Unknown type of lock "));
505
506         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
507         pTcon = cifs_sb->tcon;
508
509         if (file->private_data == NULL) {
510                 FreeXid(xid);
511                 return -EBADF;
512         }
513
514         if (IS_GETLK(cmd)) {
515                 rc = CIFSSMBLock(xid, pTcon,
516                                  ((struct cifsFileInfo *) file->
517                                   private_data)->netfid,
518                                  length,
519                                  pfLock->fl_start, 0, 1, lockType,
520                                  0 /* wait flag */ );
521                 if (rc == 0) {
522                         rc = CIFSSMBLock(xid, pTcon,
523                                          ((struct cifsFileInfo *) file->
524                                           private_data)->netfid,
525                                          length,
526                                          pfLock->fl_start, 1 /* numUnlock */ ,
527                                          0 /* numLock */ , lockType,
528                                          0 /* wait flag */ );
529                         pfLock->fl_type = F_UNLCK;
530                         if (rc != 0)
531                                 cERROR(1,
532                                         ("Error unlocking previously locked range %d during test of lock ",
533                                         rc));
534                         rc = 0;
535
536                 } else {
537                         /* if rc == ERR_SHARING_VIOLATION ? */
538                         rc = 0; /* do not change lock type to unlock since range in use */
539                 }
540
541                 FreeXid(xid);
542                 return rc;
543         }
544
545         rc = CIFSSMBLock(xid, pTcon,
546                          ((struct cifsFileInfo *) file->private_data)->
547                          netfid, length,
548                          pfLock->fl_start, numUnlock, numLock, lockType,
549                          wait_flag);
550         FreeXid(xid);
551         return rc;
552 }
553
554 ssize_t
555 cifs_write(struct file * file, const char *write_data,
556            size_t write_size, loff_t * poffset)
557 {
558         int rc = 0;
559         unsigned int bytes_written = 0;
560         unsigned int total_written;
561         struct cifs_sb_info *cifs_sb;
562         struct cifsTconInfo *pTcon;
563         int xid, long_op;
564         struct cifsFileInfo * open_file;
565
566         if(file->f_dentry == NULL)
567                 return -EBADF;
568
569         xid = GetXid();
570
571         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
572         pTcon = cifs_sb->tcon;
573
574         /*cFYI(1,
575            (" write %d bytes to offset %lld of %s", write_size,
576            *poffset, file->f_dentry->d_name.name)); */
577
578         if (file->private_data == NULL) {
579                 FreeXid(xid);
580                 return -EBADF;
581         }
582         open_file = (struct cifsFileInfo *) file->private_data;
583
584         if(file->f_dentry->d_inode == NULL) {
585                 FreeXid(xid);
586                 return -EBADF;
587         }
588
589         if (*poffset > file->f_dentry->d_inode->i_size)
590                 long_op = 2;  /* writes past end of file can take a long time */
591         else
592                 long_op = 1;
593
594         for (total_written = 0; write_size > total_written;
595              total_written += bytes_written) {
596                 rc = -EAGAIN;
597                 while(rc == -EAGAIN) {
598                         if(file->private_data == NULL) {
599                                 /* file has been closed on us */
600                                 FreeXid(xid);
601                                 return total_written;
602                         }
603                         if ((open_file->invalidHandle) && (!open_file->closePend)) {
604                                 if((file->f_dentry == NULL) || (file->f_dentry->d_inode == NULL)) {
605                                         FreeXid(xid);
606                                         return total_written;
607                                 }
608                                 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
609                                 if(rc != 0)
610                                         break;
611                         }
612
613                         rc = CIFSSMBWrite(xid, pTcon,
614                                    open_file->netfid,
615                                   write_size - total_written, *poffset,
616                                   &bytes_written,
617                                   write_data + total_written, long_op);
618                 }
619                 if (rc || (bytes_written == 0)) {
620                         if (total_written)
621                                 break;
622                         else {
623                                 FreeXid(xid);
624                                 return rc;
625                         }
626                 } else
627                         *poffset += bytes_written;
628                 long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
629         }
630
631 #ifdef CONFIG_CIFS_STATS
632         if(total_written > 0) {
633                 atomic_inc(&pTcon->num_writes);
634                 spin_lock(&pTcon->stat_lock);
635                 pTcon->bytes_written += total_written;
636                 spin_unlock(&pTcon->stat_lock);
637         }
638 #endif          
639
640         /* since the write may have blocked check these pointers again */
641         if(file->f_dentry) {
642                 if(file->f_dentry->d_inode) {
643                         file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
644                                 CURRENT_TIME;
645                         if (total_written > 0) {
646                                 if (*poffset > file->f_dentry->d_inode->i_size)
647                                         i_size_write(file->f_dentry->d_inode, *poffset);
648                         }
649                         mark_inode_dirty_sync(file->f_dentry->d_inode);
650                 }
651         }
652         FreeXid(xid);
653         return total_written;
654 }
655
656 static int
657 cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
658 {
659         struct address_space *mapping = page->mapping;
660         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
661         char * write_data;
662         int rc = -EFAULT;
663         int bytes_written = 0;
664         struct cifs_sb_info *cifs_sb;
665         struct cifsTconInfo *pTcon;
666         struct inode *inode;
667         struct cifsInodeInfo *cifsInode;
668         struct cifsFileInfo *open_file = NULL;
669         struct list_head *tmp;
670         struct list_head *tmp1;
671
672         if (!mapping) {
673                 return -EFAULT;
674         } else if(!mapping->host) {
675                 return -EFAULT;
676         }
677
678         inode = page->mapping->host;
679         cifs_sb = CIFS_SB(inode->i_sb);
680         pTcon = cifs_sb->tcon;
681
682         offset += (loff_t)from;
683         write_data = kmap(page);
684         write_data += from;
685
686         if((to > PAGE_CACHE_SIZE) || (from > to)) {
687                 kunmap(page);
688                 return -EIO;
689         }
690
691         /* racing with truncate? */
692         if(offset > mapping->host->i_size) {
693                 kunmap(page);
694                 return 0; /* don't care */
695         }
696
697         /* check to make sure that we are not extending the file */
698         if(mapping->host->i_size - offset < (loff_t)to)
699                 to = (unsigned)(mapping->host->i_size - offset); 
700                 
701
702         cifsInode = CIFS_I(mapping->host);
703         read_lock(&GlobalSMBSeslock); 
704         list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {            
705                 open_file = list_entry(tmp,struct cifsFileInfo, flist);
706                 if(open_file->closePend)
707                         continue;
708                 /* We check if file is open for writing first */
709                 if((open_file->pfile) && 
710                    ((open_file->pfile->f_flags & O_RDWR) || 
711                         (open_file->pfile->f_flags & O_WRONLY))) {
712                         read_unlock(&GlobalSMBSeslock);
713                         bytes_written = cifs_write(open_file->pfile, write_data,
714                                         to-from, &offset);
715                         read_lock(&GlobalSMBSeslock);
716                 /* Does mm or vfs already set times? */
717                         inode->i_atime = inode->i_mtime = CURRENT_TIME;
718                         if ((bytes_written > 0) && (offset)) {
719                                 rc = 0;
720                         } else if(bytes_written < 0) {
721                                 if(rc == -EBADF) {
722                                 /* have seen a case in which
723                                 kernel seemed to have closed/freed a file
724                                 even with writes active so we might as well
725                                 see if there are other file structs to try
726                                 for the same inode before giving up */
727                                         continue;
728                                 } else
729                                         rc = bytes_written;
730                         }
731                         break;  /* now that we found a valid file handle
732                                 and tried to write to it we are done, no
733                                 sense continuing to loop looking for another */
734                 }
735                 if(tmp->next == NULL) {
736                         cFYI(1,("File instance %p removed",tmp));
737                         break;
738                 }
739         }
740         read_unlock(&GlobalSMBSeslock);
741         if(open_file == NULL) {
742                 cFYI(1,("No writeable filehandles for inode"));
743                 rc = -EIO;
744         }
745
746         kunmap(page);
747         return rc;
748 }
749
750 #if 0
751 static int
752 cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
753 {
754         int rc = -EFAULT;
755         int xid;
756
757         xid = GetXid();
758 /* call 16K write then Setpageuptodate */
759         FreeXid(xid);
760         return rc;
761 }
762 #endif
763
764 static int
765 cifs_writepage(struct page* page, struct writeback_control *wbc)
766 {
767         int rc = -EFAULT;
768         int xid;
769
770         xid = GetXid();
771 /* BB add check for wbc flags */
772         page_cache_get(page);
773         
774         rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
775         SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
776         unlock_page(page);
777         page_cache_release(page);       
778         FreeXid(xid);
779         return rc;
780 }
781
782 static int
783 cifs_commit_write(struct file *file, struct page *page, unsigned offset,
784                   unsigned to)
785 {
786         int xid;
787         int rc = 0;
788         struct inode *inode = page->mapping->host;
789         loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
790         /* struct cifsFileInfo *open_file;
791         struct cifs_sb_info *cifs_sb; */
792
793         xid = GetXid();
794         cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
795         if (position > inode->i_size){
796                 i_size_write(inode, position);
797                 /*if (file->private_data == NULL) {
798                         rc = -EBADF;
799                 } else {
800                         open_file = (struct cifsFileInfo *)file->private_data;
801                         cifs_sb = CIFS_SB(inode->i_sb);
802                         rc = -EAGAIN;
803                         while(rc == -EAGAIN) {
804                                 if((open_file->invalidHandle) && 
805                                   (!open_file->closePend)) {
806                                         rc = cifs_reopen_file(file->f_dentry->d_inode,file);
807                                         if(rc != 0)
808                                                 break;
809                                 }
810                                 if(!open_file->closePend) {
811                                         rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon, 
812                                                 position, open_file->netfid,
813                                                 open_file->pid,FALSE);
814                                 } else {
815                                         rc = -EBADF;
816                                         break;
817                                 }
818                         }
819                         cFYI(1,(" SetEOF (commit write) rc = %d",rc));
820                 }*/
821         }
822         set_page_dirty(page);
823
824         FreeXid(xid);
825         return rc;
826 }
827
828 int
829 cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
830 {
831         int xid;
832         int rc = 0;
833         struct inode * inode = file->f_dentry->d_inode;
834
835         xid = GetXid();
836
837         cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 
838                 dentry->d_name.name, datasync));
839         
840         rc = filemap_fdatawrite(inode->i_mapping);
841         if(rc == 0)
842                 CIFS_I(inode)->write_behind_rc = 0;
843         FreeXid(xid);
844         return rc;
845 }
846
847 /* static int
848 cifs_sync_page(struct page *page)
849 {
850         struct address_space *mapping;
851         struct inode *inode;
852         unsigned long index = page->index;
853         unsigned int rpages = 0;
854         int rc = 0;
855
856         cFYI(1,("sync page %p",page));
857         mapping = page->mapping;
858         if (!mapping)
859                 return 0;
860         inode = mapping->host;
861         if (!inode)
862                 return 0;*/
863
864 /*      fill in rpages then 
865     result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
866
867 /*   cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
868
869         if (rc < 0)
870                 return rc;
871         return 0;
872 } */
873
874 /*
875  * As file closes, flush all cached write data for this inode checking
876  * for write behind errors.
877  *
878  */
879 int cifs_flush(struct file *file)
880 {
881         struct inode * inode = file->f_dentry->d_inode;
882         int rc = 0;
883
884         /* Rather than do the steps manually: */
885         /* lock the inode for writing */
886         /* loop through pages looking for write behind data (dirty pages) */
887         /* coalesce into contiguous 16K (or smaller) chunks to write to server */
888         /* send to server (prefer in parallel) */
889         /* deal with writebehind errors */
890         /* unlock inode for writing */
891         /* filemapfdatawrite appears easier for the time being */
892
893         rc = filemap_fdatawrite(inode->i_mapping);
894         if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
895                 CIFS_I(inode)->write_behind_rc = 0;
896                 
897         cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
898
899         return rc;
900 }
901
902
903 ssize_t
904 cifs_read(struct file * file, char *read_data, size_t read_size,
905           loff_t * poffset)
906 {
907         int rc = -EACCES;
908         unsigned int bytes_read = 0;
909         unsigned int total_read;
910         unsigned int current_read_size;
911         struct cifs_sb_info *cifs_sb;
912         struct cifsTconInfo *pTcon;
913         int xid;
914         char * current_offset;
915         struct cifsFileInfo * open_file;
916
917         xid = GetXid();
918         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
919         pTcon = cifs_sb->tcon;
920
921         if (file->private_data == NULL) {
922                 FreeXid(xid);
923                 return -EBADF;
924         }
925         open_file = (struct cifsFileInfo *)file->private_data;
926
927         for (total_read = 0,current_offset=read_data; read_size > total_read;
928                                 total_read += bytes_read,current_offset+=bytes_read) {
929                 current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
930                 rc = -EAGAIN;
931                 while(rc == -EAGAIN) {
932                         if ((open_file->invalidHandle) && (!open_file->closePend)) {
933                                 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
934                                 if(rc != 0)
935                                         break;
936                         }
937
938                         rc = CIFSSMBRead(xid, pTcon,
939                                  open_file->netfid,
940                                  current_read_size, *poffset,
941                                  &bytes_read, &current_offset);
942                 }
943                 if (rc || (bytes_read == 0)) {
944                         if (total_read) {
945                                 break;
946                         } else {
947                                 FreeXid(xid);
948                                 return rc;
949                         }
950                 } else {
951 #ifdef CONFIG_CIFS_STATS
952                         atomic_inc(&pTcon->num_reads);
953                         spin_lock(&pTcon->stat_lock);
954                         pTcon->bytes_read += total_read;
955                         spin_unlock(&pTcon->stat_lock);
956 #endif
957                         *poffset += bytes_read;
958                 }
959         }
960         FreeXid(xid);
961         return total_read;
962 }
963
964 int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
965 {
966         struct dentry * dentry = file->f_dentry;
967         int     rc, xid;
968
969         xid = GetXid();
970         rc = cifs_revalidate(dentry);
971         if (rc) {
972                 cFYI(1,("Validation prior to mmap failed, error=%d", rc));
973                 FreeXid(xid);
974                 return rc;
975         }
976         rc = generic_file_mmap(file, vma);
977         FreeXid(xid);
978         return rc;
979 }
980
981 static void cifs_copy_cache_pages(struct address_space *mapping, 
982                 struct list_head *pages, int bytes_read, 
983                 char *data,struct pagevec * plru_pvec)
984 {
985         struct page *page;
986         char * target;
987
988         while (bytes_read > 0) {
989                 if(list_empty(pages))
990                         break;
991
992                 page = list_entry(pages->prev, struct page, lru);
993                 list_del(&page->lru);
994
995                 if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
996                         page_cache_release(page);
997                         cFYI(1,("Add page cache failed"));
998                         continue;
999                 }
1000
1001                 target = kmap_atomic(page,KM_USER0);
1002
1003                 if(PAGE_CACHE_SIZE > bytes_read) {
1004                         memcpy(target,data,bytes_read);
1005                         /* zero the tail end of this partial page */
1006                         memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
1007                         bytes_read = 0;
1008                 } else {
1009                         memcpy(target,data,PAGE_CACHE_SIZE);
1010                         bytes_read -= PAGE_CACHE_SIZE;
1011                 }
1012                 kunmap_atomic(target,KM_USER0);
1013
1014                 flush_dcache_page(page);
1015                 SetPageUptodate(page);
1016                 unlock_page(page);
1017                 if (!pagevec_add(plru_pvec, page))
1018                         __pagevec_lru_add(plru_pvec);
1019                 data += PAGE_CACHE_SIZE;
1020         }
1021         return;
1022 }
1023
1024
1025 static int
1026 cifs_readpages(struct file *file, struct address_space *mapping,
1027                 struct list_head *page_list, unsigned num_pages)
1028 {
1029         int rc = -EACCES;
1030         int xid;
1031         loff_t offset;
1032         struct page * page;
1033         struct cifs_sb_info *cifs_sb;
1034         struct cifsTconInfo *pTcon;
1035         int bytes_read = 0;
1036         unsigned int read_size,i;
1037         char * smb_read_data = 0;
1038         struct smb_com_read_rsp * pSMBr;
1039         struct pagevec lru_pvec;
1040         struct cifsFileInfo * open_file;
1041
1042         xid = GetXid();
1043         if (file->private_data == NULL) {
1044                 FreeXid(xid);
1045                 return -EBADF;
1046         }
1047         open_file = (struct cifsFileInfo *)file->private_data;
1048         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1049         pTcon = cifs_sb->tcon;
1050
1051         pagevec_init(&lru_pvec, 0);
1052
1053         for(i = 0;i<num_pages;) {
1054                 unsigned contig_pages;
1055                 struct page * tmp_page;
1056                 unsigned long expected_index;
1057
1058                 if(list_empty(page_list)) {
1059                         break;
1060                 }
1061                 page = list_entry(page_list->prev, struct page, lru);
1062                 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1063
1064                 /* count adjacent pages that we will read into */
1065                 contig_pages = 0;
1066                 expected_index = list_entry(page_list->prev,struct page,lru)->index;
1067                 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1068                         if(tmp_page->index == expected_index) {
1069                                 contig_pages++;
1070                                 expected_index++;
1071                         } else {
1072                                 break; 
1073                         }
1074                 }
1075                 if(contig_pages + i >  num_pages) {
1076                         contig_pages = num_pages - i;
1077                 }
1078
1079                 /* for reads over a certain size could initiate async read ahead */
1080
1081                 read_size = contig_pages * PAGE_CACHE_SIZE;
1082                 /* Read size needs to be in multiples of one page */
1083                 read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
1084
1085                 rc = -EAGAIN;
1086                 while(rc == -EAGAIN) {
1087                         if ((open_file->invalidHandle) && (!open_file->closePend)) {
1088                                 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
1089                                 if(rc != 0)
1090                                         break;
1091                         }
1092
1093                         rc = CIFSSMBRead(xid, pTcon,
1094                                 open_file->netfid,
1095                                 read_size, offset,
1096                                 &bytes_read, &smb_read_data);
1097                         /* BB need to check return code here */
1098                         if(rc== -EAGAIN) {
1099                                 if(smb_read_data) {
1100                                         cifs_buf_release(smb_read_data);
1101                                         smb_read_data = 0;
1102                                 }
1103                         }
1104                 }
1105                 if ((rc < 0) || (smb_read_data == NULL)) {
1106                         cFYI(1,("Read error in readpages: %d",rc));
1107                         /* clean up remaing pages off list */
1108                         while (!list_empty(page_list) && (i < num_pages)) {
1109                                 page = list_entry(page_list->prev, struct page, lru);
1110                                 list_del(&page->lru);
1111                                 page_cache_release(page);
1112                         }
1113                         break;
1114                 } else if (bytes_read > 0) {
1115                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1116                         cifs_copy_cache_pages(mapping, page_list, bytes_read,
1117                                 smb_read_data + 4 /* RFC1001 hdr */ +
1118                                 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1119
1120                         i +=  bytes_read >> PAGE_CACHE_SHIFT;
1121 #ifdef CONFIG_CIFS_STATS
1122                         atomic_inc(&pTcon->num_reads);
1123                         spin_lock(&pTcon->stat_lock);
1124                         pTcon->bytes_read += bytes_read;
1125                         spin_unlock(&pTcon->stat_lock);
1126 #endif
1127                         if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1128                                 cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));
1129
1130                                 i++; /* account for partial page */
1131
1132                                 /* server copy of file can have smaller size than client */
1133                                 /* BB do we need to verify this common case ? this case is ok - 
1134                                 if we are at server EOF we will hit it on next read */
1135
1136                         /* while(!list_empty(page_list) && (i < num_pages)) {
1137                                         page = list_entry(page_list->prev,struct page, list);
1138                                         list_del(&page->list);
1139                                         page_cache_release(page);
1140                                 }
1141                                 break; */
1142                         }
1143                 } else {
1144                         cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset)); 
1145                         /* BB turn off caching and do new lookup on file size at server? */
1146                         while (!list_empty(page_list) && (i < num_pages)) {
1147                                 page = list_entry(page_list->prev, struct page, lru);
1148                                 list_del(&page->lru);
1149                                 page_cache_release(page); /* BB removeme - replace with zero of page? */
1150                         }
1151                         break;
1152                 }
1153                 if(smb_read_data) {
1154                         cifs_buf_release(smb_read_data);
1155                         smb_read_data = 0;
1156                 }
1157                 bytes_read = 0;
1158         }
1159
1160         pagevec_lru_add(&lru_pvec);
1161
1162 /* need to free smb_read_data buf before exit */
1163         if(smb_read_data) {
1164                 cifs_buf_release(smb_read_data);
1165                 smb_read_data = 0;
1166         } 
1167
1168         FreeXid(xid);
1169         return rc;
1170 }
1171
1172 static int
1173 cifs_readpage(struct file *file, struct page *page)
1174 {
1175         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1176         char * read_data;
1177         int rc = -EACCES;
1178         int xid;
1179
1180         xid = GetXid();
1181
1182         if (file->private_data == NULL) {
1183                 FreeXid(xid);
1184                 return -EBADF;
1185         }
1186
1187         cFYI(0,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
1188
1189         page_cache_get(page);
1190         read_data = kmap(page);
1191         /* for reads over a certain size could initiate async read ahead */
1192
1193         rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, &offset);
1194
1195         if (rc < 0)
1196                 goto io_error;
1197         else {
1198                 cFYI(1,("Bytes read %d ",rc));
1199         }
1200
1201         file->f_dentry->d_inode->i_atime = CURRENT_TIME;
1202
1203         if(PAGE_CACHE_SIZE > rc) {
1204                 memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
1205         }
1206         flush_dcache_page(page);
1207         SetPageUptodate(page);
1208         rc = 0;
1209
1210 io_error:
1211         kunmap(page);
1212         unlock_page(page);
1213
1214         page_cache_release(page);
1215         FreeXid(xid);
1216         return rc;
1217 }
1218
1219 void
1220 fill_in_inode(struct inode *tmp_inode,
1221               FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
1222 {
1223         struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
1224         struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
1225
1226         pfindData->ExtFileAttributes =
1227             le32_to_cpu(pfindData->ExtFileAttributes);
1228         pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
1229         pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
1230         cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
1231         cifsInfo->time = jiffies;
1232
1233         /* Linux can not store file creation time unfortunately so ignore it */
1234         tmp_inode->i_atime =
1235             cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
1236         tmp_inode->i_mtime =
1237             cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
1238         tmp_inode->i_ctime =
1239             cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
1240         /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
1241         /* 2767 perms - indicate mandatory locking */
1242                 /* BB fill in uid and gid here? with help from winbind? 
1243                         or retrieve from NTFS stream extended attribute */
1244         if(atomic_read(&cifsInfo->inUse) == 0) {
1245                 tmp_inode->i_uid = cifs_sb->mnt_uid;
1246                 tmp_inode->i_gid = cifs_sb->mnt_gid;
1247                 /* set default mode. will override for dirs below */
1248                 tmp_inode->i_mode = cifs_sb->mnt_file_mode;
1249         }
1250
1251         cFYI(0,
1252              ("CIFS FFIRST: Attributes came in as 0x%x",
1253               pfindData->ExtFileAttributes));
1254         if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
1255                 *pobject_type = DT_LNK;
1256                 /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
1257                 tmp_inode->i_mode |= S_IFLNK;
1258         } else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
1259                 *pobject_type = DT_DIR;
1260                 /* override default perms since we do not lock dirs */
1261                 if(atomic_read(&cifsInfo->inUse) == 0) {
1262                         tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
1263                 }
1264                 tmp_inode->i_mode |= S_IFDIR;
1265         } else {
1266                 *pobject_type = DT_REG;
1267                 tmp_inode->i_mode |= S_IFREG;
1268                 if(pfindData->ExtFileAttributes & ATTR_READONLY)
1269                         tmp_inode->i_mode &= ~(S_IWUGO);
1270
1271         }/* could add code here - to validate if device or weird share type? */
1272
1273         /* can not fill in nlink here as in qpathinfo version and Unx search */
1274         if(atomic_read(&cifsInfo->inUse) == 0) {
1275                 atomic_set(&cifsInfo->inUse,1);
1276         }
1277
1278         i_size_write(tmp_inode,pfindData->EndOfFile);
1279         tmp_inode->i_blocks =
1280                 (tmp_inode->i_blksize - 1 + pfindData->AllocationSize) >> tmp_inode->i_blkbits;
1281         if (pfindData->AllocationSize < pfindData->EndOfFile)
1282                 cFYI(1, ("Possible sparse file: allocation size less than end of file "));
1283         cFYI(1,
1284              ("File Size %ld and blocks %ld and blocksize %ld",
1285               (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
1286               tmp_inode->i_blksize));
1287         if (S_ISREG(tmp_inode->i_mode)) {
1288                 cFYI(1, (" File inode "));
1289                 tmp_inode->i_op = &cifs_file_inode_ops;
1290                 tmp_inode->i_fop = &cifs_file_ops;
1291                 tmp_inode->i_data.a_ops = &cifs_addr_ops;
1292         } else if (S_ISDIR(tmp_inode->i_mode)) {
1293                 cFYI(1, (" Directory inode"));
1294                 tmp_inode->i_op = &cifs_dir_inode_ops;
1295                 tmp_inode->i_fop = &cifs_dir_ops;
1296         } else if (S_ISLNK(tmp_inode->i_mode)) {
1297                 cFYI(1, (" Symbolic Link inode "));
1298                 tmp_inode->i_op = &cifs_symlink_inode_ops;
1299         } else {
1300                 cFYI(1, (" Init special inode "));
1301                 init_special_inode(tmp_inode, tmp_inode->i_mode,
1302                                    tmp_inode->i_rdev);
1303         }
1304 }
1305
1306 void
1307 unix_fill_in_inode(struct inode *tmp_inode,
1308                    FILE_UNIX_INFO * pfindData, int *pobject_type)
1309 {
1310         struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
1311         cifsInfo->time = jiffies;
1312         atomic_inc(&cifsInfo->inUse);
1313
1314         tmp_inode->i_atime =
1315             cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
1316         tmp_inode->i_mtime =
1317             cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
1318         tmp_inode->i_ctime =
1319             cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
1320
1321         tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
1322         pfindData->Type = le32_to_cpu(pfindData->Type);
1323         if (pfindData->Type == UNIX_FILE) {
1324                 *pobject_type = DT_REG;
1325                 tmp_inode->i_mode |= S_IFREG;
1326         } else if (pfindData->Type == UNIX_SYMLINK) {
1327                 *pobject_type = DT_LNK;
1328                 tmp_inode->i_mode |= S_IFLNK;
1329         } else if (pfindData->Type == UNIX_DIR) {
1330                 *pobject_type = DT_DIR;
1331                 tmp_inode->i_mode |= S_IFDIR;
1332         } else if (pfindData->Type == UNIX_CHARDEV) {
1333                 *pobject_type = DT_CHR;
1334                 tmp_inode->i_mode |= S_IFCHR;
1335         } else if (pfindData->Type == UNIX_BLOCKDEV) {
1336                 *pobject_type = DT_BLK;
1337                 tmp_inode->i_mode |= S_IFBLK;
1338         } else if (pfindData->Type == UNIX_FIFO) {
1339                 *pobject_type = DT_FIFO;
1340                 tmp_inode->i_mode |= S_IFIFO;
1341         } else if (pfindData->Type == UNIX_SOCKET) {
1342                 *pobject_type = DT_SOCK;
1343                 tmp_inode->i_mode |= S_IFSOCK;
1344         }
1345
1346         tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
1347         tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
1348         tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
1349
1350         pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
1351         pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
1352         i_size_write(tmp_inode,pfindData->EndOfFile);
1353         tmp_inode->i_blocks =
1354                 (tmp_inode->i_blksize - 1 + pfindData->NumOfBytes) >> tmp_inode->i_blkbits;
1355
1356         if (S_ISREG(tmp_inode->i_mode)) {
1357                 cFYI(1, ("File inode"));
1358                 tmp_inode->i_op = &cifs_file_inode_ops;
1359                 tmp_inode->i_fop = &cifs_file_ops;
1360                 tmp_inode->i_data.a_ops = &cifs_addr_ops;
1361         } else if (S_ISDIR(tmp_inode->i_mode)) {
1362                 cFYI(1, ("Directory inode"));
1363                 tmp_inode->i_op = &cifs_dir_inode_ops;
1364                 tmp_inode->i_fop = &cifs_dir_ops;
1365         } else if (S_ISLNK(tmp_inode->i_mode)) {
1366                 cFYI(1, ("Symbolic Link inode"));
1367                 tmp_inode->i_op = &cifs_symlink_inode_ops;
1368 /* tmp_inode->i_fop = *//* do not need to set to anything */
1369         } else {
1370                 cFYI(1, ("Special inode")); 
1371                 init_special_inode(tmp_inode, tmp_inode->i_mode,
1372                                    tmp_inode->i_rdev);
1373         }
1374 }
1375
1376 static void
1377 construct_dentry(struct qstr *qstring, struct file *file,
1378                  struct inode **ptmp_inode, struct dentry **pnew_dentry)
1379 {
1380         struct dentry *tmp_dentry;
1381         struct cifs_sb_info *cifs_sb;
1382         struct cifsTconInfo *pTcon;
1383
1384         cFYI(1, ("For %s ", qstring->name));
1385         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1386         pTcon = cifs_sb->tcon;
1387
1388         qstring->hash = full_name_hash(qstring->name, qstring->len);
1389         tmp_dentry = d_lookup(file->f_dentry, qstring);
1390         if (tmp_dentry) {
1391                 cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
1392                 *ptmp_inode = tmp_dentry->d_inode;
1393                 /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
1394                 if(*ptmp_inode == NULL) {
1395                         *ptmp_inode = new_inode(file->f_dentry->d_sb);
1396                         d_instantiate(tmp_dentry, *ptmp_inode);
1397                 }
1398         } else {
1399                 tmp_dentry = d_alloc(file->f_dentry, qstring);
1400                 if(tmp_dentry == NULL) {
1401                         cERROR(1,("Failed allocating dentry"));
1402                         return;
1403                 }
1404                         
1405                 *ptmp_inode = new_inode(file->f_dentry->d_sb);
1406                 tmp_dentry->d_op = &cifs_dentry_ops;
1407                 cFYI(0, (" instantiate dentry 0x%p with inode 0x%p ",
1408                          tmp_dentry, *ptmp_inode));
1409                 d_instantiate(tmp_dentry, *ptmp_inode);
1410                 d_rehash(tmp_dentry);
1411         }
1412
1413         tmp_dentry->d_time = jiffies;
1414         *pnew_dentry = tmp_dentry;
1415 }
1416
1417 static void reset_resume_key(struct file * dir_file, 
1418                                 unsigned char * filename, 
1419                                 unsigned int len,int Unicode,struct nls_table * nls_tab) {
1420         struct cifsFileInfo *cifsFile;
1421
1422         cifsFile = (struct cifsFileInfo *)dir_file->private_data;
1423         if(cifsFile == NULL)
1424                 return;
1425         if(cifsFile->search_resume_name) {
1426                 kfree(cifsFile->search_resume_name);
1427         }
1428
1429         if(Unicode) 
1430                 len *= 2;
1431         cifsFile->resume_name_length = len;
1432
1433         cifsFile->search_resume_name = 
1434                 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1435
1436         if(cifsFile->search_resume_name == NULL) {
1437                 cERROR(1,("failed new resume key allocate, length %d",
1438                                   cifsFile->resume_name_length));
1439                 return;
1440         }
1441         if(Unicode)
1442                 cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
1443                         filename, len, nls_tab);
1444         else
1445                 memcpy(cifsFile->search_resume_name, filename, 
1446                    cifsFile->resume_name_length);
1447         cFYI(1,("Reset resume key to: %s with len %d",filename,len));
1448         return;
1449 }
1450
1451
1452
1453 static int
1454 cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
1455              struct file *file, filldir_t filldir, void *direntry)
1456 {
1457         struct inode *tmp_inode;
1458         struct dentry *tmp_dentry;
1459         int object_type,rc;
1460
1461         pqstring->name = pfindData->FileName;
1462         pqstring->len = pfindData->FileNameLength;
1463
1464         construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
1465
1466         fill_in_inode(tmp_inode, pfindData, &object_type);
1467         rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
1468                 tmp_inode->i_ino, object_type);
1469         if(rc) {
1470                 /* due to readdir error we need to recalculate resume 
1471                 key so next readdir will restart on right entry */
1472                 cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
1473         }
1474         dput(tmp_dentry);
1475         return rc;
1476 }
1477
1478 static int
1479 cifs_filldir_unix(struct qstr *pqstring,
1480                   FILE_UNIX_INFO * pUnixFindData, struct file *file,
1481                   filldir_t filldir, void *direntry)
1482 {
1483         struct inode *tmp_inode;
1484         struct dentry *tmp_dentry;
1485         int object_type, rc;
1486
1487         pqstring->name = pUnixFindData->FileName;
1488         pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
1489
1490         construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
1491
1492         unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
1493         rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
1494                 file->f_pos, tmp_inode->i_ino, object_type);
1495         if(rc) {
1496                 /* due to readdir error we need to recalculate resume 
1497                         key so next readdir will restart on right entry */
1498                 cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
1499         }
1500         dput(tmp_dentry);
1501         return rc;
1502 }
1503
1504 int
1505 cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
1506 {
1507         int rc = 0;
1508         int xid;
1509         int Unicode = FALSE;
1510         int UnixSearch = FALSE;
1511         unsigned int bufsize, i;
1512         __u16 searchHandle;
1513         struct cifs_sb_info *cifs_sb;
1514         struct cifsTconInfo *pTcon;
1515         struct cifsFileInfo *cifsFile = NULL;
1516         char *full_path = NULL;
1517         char *data;
1518         struct qstr qstring;
1519         T2_FFIRST_RSP_PARMS findParms;
1520         T2_FNEXT_RSP_PARMS findNextParms;
1521         FILE_DIRECTORY_INFO *pfindData;
1522         FILE_DIRECTORY_INFO *lastFindData;
1523         FILE_UNIX_INFO *pfindDataUnix;
1524
1525         xid = GetXid();
1526
1527         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1528         pTcon = cifs_sb->tcon;
1529         bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
1530         if(bufsize > CIFS_MAX_MSGSIZE) {
1531                 FreeXid(xid);
1532                 return -EIO;
1533         }
1534         data = kmalloc(bufsize, GFP_KERNEL);
1535         pfindData = (FILE_DIRECTORY_INFO *) data;
1536
1537         full_path = build_wildcard_path_from_dentry(file->f_dentry);
1538
1539         cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
1540
1541         switch ((int) file->f_pos) {
1542         case 0:
1543                 if (filldir(direntry, ".", 1, file->f_pos,
1544                      file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
1545                         cERROR(1, ("Filldir for current dir failed "));
1546                         break;
1547                 }
1548                 file->f_pos++;
1549                 /* fallthrough */
1550         case 1:
1551                 if (filldir(direntry, "..", 2, file->f_pos,
1552                      file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
1553                         cERROR(1, ("Filldir for parent dir failed "));
1554                         break;
1555                 }
1556                 file->f_pos++;
1557                 /* fallthrough */
1558         case 2:
1559                 if (file->private_data != NULL) {
1560                         cifsFile =
1561                                 (struct cifsFileInfo *) file->private_data;
1562                         if (cifsFile->endOfSearch) {
1563                                 if(cifsFile->emptyDir) {
1564                                         cFYI(1, ("End of search, empty dir"));
1565                                         rc = 0;
1566                                         break;
1567                                 }
1568                         } else {
1569                                 cifsFile->invalidHandle = TRUE;
1570                                 CIFSFindClose(xid, pTcon, cifsFile->netfid);
1571                         }
1572                         if(cifsFile->search_resume_name) {
1573                                 kfree(cifsFile->search_resume_name);
1574                                 cifsFile->search_resume_name = NULL;
1575                         }
1576                 }
1577                 rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
1578                                 &findParms, cifs_sb->local_nls,
1579                                 &Unicode, &UnixSearch);
1580                 cFYI(1, ("Count: %d  End: %d ", findParms.SearchCount,
1581                         findParms.EndofSearch));
1582  
1583                 if (rc == 0) {
1584                         searchHandle = findParms.SearchHandle;
1585                         if(file->private_data == NULL)
1586                                 file->private_data =
1587                                         kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
1588                         if (file->private_data) {
1589                                 memset(file->private_data, 0,
1590                                        sizeof (struct cifsFileInfo));
1591                                 cifsFile =
1592                                     (struct cifsFileInfo *) file->private_data;
1593                                 cifsFile->netfid = searchHandle;
1594                                 cifsFile->invalidHandle = FALSE;
1595                                 init_MUTEX(&cifsFile->fh_sem);
1596                         } else {
1597                                 rc = -ENOMEM;
1598                                 break;
1599                         }
1600
1601                         renew_parental_timestamps(file->f_dentry);
1602                         lastFindData = 
1603                                 (FILE_DIRECTORY_INFO *) ((char *) pfindData + 
1604                                         findParms.LastNameOffset);
1605                         if((char *)lastFindData > (char *)pfindData + bufsize) {
1606                                 cFYI(1,("last search entry past end of packet"));
1607                                 rc = -EIO;
1608                                 break;
1609                         }
1610                         /* Offset of resume key same for levels 257 and 514 */
1611                         cifsFile->resume_key = lastFindData->FileIndex;
1612                         if(UnixSearch == FALSE) {
1613                                 cifsFile->resume_name_length = 
1614                                         le32_to_cpu(lastFindData->FileNameLength);
1615                                 if(cifsFile->resume_name_length > bufsize - 64) {
1616                                         cFYI(1,("Illegal resume file name length %d",
1617                                                 cifsFile->resume_name_length));
1618                                         rc = -ENOMEM;
1619                                         break;
1620                                 }
1621                                 cifsFile->search_resume_name = 
1622                                         kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1623                                 cFYI(1,("Last file: %s with name %d bytes long",
1624                                         lastFindData->FileName,
1625                                         cifsFile->resume_name_length));
1626                                 memcpy(cifsFile->search_resume_name,
1627                                         lastFindData->FileName, 
1628                                         cifsFile->resume_name_length);
1629                         } else {
1630                                 pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
1631                                 if (Unicode == TRUE) {
1632                                         for(i=0;(pfindDataUnix->FileName[i] 
1633                                                     | pfindDataUnix->FileName[i+1]);
1634                                                 i+=2) {
1635                                                 if(i > bufsize-64)
1636                                                         break;
1637                                         }
1638                                         cifsFile->resume_name_length = i + 2;
1639                                 } else {
1640                                         cifsFile->resume_name_length = 
1641                                                 strnlen(pfindDataUnix->FileName,
1642                                                         bufsize-63);
1643                                 }
1644                                 if(cifsFile->resume_name_length > bufsize - 64) {
1645                                         cFYI(1,("Illegal resume file name length %d",
1646                                                 cifsFile->resume_name_length));
1647                                         rc = -ENOMEM;
1648                                         break;
1649                                 }
1650                                 cifsFile->search_resume_name = 
1651                                         kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1652                                 cFYI(1,("Last file: %s with name %d bytes long",
1653                                         pfindDataUnix->FileName,
1654                                         cifsFile->resume_name_length));
1655                                 memcpy(cifsFile->search_resume_name,
1656                                         pfindDataUnix->FileName, 
1657                                         cifsFile->resume_name_length);
1658                         }
1659                         for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
1660                                 if (UnixSearch == FALSE) {
1661                                         pfindData->FileNameLength =
1662                                           le32_to_cpu(pfindData->FileNameLength);
1663                                         if (Unicode == TRUE)
1664                                                 pfindData->FileNameLength =
1665                                                     cifs_strfromUCS_le
1666                                                     (pfindData->FileName,
1667                                                      (wchar_t *)
1668                                                      pfindData->FileName,
1669                                                      (pfindData->
1670                                                       FileNameLength) / 2,
1671                                                      cifs_sb->local_nls);
1672                                         qstring.len = pfindData->FileNameLength;
1673                                         if (((qstring.len != 1)
1674                                              || (pfindData->FileName[0] != '.'))
1675                                             && ((qstring.len != 2)
1676                                                 || (pfindData->
1677                                                     FileName[0] != '.')
1678                                                 || (pfindData->
1679                                                     FileName[1] != '.'))) {
1680                                                 if(cifs_filldir(&qstring,
1681                                                              pfindData,
1682                                                              file, filldir,
1683                                                              direntry)) {
1684                                                         /* do not end search if
1685                                                                 kernel not ready to take
1686                                                                 remaining entries yet */
1687                                                         reset_resume_key(file, pfindData->FileName,qstring.len,
1688                                                                 Unicode, cifs_sb->local_nls);
1689                                                         findParms.EndofSearch = 0;
1690                                                         break;
1691                                                 }
1692                                                 file->f_pos++;
1693                                         }
1694                                 } else {        /* UnixSearch */
1695                                         pfindDataUnix =
1696                                             (FILE_UNIX_INFO *) pfindData;
1697                                         if (Unicode == TRUE)
1698                                                 qstring.len =
1699                                                         cifs_strfromUCS_le
1700                                                         (pfindDataUnix->FileName,
1701                                                         (wchar_t *)
1702                                                         pfindDataUnix->FileName,
1703                                                         MAX_PATHCONF,
1704                                                         cifs_sb->local_nls);
1705                                         else
1706                                                 qstring.len =
1707                                                         strnlen(pfindDataUnix->
1708                                                           FileName,
1709                                                           MAX_PATHCONF);
1710                                         if (((qstring.len != 1)
1711                                              || (pfindDataUnix->
1712                                                  FileName[0] != '.'))
1713                                             && ((qstring.len != 2)
1714                                                 || (pfindDataUnix->
1715                                                     FileName[0] != '.')
1716                                                 || (pfindDataUnix->
1717                                                     FileName[1] != '.'))) {
1718                                                 if(cifs_filldir_unix(&qstring,
1719                                                                   pfindDataUnix,
1720                                                                   file,
1721                                                                   filldir,
1722                                                                   direntry)) {
1723                                                         /* do not end search if
1724                                                                 kernel not ready to take
1725                                                                 remaining entries yet */
1726                                                         findParms.EndofSearch = 0;
1727                                                         reset_resume_key(file, pfindDataUnix->FileName,
1728                                                                 qstring.len,Unicode,cifs_sb->local_nls);
1729                                                         break;
1730                                                 }
1731                                                 file->f_pos++;
1732                                         }
1733                                 }
1734                                 /* works also for Unix ff struct since first field of both */
1735                                 pfindData = 
1736                                         (FILE_DIRECTORY_INFO *) ((char *) pfindData
1737                                                  + le32_to_cpu(pfindData->NextEntryOffset));
1738                                 /* BB also should check to make sure that pointer is not beyond the end of the SMB */
1739                                 /* if(pfindData > lastFindData) rc = -EIO; break; */
1740                         }       /* end for loop */
1741                         if ((findParms.EndofSearch != 0) && cifsFile) {
1742                                 cifsFile->endOfSearch = TRUE;
1743                                 if(findParms.SearchCount == 2)
1744                                         cifsFile->emptyDir = TRUE;
1745                         }
1746                 } else {
1747                         if (cifsFile)
1748                                 cifsFile->endOfSearch = TRUE;
1749                         /* unless parent directory gone do not return error */
1750                         rc = 0;
1751                 }
1752                 break;
1753         default:
1754                 if (file->private_data == NULL) {
1755                         rc = -EBADF;
1756                         cFYI(1,
1757                              ("Readdir on closed srch, pos = %lld",
1758                               file->f_pos));
1759                 } else {
1760                         cifsFile = (struct cifsFileInfo *) file->private_data;
1761                         if (cifsFile->endOfSearch) {
1762                                 rc = 0;
1763                                 cFYI(1, ("End of search "));
1764                                 break;
1765                         }
1766                         searchHandle = cifsFile->netfid;
1767                         rc = CIFSFindNext(xid, pTcon, pfindData,
1768                                 &findNextParms, searchHandle, 
1769                                 cifsFile->search_resume_name,
1770                                 cifsFile->resume_name_length,
1771                                 cifsFile->resume_key,
1772                                 &Unicode, &UnixSearch);
1773                         cFYI(1,("Count: %d  End: %d ",
1774                               findNextParms.SearchCount,
1775                               findNextParms.EndofSearch));
1776                         if ((rc == 0) && (findNextParms.SearchCount != 0)) {
1777                         /* BB save off resume key, key name and name length  */
1778                                 lastFindData = 
1779                                         (FILE_DIRECTORY_INFO *) ((char *) pfindData 
1780                                                 + findNextParms.LastNameOffset);
1781                                 if((char *)lastFindData > (char *)pfindData + bufsize) {
1782                                         cFYI(1,("last search entry past end of packet"));
1783                                         rc = -EIO;
1784                                         break;
1785                                 }
1786                                 /* Offset of resume key same for levels 257 and 514 */
1787                                 cifsFile->resume_key = lastFindData->FileIndex;
1788
1789                                 if(UnixSearch == FALSE) {
1790                                         cifsFile->resume_name_length = 
1791                                                 le32_to_cpu(lastFindData->FileNameLength);
1792                                         if(cifsFile->resume_name_length > bufsize - 64) {
1793                                                 cFYI(1,("Illegal resume file name length %d",
1794                                                         cifsFile->resume_name_length));
1795                                                 rc = -ENOMEM;
1796                                                 break;
1797                                         }
1798                                         /* Free the memory allocated by previous findfirst 
1799                                         or findnext call - we can not reuse the memory since
1800                                         the resume name may not be same string length */
1801                                         if(cifsFile->search_resume_name)
1802                                                 kfree(cifsFile->search_resume_name);
1803                                         cifsFile->search_resume_name = 
1804                                                 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1805                                         cFYI(1,("Last file: %s with name %d bytes long",
1806                                                 lastFindData->FileName,
1807                                                 cifsFile->resume_name_length));
1808                                         memcpy(cifsFile->search_resume_name,
1809                                                 lastFindData->FileName, 
1810                                                 cifsFile->resume_name_length);
1811                                 } else {
1812                                         pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
1813                                         if (Unicode == TRUE) {
1814                                                 for(i=0;(pfindDataUnix->FileName[i] 
1815                                                                 | pfindDataUnix->FileName[i+1]);
1816                                                         i+=2) {
1817                                                         if(i > bufsize-64)
1818                                                                 break;
1819                                                 }
1820                                                 cifsFile->resume_name_length = i + 2;
1821                                         } else {
1822                                                 cifsFile->resume_name_length = 
1823                                                         strnlen(pfindDataUnix->
1824                                                          FileName,
1825                                                          MAX_PATHCONF);
1826                                         }
1827                                         if(cifsFile->resume_name_length > bufsize - 64) {
1828                                                 cFYI(1,("Illegal resume file name length %d",
1829                                                                 cifsFile->resume_name_length));
1830                                                 rc = -ENOMEM;
1831                                                 break;
1832                                         }
1833                                         /* Free the memory allocated by previous findfirst 
1834                                         or findnext call - we can not reuse the memory since
1835                                         the resume name may not be same string length */
1836                                         if(cifsFile->search_resume_name)
1837                                                 kfree(cifsFile->search_resume_name);
1838                                         cifsFile->search_resume_name = 
1839                                                 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1840                                         cFYI(1,("fnext last file: %s with name %d bytes long",
1841                                                 pfindDataUnix->FileName,
1842                                                 cifsFile->resume_name_length));
1843                                         memcpy(cifsFile->search_resume_name,
1844                                                 pfindDataUnix->FileName, 
1845                                                 cifsFile->resume_name_length);
1846                                 }
1847
1848                                 for (i = 0; i < findNextParms.SearchCount; i++) {
1849                                         pfindData->FileNameLength =
1850                                             le32_to_cpu(pfindData->
1851                                                         FileNameLength);
1852                                         if (UnixSearch == FALSE) {
1853                                                 if (Unicode == TRUE)
1854                                                         pfindData->FileNameLength =
1855                                                           cifs_strfromUCS_le
1856                                                           (pfindData->FileName,
1857                                                           (wchar_t *)
1858                                                           pfindData->FileName,
1859                                                           (pfindData->FileNameLength)/ 2,
1860                                                           cifs_sb->local_nls);
1861                                                 qstring.len = 
1862                                                         pfindData->FileNameLength;
1863                                                 if (((qstring.len != 1)
1864                                                     || (pfindData->FileName[0] != '.'))
1865                                                     && ((qstring.len != 2)
1866                                                         || (pfindData->FileName[0] != '.')
1867                                                         || (pfindData->FileName[1] !=
1868                                                             '.'))) {
1869                                                         if(cifs_filldir
1870                                                             (&qstring,
1871                                                              pfindData,
1872                                                              file, filldir,
1873                                                              direntry)) {
1874                                                         /* do not end search if
1875                                                                 kernel not ready to take
1876                                                                 remaining entries yet */
1877                                                                 findNextParms.EndofSearch = 0;
1878                                                                 reset_resume_key(file, pfindData->FileName,qstring.len,
1879                                                                         Unicode,cifs_sb->local_nls);
1880                                                                 break;
1881                                                         }
1882                                                         file->f_pos++;
1883                                                 }
1884                                         } else {        /* UnixSearch */
1885                                                 pfindDataUnix =
1886                                                     (FILE_UNIX_INFO *)
1887                                                     pfindData;
1888                                                 if (Unicode == TRUE)
1889                                                         qstring.len =
1890                                                           cifs_strfromUCS_le
1891                                                           (pfindDataUnix->FileName,
1892                                                           (wchar_t *)
1893                                                           pfindDataUnix->FileName,
1894                                                           MAX_PATHCONF,
1895                                                           cifs_sb->local_nls);
1896                                                 else
1897                                                         qstring.len =
1898                                                           strnlen
1899                                                           (pfindDataUnix->
1900                                                           FileName,
1901                                                           MAX_PATHCONF);
1902                                                 if (((qstring.len != 1)
1903                                                      || (pfindDataUnix->
1904                                                          FileName[0] != '.'))
1905                                                     && ((qstring.len != 2)
1906                                                         || (pfindDataUnix->
1907                                                             FileName[0] != '.')
1908                                                         || (pfindDataUnix->
1909                                                             FileName[1] !=
1910                                                             '.'))) {
1911                                                         if(cifs_filldir_unix
1912                                                             (&qstring,
1913                                                              pfindDataUnix,
1914                                                              file, filldir,
1915                                                              direntry)) {
1916                                                                 /* do not end search if
1917                                                                 kernel not ready to take
1918                                                                 remaining entries yet */
1919                                                                 findNextParms.EndofSearch = 0;
1920                                                                 reset_resume_key(file, pfindDataUnix->FileName,qstring.len,
1921                                                                         Unicode,cifs_sb->local_nls);
1922                                                                 break;
1923                                                         }
1924                                                         file->f_pos++;
1925                                                 }
1926                                         }
1927                                         pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData + 
1928                                                 le32_to_cpu(pfindData->NextEntryOffset));
1929         /* works also for Unix find struct since first field of both */
1930         /* BB also should check to ensure pointer not beyond end of SMB */
1931                                 } /* end for loop */
1932                                 if (findNextParms.EndofSearch != 0) {
1933                                         cifsFile->endOfSearch = TRUE;
1934                                 }
1935                         } else {
1936                                 cifsFile->endOfSearch = TRUE;
1937                                 rc = 0; /* unless parent directory disappeared - do not
1938                                 return error here (eg Access Denied or no more files) */
1939                         }
1940                 }
1941         } /* end switch */
1942         if (data)
1943                 kfree(data);
1944         if (full_path)
1945                 kfree(full_path);
1946         FreeXid(xid);
1947
1948         return rc;
1949 }
1950 int cifs_prepare_write(struct file *file, struct page *page,
1951                         unsigned from, unsigned to)
1952 {
1953         cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
1954         if (!PageUptodate(page)) {
1955                 if (to - from != PAGE_CACHE_SIZE) {
1956                         void *kaddr = kmap_atomic(page, KM_USER0);
1957                         memset(kaddr, 0, from);
1958                         memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1959                         flush_dcache_page(page);
1960                         kunmap_atomic(kaddr, KM_USER0);
1961                 }
1962                 SetPageUptodate(page);
1963         }
1964         return 0;
1965 }
1966
1967
1968 struct address_space_operations cifs_addr_ops = {
1969         .readpage = cifs_readpage,
1970         .readpages = cifs_readpages,
1971         .writepage = cifs_writepage,
1972         .prepare_write = simple_prepare_write, /* BB fixme BB */
1973 /*      .prepare_write = cifs_prepare_write, */  /* BB removeme BB */
1974         .commit_write = cifs_commit_write,
1975    /* .sync_page = cifs_sync_page, */
1976         /*.direct_IO = */
1977 };