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