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