[CIFS] CIFS readdir perf optimizations part 1
[powerpc.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/backing-dev.h>
25 #include <linux/stat.h>
26 #include <linux/fcntl.h>
27 #include <linux/mpage.h>
28 #include <linux/pagemap.h>
29 #include <linux/pagevec.h>
30 #include <linux/smp_lock.h>
31 #include <linux/writeback.h>
32 #include <linux/delay.h>
33 #include <asm/div64.h>
34 #include "cifsfs.h"
35 #include "cifspdu.h"
36 #include "cifsglob.h"
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
40 #include "cifs_fs_sb.h"
41
42 static inline struct cifsFileInfo *cifs_init_private(
43         struct cifsFileInfo *private_data, struct inode *inode,
44         struct file *file, __u16 netfid)
45 {
46         memset(private_data, 0, sizeof(struct cifsFileInfo));
47         private_data->netfid = netfid;
48         private_data->pid = current->tgid;      
49         init_MUTEX(&private_data->fh_sem);
50         private_data->pfile = file; /* needed for writepage */
51         private_data->pInode = inode;
52         private_data->invalidHandle = FALSE;
53         private_data->closePend = FALSE;
54         /* we have to track num writers to the inode, since writepages
55         does not tell us which handle the write is for so there can
56         be a close (overlapping with write) of the filehandle that
57         cifs_writepages chose to use */
58         atomic_set(&private_data->wrtPending,0); 
59
60         return private_data;
61 }
62
63 static inline int cifs_convert_flags(unsigned int flags)
64 {
65         if ((flags & O_ACCMODE) == O_RDONLY)
66                 return GENERIC_READ;
67         else if ((flags & O_ACCMODE) == O_WRONLY)
68                 return GENERIC_WRITE;
69         else if ((flags & O_ACCMODE) == O_RDWR) {
70                 /* GENERIC_ALL is too much permission to request
71                    can cause unnecessary access denied on create */
72                 /* return GENERIC_ALL; */
73                 return (GENERIC_READ | GENERIC_WRITE);
74         }
75
76         return 0x20197;
77 }
78
79 static inline int cifs_get_disposition(unsigned int flags)
80 {
81         if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
82                 return FILE_CREATE;
83         else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
84                 return FILE_OVERWRITE_IF;
85         else if ((flags & O_CREAT) == O_CREAT)
86                 return FILE_OPEN_IF;
87         else
88                 return FILE_OPEN;
89 }
90
91 /* all arguments to this function must be checked for validity in caller */
92 static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
93         struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
94         struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
95         char *full_path, int xid)
96 {
97         struct timespec temp;
98         int rc;
99
100         /* want handles we can use to read with first
101            in the list so we do not have to walk the
102            list to search for one in prepare_write */
103         if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
104                 list_add_tail(&pCifsFile->flist, 
105                               &pCifsInode->openFileList);
106         } else {
107                 list_add(&pCifsFile->flist,
108                          &pCifsInode->openFileList);
109         }
110         write_unlock(&GlobalSMBSeslock);
111         write_unlock(&file->f_owner.lock);
112         if (pCifsInode->clientCanCacheRead) {
113                 /* we have the inode open somewhere else
114                    no need to discard cache data */
115                 goto client_can_cache;
116         }
117
118         /* BB need same check in cifs_create too? */
119         /* if not oplocked, invalidate inode pages if mtime or file
120            size changed */
121         temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
122         if (timespec_equal(&file->f_dentry->d_inode->i_mtime, &temp) && 
123                            (file->f_dentry->d_inode->i_size == 
124                             (loff_t)le64_to_cpu(buf->EndOfFile))) {
125                 cFYI(1, ("inode unchanged on server"));
126         } else {
127                 if (file->f_dentry->d_inode->i_mapping) {
128                 /* BB no need to lock inode until after invalidate
129                    since namei code should already have it locked? */
130                         filemap_write_and_wait(file->f_dentry->d_inode->i_mapping);
131                 }
132                 cFYI(1, ("invalidating remote inode since open detected it "
133                          "changed"));
134                 invalidate_remote_inode(file->f_dentry->d_inode);
135         }
136
137 client_can_cache:
138         if (pTcon->ses->capabilities & CAP_UNIX)
139                 rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
140                         full_path, inode->i_sb, xid);
141         else
142                 rc = cifs_get_inode_info(&file->f_dentry->d_inode,
143                         full_path, buf, inode->i_sb, xid);
144
145         if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
146                 pCifsInode->clientCanCacheAll = TRUE;
147                 pCifsInode->clientCanCacheRead = TRUE;
148                 cFYI(1, ("Exclusive Oplock granted on inode %p",
149                          file->f_dentry->d_inode));
150         } else if ((*oplock & 0xF) == OPLOCK_READ)
151                 pCifsInode->clientCanCacheRead = TRUE;
152
153         return rc;
154 }
155
156 int cifs_open(struct inode *inode, struct file *file)
157 {
158         int rc = -EACCES;
159         int xid, oplock;
160         struct cifs_sb_info *cifs_sb;
161         struct cifsTconInfo *pTcon;
162         struct cifsFileInfo *pCifsFile;
163         struct cifsInodeInfo *pCifsInode;
164         struct list_head *tmp;
165         char *full_path = NULL;
166         int desiredAccess;
167         int disposition;
168         __u16 netfid;
169         FILE_ALL_INFO *buf = NULL;
170
171         xid = GetXid();
172
173         cifs_sb = CIFS_SB(inode->i_sb);
174         pTcon = cifs_sb->tcon;
175
176         if (file->f_flags & O_CREAT) {
177                 /* search inode for this file and fill in file->private_data */
178                 pCifsInode = CIFS_I(file->f_dentry->d_inode);
179                 read_lock(&GlobalSMBSeslock);
180                 list_for_each(tmp, &pCifsInode->openFileList) {
181                         pCifsFile = list_entry(tmp, struct cifsFileInfo,
182                                                flist);
183                         if ((pCifsFile->pfile == NULL) &&
184                             (pCifsFile->pid == current->tgid)) {
185                                 /* mode set in cifs_create */
186
187                                 /* needed for writepage */
188                                 pCifsFile->pfile = file;
189                                 
190                                 file->private_data = pCifsFile;
191                                 break;
192                         }
193                 }
194                 read_unlock(&GlobalSMBSeslock);
195                 if (file->private_data != NULL) {
196                         rc = 0;
197                         FreeXid(xid);
198                         return rc;
199                 } else {
200                         if (file->f_flags & O_EXCL)
201                                 cERROR(1, ("could not find file instance for "
202                                            "new file %p ", file));
203                 }
204         }
205
206         down(&inode->i_sb->s_vfs_rename_sem);
207         full_path = build_path_from_dentry(file->f_dentry);
208         up(&inode->i_sb->s_vfs_rename_sem);
209         if (full_path == NULL) {
210                 FreeXid(xid);
211                 return -ENOMEM;
212         }
213
214         cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
215                  inode, file->f_flags, full_path));
216         desiredAccess = cifs_convert_flags(file->f_flags);
217
218 /*********************************************************************
219  *  open flag mapping table:
220  *  
221  *      POSIX Flag            CIFS Disposition
222  *      ----------            ---------------- 
223  *      O_CREAT               FILE_OPEN_IF
224  *      O_CREAT | O_EXCL      FILE_CREATE
225  *      O_CREAT | O_TRUNC     FILE_OVERWRITE_IF
226  *      O_TRUNC               FILE_OVERWRITE
227  *      none of the above     FILE_OPEN
228  *
229  *      Note that there is not a direct match between disposition
230  *      FILE_SUPERSEDE (ie create whether or not file exists although 
231  *      O_CREAT | O_TRUNC is similar but truncates the existing
232  *      file rather than creating a new file as FILE_SUPERSEDE does
233  *      (which uses the attributes / metadata passed in on open call)
234  *?
235  *?  O_SYNC is a reasonable match to CIFS writethrough flag  
236  *?  and the read write flags match reasonably.  O_LARGEFILE
237  *?  is irrelevant because largefile support is always used
238  *?  by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
239  *       O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
240  *********************************************************************/
241
242         disposition = cifs_get_disposition(file->f_flags);
243
244         if (oplockEnabled)
245                 oplock = REQ_OPLOCK;
246         else
247                 oplock = FALSE;
248
249         /* BB pass O_SYNC flag through on file attributes .. BB */
250
251         /* Also refresh inode by passing in file_info buf returned by SMBOpen
252            and calling get_inode_info with returned buf (at least helps
253            non-Unix server case) */
254
255         /* BB we can not do this if this is the second open of a file 
256            and the first handle has writebehind data, we might be 
257            able to simply do a filemap_fdatawrite/filemap_fdatawait first */
258         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
259         if (!buf) {
260                 rc = -ENOMEM;
261                 goto out;
262         }
263         rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
264                          CREATE_NOT_DIR, &netfid, &oplock, buf,
265                          cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
266                                  & CIFS_MOUNT_MAP_SPECIAL_CHR);
267         if (rc == -EIO) {
268                 /* Old server, try legacy style OpenX */
269                 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
270                         desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
271                         cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
272                                 & CIFS_MOUNT_MAP_SPECIAL_CHR);
273         }
274         if (rc) {
275                 cFYI(1, ("cifs_open returned 0x%x ", rc));
276                 goto out;
277         }
278         file->private_data =
279                 kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
280         if (file->private_data == NULL) {
281                 rc = -ENOMEM;
282                 goto out;
283         }
284         pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
285         write_lock(&file->f_owner.lock);
286         write_lock(&GlobalSMBSeslock);
287         list_add(&pCifsFile->tlist, &pTcon->openFileList);
288
289         pCifsInode = CIFS_I(file->f_dentry->d_inode);
290         if (pCifsInode) {
291                 rc = cifs_open_inode_helper(inode, file, pCifsInode,
292                                             pCifsFile, pTcon,
293                                             &oplock, buf, full_path, xid);
294         } else {
295                 write_unlock(&GlobalSMBSeslock);
296                 write_unlock(&file->f_owner.lock);
297         }
298
299         if (oplock & CIFS_CREATE_ACTION) {           
300                 /* time to set mode which we can not set earlier due to
301                    problems creating new read-only files */
302                 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
303                         CIFSSMBUnixSetPerms(xid, pTcon, full_path,
304                                             inode->i_mode,
305                                             (__u64)-1, (__u64)-1, 0 /* dev */,
306                                             cifs_sb->local_nls,
307                                             cifs_sb->mnt_cifs_flags & 
308                                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
309                 } else {
310                         /* BB implement via Windows security descriptors eg
311                            CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
312                                               -1, -1, local_nls);
313                            in the meantime could set r/o dos attribute when
314                            perms are eg: mode & 0222 == 0 */
315                 }
316         }
317
318 out:
319         kfree(buf);
320         kfree(full_path);
321         FreeXid(xid);
322         return rc;
323 }
324
325 /* Try to reaquire byte range locks that were released when session */
326 /* to server was lost */
327 static int cifs_relock_file(struct cifsFileInfo *cifsFile)
328 {
329         int rc = 0;
330
331 /* BB list all locks open on this file and relock */
332
333         return rc;
334 }
335
336 static int cifs_reopen_file(struct inode *inode, struct file *file, 
337         int can_flush)
338 {
339         int rc = -EACCES;
340         int xid, oplock;
341         struct cifs_sb_info *cifs_sb;
342         struct cifsTconInfo *pTcon;
343         struct cifsFileInfo *pCifsFile;
344         struct cifsInodeInfo *pCifsInode;
345         char *full_path = NULL;
346         int desiredAccess;
347         int disposition = FILE_OPEN;
348         __u16 netfid;
349
350         if (inode == NULL)
351                 return -EBADF;
352         if (file->private_data) {
353                 pCifsFile = (struct cifsFileInfo *)file->private_data;
354         } else
355                 return -EBADF;
356
357         xid = GetXid();
358         down(&pCifsFile->fh_sem);
359         if (pCifsFile->invalidHandle == FALSE) {
360                 up(&pCifsFile->fh_sem);
361                 FreeXid(xid);
362                 return 0;
363         }
364
365         if (file->f_dentry == NULL) {
366                 up(&pCifsFile->fh_sem);
367                 cFYI(1, ("failed file reopen, no valid name if dentry freed"));
368                 FreeXid(xid);
369                 return -EBADF;
370         }
371         cifs_sb = CIFS_SB(inode->i_sb);
372         pTcon = cifs_sb->tcon;
373 /* can not grab rename sem here because various ops, including
374    those that already have the rename sem can end up causing writepage
375    to get called and if the server was down that means we end up here,
376    and we can never tell if the caller already has the rename_sem */
377         full_path = build_path_from_dentry(file->f_dentry);
378         if (full_path == NULL) {
379                 up(&pCifsFile->fh_sem);
380                 FreeXid(xid);
381                 return -ENOMEM;
382         }
383
384         cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
385                  inode, file->f_flags,full_path));
386         desiredAccess = cifs_convert_flags(file->f_flags);
387
388         if (oplockEnabled)
389                 oplock = REQ_OPLOCK;
390         else
391                 oplock = FALSE;
392
393         /* Can not refresh inode by passing in file_info buf to be returned
394            by SMBOpen and then calling get_inode_info with returned buf 
395            since file might have write behind data that needs to be flushed 
396            and server version of file size can be stale. If we knew for sure
397            that inode was not dirty locally we could do this */
398
399 /*      buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
400         if (buf == 0) {
401                 up(&pCifsFile->fh_sem);
402                 kfree(full_path);
403                 FreeXid(xid);
404                 return -ENOMEM;
405         } */
406         rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
407                          CREATE_NOT_DIR, &netfid, &oplock, NULL,
408                          cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 
409                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
410         if (rc) {
411                 up(&pCifsFile->fh_sem);
412                 cFYI(1, ("cifs_open returned 0x%x ", rc));
413                 cFYI(1, ("oplock: %d ", oplock));
414         } else {
415                 pCifsFile->netfid = netfid;
416                 pCifsFile->invalidHandle = FALSE;
417                 up(&pCifsFile->fh_sem);
418                 pCifsInode = CIFS_I(inode);
419                 if (pCifsInode) {
420                         if (can_flush) {
421                                 filemap_write_and_wait(inode->i_mapping);
422                         /* temporarily disable caching while we
423                            go to server to get inode info */
424                                 pCifsInode->clientCanCacheAll = FALSE;
425                                 pCifsInode->clientCanCacheRead = FALSE;
426                                 if (pTcon->ses->capabilities & CAP_UNIX)
427                                         rc = cifs_get_inode_info_unix(&inode,
428                                                 full_path, inode->i_sb, xid);
429                                 else
430                                         rc = cifs_get_inode_info(&inode,
431                                                 full_path, NULL, inode->i_sb,
432                                                 xid);
433                         } /* else we are writing out data to server already
434                              and could deadlock if we tried to flush data, and
435                              since we do not know if we have data that would
436                              invalidate the current end of file on the server
437                              we can not go to the server to get the new inod
438                              info */
439                         if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
440                                 pCifsInode->clientCanCacheAll = TRUE;
441                                 pCifsInode->clientCanCacheRead = TRUE;
442                                 cFYI(1, ("Exclusive Oplock granted on inode %p",
443                                          file->f_dentry->d_inode));
444                         } else if ((oplock & 0xF) == OPLOCK_READ) {
445                                 pCifsInode->clientCanCacheRead = TRUE;
446                                 pCifsInode->clientCanCacheAll = FALSE;
447                         } else {
448                                 pCifsInode->clientCanCacheRead = FALSE;
449                                 pCifsInode->clientCanCacheAll = FALSE;
450                         }
451                         cifs_relock_file(pCifsFile);
452                 }
453         }
454
455         kfree(full_path);
456         FreeXid(xid);
457         return rc;
458 }
459
460 int cifs_close(struct inode *inode, struct file *file)
461 {
462         int rc = 0;
463         int xid;
464         struct cifs_sb_info *cifs_sb;
465         struct cifsTconInfo *pTcon;
466         struct cifsFileInfo *pSMBFile =
467                 (struct cifsFileInfo *)file->private_data;
468
469         xid = GetXid();
470
471         cifs_sb = CIFS_SB(inode->i_sb);
472         pTcon = cifs_sb->tcon;
473         if (pSMBFile) {
474                 pSMBFile->closePend = TRUE;
475                 write_lock(&file->f_owner.lock);
476                 if (pTcon) {
477                         /* no sense reconnecting to close a file that is
478                            already closed */
479                         if (pTcon->tidStatus != CifsNeedReconnect) {
480                                 int timeout = 2;
481                                 while((atomic_read(&pSMBFile->wrtPending) != 0)
482                                          && (timeout < 1000) ) {
483                                         /* Give write a better chance to get to
484                                         server ahead of the close.  We do not
485                                         want to add a wait_q here as it would
486                                         increase the memory utilization as
487                                         the struct would be in each open file,
488                                         but this should give enough time to 
489                                         clear the socket */
490                                         write_unlock(&file->f_owner.lock);
491                                         cERROR(1,("close with pending writes"));
492                                         msleep(timeout);
493                                         write_lock(&file->f_owner.lock);
494                                         timeout *= 4;
495                                 } 
496                                 write_unlock(&file->f_owner.lock);
497                                 rc = CIFSSMBClose(xid, pTcon,
498                                                   pSMBFile->netfid);
499                                 write_lock(&file->f_owner.lock);
500                         }
501                 }
502                 write_lock(&GlobalSMBSeslock);
503                 list_del(&pSMBFile->flist);
504                 list_del(&pSMBFile->tlist);
505                 write_unlock(&GlobalSMBSeslock);
506                 write_unlock(&file->f_owner.lock);
507                 kfree(pSMBFile->search_resume_name);
508                 kfree(file->private_data);
509                 file->private_data = NULL;
510         } else
511                 rc = -EBADF;
512
513         if (list_empty(&(CIFS_I(inode)->openFileList))) {
514                 cFYI(1, ("closing last open instance for inode %p", inode));
515                 /* if the file is not open we do not know if we can cache info
516                    on this inode, much less write behind and read ahead */
517                 CIFS_I(inode)->clientCanCacheRead = FALSE;
518                 CIFS_I(inode)->clientCanCacheAll  = FALSE;
519         }
520         if ((rc ==0) && CIFS_I(inode)->write_behind_rc)
521                 rc = CIFS_I(inode)->write_behind_rc;
522         FreeXid(xid);
523         return rc;
524 }
525
526 int cifs_closedir(struct inode *inode, struct file *file)
527 {
528         int rc = 0;
529         int xid;
530         struct cifsFileInfo *pCFileStruct =
531             (struct cifsFileInfo *)file->private_data;
532         char *ptmp;
533
534         cFYI(1, ("Closedir inode = 0x%p with ", inode));
535
536         xid = GetXid();
537
538         if (pCFileStruct) {
539                 struct cifsTconInfo *pTcon;
540                 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_dentry->d_sb);
541
542                 pTcon = cifs_sb->tcon;
543
544                 cFYI(1, ("Freeing private data in close dir"));
545                 if ((pCFileStruct->srch_inf.endOfSearch == FALSE) &&
546                    (pCFileStruct->invalidHandle == FALSE)) {
547                         pCFileStruct->invalidHandle = TRUE;
548                         rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
549                         cFYI(1, ("Closing uncompleted readdir with rc %d",
550                                  rc));
551                         /* not much we can do if it fails anyway, ignore rc */
552                         rc = 0;
553                 }
554                 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
555                 if (ptmp) {
556                         cFYI(1, ("closedir free smb buf in srch struct"));
557                         pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
558                         if(pCFileStruct->srch_inf.smallBuf)
559                                 cifs_small_buf_release(ptmp);
560                         else
561                                 cifs_buf_release(ptmp);
562                 }
563                 ptmp = pCFileStruct->search_resume_name;
564                 if (ptmp) {
565                         cFYI(1, ("closedir free resume name"));
566                         pCFileStruct->search_resume_name = NULL;
567                         kfree(ptmp);
568                 }
569                 kfree(file->private_data);
570                 file->private_data = NULL;
571         }
572         /* BB can we lock the filestruct while this is going on? */
573         FreeXid(xid);
574         return rc;
575 }
576
577 int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
578 {
579         int rc, xid;
580         __u32 lockType = LOCKING_ANDX_LARGE_FILES;
581         __u32 numLock = 0;
582         __u32 numUnlock = 0;
583         __u64 length;
584         int wait_flag = FALSE;
585         struct cifs_sb_info *cifs_sb;
586         struct cifsTconInfo *pTcon;
587
588         length = 1 + pfLock->fl_end - pfLock->fl_start;
589         rc = -EACCES;
590         xid = GetXid();
591
592         cFYI(1, ("Lock parm: 0x%x flockflags: "
593                  "0x%x flocktype: 0x%x start: %lld end: %lld",
594                 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
595                 pfLock->fl_end));
596
597         if (pfLock->fl_flags & FL_POSIX)
598                 cFYI(1, ("Posix"));
599         if (pfLock->fl_flags & FL_FLOCK)
600                 cFYI(1, ("Flock"));
601         if (pfLock->fl_flags & FL_SLEEP) {
602                 cFYI(1, ("Blocking lock"));
603                 wait_flag = TRUE;
604         }
605         if (pfLock->fl_flags & FL_ACCESS)
606                 cFYI(1, ("Process suspended by mandatory locking - "
607                          "not implemented yet "));
608         if (pfLock->fl_flags & FL_LEASE)
609                 cFYI(1, ("Lease on file - not implemented yet"));
610         if (pfLock->fl_flags & 
611             (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
612                 cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags));
613
614         if (pfLock->fl_type == F_WRLCK) {
615                 cFYI(1, ("F_WRLCK "));
616                 numLock = 1;
617         } else if (pfLock->fl_type == F_UNLCK) {
618                 cFYI(1, ("F_UNLCK"));
619                 numUnlock = 1;
620                 /* Check if unlock includes more than
621                 one lock range */
622         } else if (pfLock->fl_type == F_RDLCK) {
623                 cFYI(1, ("F_RDLCK"));
624                 lockType |= LOCKING_ANDX_SHARED_LOCK;
625                 numLock = 1;
626         } else if (pfLock->fl_type == F_EXLCK) {
627                 cFYI(1, ("F_EXLCK"));
628                 numLock = 1;
629         } else if (pfLock->fl_type == F_SHLCK) {
630                 cFYI(1, ("F_SHLCK"));
631                 lockType |= LOCKING_ANDX_SHARED_LOCK;
632                 numLock = 1;
633         } else
634                 cFYI(1, ("Unknown type of lock"));
635
636         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
637         pTcon = cifs_sb->tcon;
638
639         if (file->private_data == NULL) {
640                 FreeXid(xid);
641                 return -EBADF;
642         }
643
644         if (IS_GETLK(cmd)) {
645                 rc = CIFSSMBLock(xid, pTcon,
646                                  ((struct cifsFileInfo *)file->
647                                   private_data)->netfid,
648                                  length,
649                                  pfLock->fl_start, 0, 1, lockType,
650                                  0 /* wait flag */ );
651                 if (rc == 0) {
652                         rc = CIFSSMBLock(xid, pTcon,
653                                          ((struct cifsFileInfo *) file->
654                                           private_data)->netfid,
655                                          length,
656                                          pfLock->fl_start, 1 /* numUnlock */ ,
657                                          0 /* numLock */ , lockType,
658                                          0 /* wait flag */ );
659                         pfLock->fl_type = F_UNLCK;
660                         if (rc != 0)
661                                 cERROR(1, ("Error unlocking previously locked "
662                                            "range %d during test of lock ",
663                                            rc));
664                         rc = 0;
665
666                 } else {
667                         /* if rc == ERR_SHARING_VIOLATION ? */
668                         rc = 0; /* do not change lock type to unlock
669                                    since range in use */
670                 }
671
672                 FreeXid(xid);
673                 return rc;
674         }
675
676         rc = CIFSSMBLock(xid, pTcon,
677                          ((struct cifsFileInfo *) file->private_data)->
678                          netfid, length,
679                          pfLock->fl_start, numUnlock, numLock, lockType,
680                          wait_flag);
681         if (pfLock->fl_flags & FL_POSIX)
682                 posix_lock_file_wait(file, pfLock);
683         FreeXid(xid);
684         return rc;
685 }
686
687 ssize_t cifs_user_write(struct file *file, const char __user *write_data,
688         size_t write_size, loff_t *poffset)
689 {
690         int rc = 0;
691         unsigned int bytes_written = 0;
692         unsigned int total_written;
693         struct cifs_sb_info *cifs_sb;
694         struct cifsTconInfo *pTcon;
695         int xid, long_op;
696         struct cifsFileInfo *open_file;
697
698         if (file->f_dentry == NULL)
699                 return -EBADF;
700
701         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
702         if (cifs_sb == NULL)
703                 return -EBADF;
704
705         pTcon = cifs_sb->tcon;
706
707         /* cFYI(1,
708            (" write %d bytes to offset %lld of %s", write_size,
709            *poffset, file->f_dentry->d_name.name)); */
710
711         if (file->private_data == NULL)
712                 return -EBADF;
713         else
714                 open_file = (struct cifsFileInfo *) file->private_data;
715         
716         xid = GetXid();
717         if (file->f_dentry->d_inode == NULL) {
718                 FreeXid(xid);
719                 return -EBADF;
720         }
721
722         if (*poffset > file->f_dentry->d_inode->i_size)
723                 long_op = 2; /* writes past end of file can take a long time */
724         else
725                 long_op = 1;
726
727         for (total_written = 0; write_size > total_written;
728              total_written += bytes_written) {
729                 rc = -EAGAIN;
730                 while (rc == -EAGAIN) {
731                         if (file->private_data == NULL) {
732                                 /* file has been closed on us */
733                                 FreeXid(xid);
734                         /* if we have gotten here we have written some data
735                            and blocked, and the file has been freed on us while
736                            we blocked so return what we managed to write */
737                                 return total_written;
738                         } 
739                         if (open_file->closePend) {
740                                 FreeXid(xid);
741                                 if (total_written)
742                                         return total_written;
743                                 else
744                                         return -EBADF;
745                         }
746                         if (open_file->invalidHandle) {
747                                 if ((file->f_dentry == NULL) ||
748                                     (file->f_dentry->d_inode == NULL)) {
749                                         FreeXid(xid);
750                                         return total_written;
751                                 }
752                                 /* we could deadlock if we called
753                                    filemap_fdatawait from here so tell
754                                    reopen_file not to flush data to server
755                                    now */
756                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
757                                         file, FALSE);
758                                 if (rc != 0)
759                                         break;
760                         }
761
762                         rc = CIFSSMBWrite(xid, pTcon,
763                                 open_file->netfid,
764                                 min_t(const int, cifs_sb->wsize,
765                                       write_size - total_written),
766                                 *poffset, &bytes_written,
767                                 NULL, write_data + total_written, long_op);
768                 }
769                 if (rc || (bytes_written == 0)) {
770                         if (total_written)
771                                 break;
772                         else {
773                                 FreeXid(xid);
774                                 return rc;
775                         }
776                 } else
777                         *poffset += bytes_written;
778                 long_op = FALSE; /* subsequent writes fast -
779                                     15 seconds is plenty */
780         }
781
782         cifs_stats_bytes_written(pTcon, total_written);
783
784         /* since the write may have blocked check these pointers again */
785         if (file->f_dentry) {
786                 if (file->f_dentry->d_inode) {
787                         struct inode *inode = file->f_dentry->d_inode;
788                         inode->i_ctime = inode->i_mtime =
789                                 current_fs_time(inode->i_sb);
790                         if (total_written > 0) {
791                                 if (*poffset > file->f_dentry->d_inode->i_size)
792                                         i_size_write(file->f_dentry->d_inode,
793                                         *poffset);
794                         }
795                         mark_inode_dirty_sync(file->f_dentry->d_inode);
796                 }
797         }
798         FreeXid(xid);
799         return total_written;
800 }
801
802 static ssize_t cifs_write(struct file *file, const char *write_data,
803         size_t write_size, loff_t *poffset)
804 {
805         int rc = 0;
806         unsigned int bytes_written = 0;
807         unsigned int total_written;
808         struct cifs_sb_info *cifs_sb;
809         struct cifsTconInfo *pTcon;
810         int xid, long_op;
811         struct cifsFileInfo *open_file;
812
813         if (file->f_dentry == NULL)
814                 return -EBADF;
815
816         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
817         if (cifs_sb == NULL)
818                 return -EBADF;
819
820         pTcon = cifs_sb->tcon;
821
822         cFYI(1,("write %zd bytes to offset %lld of %s", write_size,
823            *poffset, file->f_dentry->d_name.name));
824
825         if (file->private_data == NULL)
826                 return -EBADF;
827         else
828                 open_file = (struct cifsFileInfo *)file->private_data;
829         
830         xid = GetXid();
831         if (file->f_dentry->d_inode == NULL) {
832                 FreeXid(xid);
833                 return -EBADF;
834         }
835
836         if (*poffset > file->f_dentry->d_inode->i_size)
837                 long_op = 2; /* writes past end of file can take a long time */
838         else
839                 long_op = 1;
840
841         for (total_written = 0; write_size > total_written;
842              total_written += bytes_written) {
843                 rc = -EAGAIN;
844                 while (rc == -EAGAIN) {
845                         if (file->private_data == NULL) {
846                                 /* file has been closed on us */
847                                 FreeXid(xid);
848                         /* if we have gotten here we have written some data
849                            and blocked, and the file has been freed on us
850                            while we blocked so return what we managed to 
851                            write */
852                                 return total_written;
853                         } 
854                         if (open_file->closePend) {
855                                 FreeXid(xid);
856                                 if (total_written)
857                                         return total_written;
858                                 else
859                                         return -EBADF;
860                         }
861                         if (open_file->invalidHandle) {
862                                 if ((file->f_dentry == NULL) ||
863                                    (file->f_dentry->d_inode == NULL)) {
864                                         FreeXid(xid);
865                                         return total_written;
866                                 }
867                                 /* we could deadlock if we called
868                                    filemap_fdatawait from here so tell
869                                    reopen_file not to flush data to 
870                                    server now */
871                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
872                                         file, FALSE);
873                                 if (rc != 0)
874                                         break;
875                         }
876                         /* BB FIXME We can not sign across two buffers yet */
877                         if((pTcon->ses->server->secMode & 
878                          (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
879                                 struct kvec iov[2];
880                                 unsigned int len;
881
882                                 len = min((size_t)cifs_sb->wsize,
883                                           write_size - total_written);
884                                 /* iov[0] is reserved for smb header */
885                                 iov[1].iov_base = (char *)write_data +
886                                                   total_written;
887                                 iov[1].iov_len = len;
888                                 rc = CIFSSMBWrite2(xid, pTcon,
889                                                 open_file->netfid, len,
890                                                 *poffset, &bytes_written,
891                                                 iov, 1, long_op);
892                         } else
893                         /* BB FIXME fixup indentation of line below */
894                         rc = CIFSSMBWrite(xid, pTcon,
895                                  open_file->netfid,
896                                  min_t(const int, cifs_sb->wsize, 
897                                        write_size - total_written),
898                                  *poffset, &bytes_written,
899                                  write_data + total_written, NULL, long_op);
900                 }
901                 if (rc || (bytes_written == 0)) {
902                         if (total_written)
903                                 break;
904                         else {
905                                 FreeXid(xid);
906                                 return rc;
907                         }
908                 } else
909                         *poffset += bytes_written;
910                 long_op = FALSE; /* subsequent writes fast - 
911                                     15 seconds is plenty */
912         }
913
914         cifs_stats_bytes_written(pTcon, total_written);
915
916         /* since the write may have blocked check these pointers again */
917         if (file->f_dentry) {
918                 if (file->f_dentry->d_inode) {
919                         file->f_dentry->d_inode->i_ctime = 
920                         file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
921                         if (total_written > 0) {
922                                 if (*poffset > file->f_dentry->d_inode->i_size)
923                                         i_size_write(file->f_dentry->d_inode, 
924                                                      *poffset);
925                         }
926                         mark_inode_dirty_sync(file->f_dentry->d_inode);
927                 }
928         }
929         FreeXid(xid);
930         return total_written;
931 }
932
933 struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
934 {
935         struct cifsFileInfo *open_file;
936         int rc;
937
938         read_lock(&GlobalSMBSeslock);
939         list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
940                 if (open_file->closePend)
941                         continue;
942                 if (open_file->pfile &&
943                     ((open_file->pfile->f_flags & O_RDWR) ||
944                      (open_file->pfile->f_flags & O_WRONLY))) {
945                         atomic_inc(&open_file->wrtPending);
946                         read_unlock(&GlobalSMBSeslock);
947                         if((open_file->invalidHandle) && 
948                            (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
949                                 rc = cifs_reopen_file(&cifs_inode->vfs_inode, 
950                                                       open_file->pfile, FALSE);
951                                 /* if it fails, try another handle - might be */
952                                 /* dangerous to hold up writepages with retry */
953                                 if(rc) {
954                                         cFYI(1,("failed on reopen file in wp"));
955                                         read_lock(&GlobalSMBSeslock);
956                                         /* can not use this handle, no write
957                                         pending on this one after all */
958                                         atomic_dec
959                                              (&open_file->wrtPending);
960                                         continue;
961                                 }
962                         }
963                         return open_file;
964                 }
965         }
966         read_unlock(&GlobalSMBSeslock);
967         return NULL;
968 }
969
970 static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
971 {
972         struct address_space *mapping = page->mapping;
973         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
974         char *write_data;
975         int rc = -EFAULT;
976         int bytes_written = 0;
977         struct cifs_sb_info *cifs_sb;
978         struct cifsTconInfo *pTcon;
979         struct inode *inode;
980         struct cifsFileInfo *open_file;
981
982         if (!mapping || !mapping->host)
983                 return -EFAULT;
984
985         inode = page->mapping->host;
986         cifs_sb = CIFS_SB(inode->i_sb);
987         pTcon = cifs_sb->tcon;
988
989         offset += (loff_t)from;
990         write_data = kmap(page);
991         write_data += from;
992
993         if ((to > PAGE_CACHE_SIZE) || (from > to)) {
994                 kunmap(page);
995                 return -EIO;
996         }
997
998         /* racing with truncate? */
999         if (offset > mapping->host->i_size) {
1000                 kunmap(page);
1001                 return 0; /* don't care */
1002         }
1003
1004         /* check to make sure that we are not extending the file */
1005         if (mapping->host->i_size - offset < (loff_t)to)
1006                 to = (unsigned)(mapping->host->i_size - offset); 
1007
1008         open_file = find_writable_file(CIFS_I(mapping->host));
1009         if (open_file) {
1010                 bytes_written = cifs_write(open_file->pfile, write_data,
1011                                            to-from, &offset);
1012                 atomic_dec(&open_file->wrtPending);
1013                 /* Does mm or vfs already set times? */
1014                 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
1015                 if ((bytes_written > 0) && (offset)) {
1016                         rc = 0;
1017                 } else if (bytes_written < 0) {
1018                         if (rc != -EBADF)
1019                                 rc = bytes_written;
1020                 }
1021         } else {
1022                 cFYI(1, ("No writeable filehandles for inode"));
1023                 rc = -EIO;
1024         }
1025
1026         kunmap(page);
1027         return rc;
1028 }
1029
1030 static int cifs_writepages(struct address_space *mapping,
1031                            struct writeback_control *wbc)
1032 {
1033         struct backing_dev_info *bdi = mapping->backing_dev_info;
1034         unsigned int bytes_to_write;
1035         unsigned int bytes_written;
1036         struct cifs_sb_info *cifs_sb;
1037         int done = 0;
1038         pgoff_t end = -1;
1039         pgoff_t index;
1040         int is_range = 0;
1041         struct kvec iov[32];
1042         int len;
1043         int n_iov = 0;
1044         pgoff_t next;
1045         int nr_pages;
1046         __u64 offset = 0;
1047         struct cifsFileInfo *open_file;
1048         struct page *page;
1049         struct pagevec pvec;
1050         int rc = 0;
1051         int scanned = 0;
1052         int xid;
1053
1054         cifs_sb = CIFS_SB(mapping->host->i_sb);
1055         
1056         /*
1057          * If wsize is smaller that the page cache size, default to writing
1058          * one page at a time via cifs_writepage
1059          */
1060         if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1061                 return generic_writepages(mapping, wbc);
1062
1063         /* BB FIXME we do not have code to sign across multiple buffers yet,
1064            so go to older writepage style write which we can sign if needed */
1065         if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
1066                 if(cifs_sb->tcon->ses->server->secMode &
1067                           (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1068                         return generic_writepages(mapping, wbc);
1069
1070         /*
1071          * BB: Is this meaningful for a non-block-device file system?
1072          * If it is, we should test it again after we do I/O
1073          */
1074         if (wbc->nonblocking && bdi_write_congested(bdi)) {
1075                 wbc->encountered_congestion = 1;
1076                 return 0;
1077         }
1078
1079         xid = GetXid();
1080
1081         pagevec_init(&pvec, 0);
1082         if (wbc->sync_mode == WB_SYNC_NONE)
1083                 index = mapping->writeback_index; /* Start from prev offset */
1084         else {
1085                 index = 0;
1086                 scanned = 1;
1087         }
1088         if (wbc->start || wbc->end) {
1089                 index = wbc->start >> PAGE_CACHE_SHIFT;
1090                 end = wbc->end >> PAGE_CACHE_SHIFT;
1091                 is_range = 1;
1092                 scanned = 1;
1093         }
1094 retry:
1095         while (!done && (index <= end) &&
1096                (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
1097                         PAGECACHE_TAG_DIRTY,
1098                         min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1))) {
1099                 int first;
1100                 unsigned int i;
1101
1102                 first = -1;
1103                 next = 0;
1104                 n_iov = 0;
1105                 bytes_to_write = 0;
1106
1107                 for (i = 0; i < nr_pages; i++) {
1108                         page = pvec.pages[i];
1109                         /*
1110                          * At this point we hold neither mapping->tree_lock nor
1111                          * lock on the page itself: the page may be truncated or
1112                          * invalidated (changing page->mapping to NULL), or even
1113                          * swizzled back from swapper_space to tmpfs file
1114                          * mapping
1115                          */
1116
1117                         if (first < 0)
1118                                 lock_page(page);
1119                         else if (TestSetPageLocked(page))
1120                                 break;
1121
1122                         if (unlikely(page->mapping != mapping)) {
1123                                 unlock_page(page);
1124                                 break;
1125                         }
1126
1127                         if (unlikely(is_range) && (page->index > end)) {
1128                                 done = 1;
1129                                 unlock_page(page);
1130                                 break;
1131                         }
1132
1133                         if (next && (page->index != next)) {
1134                                 /* Not next consecutive page */
1135                                 unlock_page(page);
1136                                 break;
1137                         }
1138
1139                         if (wbc->sync_mode != WB_SYNC_NONE)
1140                                 wait_on_page_writeback(page);
1141
1142                         if (PageWriteback(page) ||
1143                                         !test_clear_page_dirty(page)) {
1144                                 unlock_page(page);
1145                                 break;
1146                         }
1147
1148                         if (page_offset(page) >= mapping->host->i_size) {
1149                                 done = 1;
1150                                 unlock_page(page);
1151                                 break;
1152                         }
1153
1154                         /*
1155                          * BB can we get rid of this?  pages are held by pvec
1156                          */
1157                         page_cache_get(page);
1158
1159                         len = min(mapping->host->i_size - page_offset(page),
1160                                   (loff_t)PAGE_CACHE_SIZE);
1161
1162                         /* reserve iov[0] for the smb header */
1163                         n_iov++;
1164                         iov[n_iov].iov_base = kmap(page);
1165                         iov[n_iov].iov_len = len;
1166                         bytes_to_write += len;
1167
1168                         if (first < 0) {
1169                                 first = i;
1170                                 offset = page_offset(page);
1171                         }
1172                         next = page->index + 1;
1173                         if (bytes_to_write + PAGE_CACHE_SIZE > cifs_sb->wsize)
1174                                 break;
1175                 }
1176                 if (n_iov) {
1177                         /* Search for a writable handle every time we call
1178                          * CIFSSMBWrite2.  We can't rely on the last handle
1179                          * we used to still be valid
1180                          */
1181                         open_file = find_writable_file(CIFS_I(mapping->host));
1182                         if (!open_file) {
1183                                 cERROR(1, ("No writable handles for inode"));
1184                                 rc = -EBADF;
1185                         } else {
1186                                 rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
1187                                                    open_file->netfid,
1188                                                    bytes_to_write, offset,
1189                                                    &bytes_written, iov, n_iov,
1190                                                    1);
1191                                 atomic_dec(&open_file->wrtPending);
1192                                 if (rc || bytes_written < bytes_to_write) {
1193                                         cERROR(1,("Write2 ret %d, written = %d",
1194                                                   rc, bytes_written));
1195                                         /* BB what if continued retry is
1196                                            requested via mount flags? */
1197                                         set_bit(AS_EIO, &mapping->flags);
1198                                 } else {
1199                                         cifs_stats_bytes_written(cifs_sb->tcon,
1200                                                                  bytes_written);
1201                                 }
1202                         }
1203                         for (i = 0; i < n_iov; i++) {
1204                                 page = pvec.pages[first + i];
1205                                 /* Should we also set page error on
1206                                 success rc but too little data written? */
1207                                 /* BB investigate retry logic on temporary
1208                                 server crash cases and how recovery works
1209                                 when page marked as error */ 
1210                                 if(rc)
1211                                         SetPageError(page);
1212                                 kunmap(page);
1213                                 unlock_page(page);
1214                                 page_cache_release(page);
1215                         }
1216                         if ((wbc->nr_to_write -= n_iov) <= 0)
1217                                 done = 1;
1218                         index = next;
1219                 }
1220                 pagevec_release(&pvec);
1221         }
1222         if (!scanned && !done) {
1223                 /*
1224                  * We hit the last page and there is more work to be done: wrap
1225                  * back to the start of the file
1226                  */
1227                 scanned = 1;
1228                 index = 0;
1229                 goto retry;
1230         }
1231         if (!is_range)
1232                 mapping->writeback_index = index;
1233
1234         FreeXid(xid);
1235
1236         return rc;
1237 }
1238
1239 static int cifs_writepage(struct page* page, struct writeback_control *wbc)
1240 {
1241         int rc = -EFAULT;
1242         int xid;
1243
1244         xid = GetXid();
1245 /* BB add check for wbc flags */
1246         page_cache_get(page);
1247         if (!PageUptodate(page)) {
1248                 cFYI(1, ("ppw - page not up to date"));
1249         }
1250         
1251         rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
1252         SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
1253         unlock_page(page);
1254         page_cache_release(page);       
1255         FreeXid(xid);
1256         return rc;
1257 }
1258
1259 static int cifs_commit_write(struct file *file, struct page *page,
1260         unsigned offset, unsigned to)
1261 {
1262         int xid;
1263         int rc = 0;
1264         struct inode *inode = page->mapping->host;
1265         loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
1266         char *page_data;
1267
1268         xid = GetXid();
1269         cFYI(1, ("commit write for page %p up to position %lld for %d", 
1270                  page, position, to));
1271         if (position > inode->i_size) {
1272                 i_size_write(inode, position);
1273                 /* if (file->private_data == NULL) {
1274                         rc = -EBADF;
1275                 } else {
1276                         open_file = (struct cifsFileInfo *)file->private_data;
1277                         cifs_sb = CIFS_SB(inode->i_sb);
1278                         rc = -EAGAIN;
1279                         while (rc == -EAGAIN) {
1280                                 if ((open_file->invalidHandle) && 
1281                                     (!open_file->closePend)) {
1282                                         rc = cifs_reopen_file(
1283                                                 file->f_dentry->d_inode, file);
1284                                         if (rc != 0)
1285                                                 break;
1286                                 }
1287                                 if (!open_file->closePend) {
1288                                         rc = CIFSSMBSetFileSize(xid,
1289                                                 cifs_sb->tcon, position,
1290                                                 open_file->netfid,
1291                                                 open_file->pid, FALSE);
1292                                 } else {
1293                                         rc = -EBADF;
1294                                         break;
1295                                 }
1296                         }
1297                         cFYI(1, (" SetEOF (commit write) rc = %d", rc));
1298                 } */
1299         }
1300         if (!PageUptodate(page)) {
1301                 position =  ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
1302                 /* can not rely on (or let) writepage write this data */
1303                 if (to < offset) {
1304                         cFYI(1, ("Illegal offsets, can not copy from %d to %d",
1305                                 offset, to));
1306                         FreeXid(xid);
1307                         return rc;
1308                 }
1309                 /* this is probably better than directly calling
1310                    partialpage_write since in this function the file handle is
1311                    known which we might as well leverage */
1312                 /* BB check if anything else missing out of ppw
1313                    such as updating last write time */
1314                 page_data = kmap(page);
1315                 rc = cifs_write(file, page_data + offset, to-offset,
1316                                 &position);
1317                 if (rc > 0)
1318                         rc = 0;
1319                 /* else if (rc < 0) should we set writebehind rc? */
1320                 kunmap(page);
1321         } else {        
1322                 set_page_dirty(page);
1323         }
1324
1325         FreeXid(xid);
1326         return rc;
1327 }
1328
1329 int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1330 {
1331         int xid;
1332         int rc = 0;
1333         struct inode *inode = file->f_dentry->d_inode;
1334
1335         xid = GetXid();
1336
1337         cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 
1338                 dentry->d_name.name, datasync));
1339         
1340         rc = filemap_fdatawrite(inode->i_mapping);
1341         if (rc == 0)
1342                 CIFS_I(inode)->write_behind_rc = 0;
1343         FreeXid(xid);
1344         return rc;
1345 }
1346
1347 /* static int cifs_sync_page(struct page *page)
1348 {
1349         struct address_space *mapping;
1350         struct inode *inode;
1351         unsigned long index = page->index;
1352         unsigned int rpages = 0;
1353         int rc = 0;
1354
1355         cFYI(1, ("sync page %p",page));
1356         mapping = page->mapping;
1357         if (!mapping)
1358                 return 0;
1359         inode = mapping->host;
1360         if (!inode)
1361                 return 0; */
1362
1363 /*      fill in rpages then 
1364         result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
1365
1366 /*      cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
1367
1368         if (rc < 0)
1369                 return rc;
1370         return 0;
1371 } */
1372
1373 /*
1374  * As file closes, flush all cached write data for this inode checking
1375  * for write behind errors.
1376  */
1377 int cifs_flush(struct file *file)
1378 {
1379         struct inode * inode = file->f_dentry->d_inode;
1380         int rc = 0;
1381
1382         /* Rather than do the steps manually:
1383            lock the inode for writing
1384            loop through pages looking for write behind data (dirty pages)
1385            coalesce into contiguous 16K (or smaller) chunks to write to server
1386            send to server (prefer in parallel)
1387            deal with writebehind errors
1388            unlock inode for writing
1389            filemapfdatawrite appears easier for the time being */
1390
1391         rc = filemap_fdatawrite(inode->i_mapping);
1392         if (!rc) /* reset wb rc if we were able to write out dirty pages */
1393                 CIFS_I(inode)->write_behind_rc = 0;
1394                 
1395         cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc));
1396
1397         return rc;
1398 }
1399
1400 ssize_t cifs_user_read(struct file *file, char __user *read_data,
1401         size_t read_size, loff_t *poffset)
1402 {
1403         int rc = -EACCES;
1404         unsigned int bytes_read = 0;
1405         unsigned int total_read = 0;
1406         unsigned int current_read_size;
1407         struct cifs_sb_info *cifs_sb;
1408         struct cifsTconInfo *pTcon;
1409         int xid;
1410         struct cifsFileInfo *open_file;
1411         char *smb_read_data;
1412         char __user *current_offset;
1413         struct smb_com_read_rsp *pSMBr;
1414
1415         xid = GetXid();
1416         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1417         pTcon = cifs_sb->tcon;
1418
1419         if (file->private_data == NULL) {
1420                 FreeXid(xid);
1421                 return -EBADF;
1422         }
1423         open_file = (struct cifsFileInfo *)file->private_data;
1424
1425         if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
1426                 cFYI(1, ("attempting read on write only file instance"));
1427         }
1428         for (total_read = 0, current_offset = read_data;
1429              read_size > total_read;
1430              total_read += bytes_read, current_offset += bytes_read) {
1431                 current_read_size = min_t(const int, read_size - total_read, 
1432                                           cifs_sb->rsize);
1433                 rc = -EAGAIN;
1434                 smb_read_data = NULL;
1435                 while (rc == -EAGAIN) {
1436                         int buf_type = CIFS_NO_BUFFER;
1437                         if ((open_file->invalidHandle) && 
1438                             (!open_file->closePend)) {
1439                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1440                                         file, TRUE);
1441                                 if (rc != 0)
1442                                         break;
1443                         }
1444                         rc = CIFSSMBRead(xid, pTcon,
1445                                          open_file->netfid,
1446                                          current_read_size, *poffset,
1447                                          &bytes_read, &smb_read_data,
1448                                          &buf_type);
1449                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1450                         if (smb_read_data) {
1451                                 if (copy_to_user(current_offset,
1452                                                 smb_read_data +
1453                                                 4 /* RFC1001 length field */ +
1454                                                 le16_to_cpu(pSMBr->DataOffset),
1455                                                 bytes_read)) {
1456                                         rc = -EFAULT;
1457                                 }
1458
1459                                 if(buf_type == CIFS_SMALL_BUFFER)
1460                                         cifs_small_buf_release(smb_read_data);
1461                                 else if(buf_type == CIFS_LARGE_BUFFER)
1462                                         cifs_buf_release(smb_read_data);
1463                                 smb_read_data = NULL;
1464                         }
1465                 }
1466                 if (rc || (bytes_read == 0)) {
1467                         if (total_read) {
1468                                 break;
1469                         } else {
1470                                 FreeXid(xid);
1471                                 return rc;
1472                         }
1473                 } else {
1474                         cifs_stats_bytes_read(pTcon, bytes_read);
1475                         *poffset += bytes_read;
1476                 }
1477         }
1478         FreeXid(xid);
1479         return total_read;
1480 }
1481
1482
1483 static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1484         loff_t *poffset)
1485 {
1486         int rc = -EACCES;
1487         unsigned int bytes_read = 0;
1488         unsigned int total_read;
1489         unsigned int current_read_size;
1490         struct cifs_sb_info *cifs_sb;
1491         struct cifsTconInfo *pTcon;
1492         int xid;
1493         char *current_offset;
1494         struct cifsFileInfo *open_file;
1495         int buf_type = CIFS_NO_BUFFER;
1496
1497         xid = GetXid();
1498         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1499         pTcon = cifs_sb->tcon;
1500
1501         if (file->private_data == NULL) {
1502                 FreeXid(xid);
1503                 return -EBADF;
1504         }
1505         open_file = (struct cifsFileInfo *)file->private_data;
1506
1507         if ((file->f_flags & O_ACCMODE) == O_WRONLY)
1508                 cFYI(1, ("attempting read on write only file instance"));
1509
1510         for (total_read = 0, current_offset = read_data; 
1511              read_size > total_read;
1512              total_read += bytes_read, current_offset += bytes_read) {
1513                 current_read_size = min_t(const int, read_size - total_read,
1514                                           cifs_sb->rsize);
1515                 /* For windows me and 9x we do not want to request more
1516                 than it negotiated since it will refuse the read then */
1517                 if((pTcon->ses) && 
1518                         !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
1519                         current_read_size = min_t(const int, current_read_size,
1520                                         pTcon->ses->server->maxBuf - 128);
1521                 }
1522                 rc = -EAGAIN;
1523                 while (rc == -EAGAIN) {
1524                         if ((open_file->invalidHandle) && 
1525                             (!open_file->closePend)) {
1526                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1527                                         file, TRUE);
1528                                 if (rc != 0)
1529                                         break;
1530                         }
1531                         rc = CIFSSMBRead(xid, pTcon,
1532                                          open_file->netfid,
1533                                          current_read_size, *poffset,
1534                                          &bytes_read, &current_offset,
1535                                          &buf_type);
1536                 }
1537                 if (rc || (bytes_read == 0)) {
1538                         if (total_read) {
1539                                 break;
1540                         } else {
1541                                 FreeXid(xid);
1542                                 return rc;
1543                         }
1544                 } else {
1545                         cifs_stats_bytes_read(pTcon, total_read);
1546                         *poffset += bytes_read;
1547                 }
1548         }
1549         FreeXid(xid);
1550         return total_read;
1551 }
1552
1553 int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1554 {
1555         struct dentry *dentry = file->f_dentry;
1556         int rc, xid;
1557
1558         xid = GetXid();
1559         rc = cifs_revalidate(dentry);
1560         if (rc) {
1561                 cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
1562                 FreeXid(xid);
1563                 return rc;
1564         }
1565         rc = generic_file_mmap(file, vma);
1566         FreeXid(xid);
1567         return rc;
1568 }
1569
1570
1571 static void cifs_copy_cache_pages(struct address_space *mapping, 
1572         struct list_head *pages, int bytes_read, char *data,
1573         struct pagevec *plru_pvec)
1574 {
1575         struct page *page;
1576         char *target;
1577
1578         while (bytes_read > 0) {
1579                 if (list_empty(pages))
1580                         break;
1581
1582                 page = list_entry(pages->prev, struct page, lru);
1583                 list_del(&page->lru);
1584
1585                 if (add_to_page_cache(page, mapping, page->index,
1586                                       GFP_KERNEL)) {
1587                         page_cache_release(page);
1588                         cFYI(1, ("Add page cache failed"));
1589                         data += PAGE_CACHE_SIZE;
1590                         bytes_read -= PAGE_CACHE_SIZE;
1591                         continue;
1592                 }
1593
1594                 target = kmap_atomic(page,KM_USER0);
1595
1596                 if (PAGE_CACHE_SIZE > bytes_read) {
1597                         memcpy(target, data, bytes_read);
1598                         /* zero the tail end of this partial page */
1599                         memset(target + bytes_read, 0, 
1600                                PAGE_CACHE_SIZE - bytes_read);
1601                         bytes_read = 0;
1602                 } else {
1603                         memcpy(target, data, PAGE_CACHE_SIZE);
1604                         bytes_read -= PAGE_CACHE_SIZE;
1605                 }
1606                 kunmap_atomic(target, KM_USER0);
1607
1608                 flush_dcache_page(page);
1609                 SetPageUptodate(page);
1610                 unlock_page(page);
1611                 if (!pagevec_add(plru_pvec, page))
1612                         __pagevec_lru_add(plru_pvec);
1613                 data += PAGE_CACHE_SIZE;
1614         }
1615         return;
1616 }
1617
1618 static int cifs_readpages(struct file *file, struct address_space *mapping,
1619         struct list_head *page_list, unsigned num_pages)
1620 {
1621         int rc = -EACCES;
1622         int xid;
1623         loff_t offset;
1624         struct page *page;
1625         struct cifs_sb_info *cifs_sb;
1626         struct cifsTconInfo *pTcon;
1627         int bytes_read = 0;
1628         unsigned int read_size,i;
1629         char *smb_read_data = NULL;
1630         struct smb_com_read_rsp *pSMBr;
1631         struct pagevec lru_pvec;
1632         struct cifsFileInfo *open_file;
1633         int buf_type = CIFS_NO_BUFFER;
1634
1635         xid = GetXid();
1636         if (file->private_data == NULL) {
1637                 FreeXid(xid);
1638                 return -EBADF;
1639         }
1640         open_file = (struct cifsFileInfo *)file->private_data;
1641         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1642         pTcon = cifs_sb->tcon;
1643
1644         pagevec_init(&lru_pvec, 0);
1645
1646         for (i = 0; i < num_pages; ) {
1647                 unsigned contig_pages;
1648                 struct page *tmp_page;
1649                 unsigned long expected_index;
1650
1651                 if (list_empty(page_list))
1652                         break;
1653
1654                 page = list_entry(page_list->prev, struct page, lru);
1655                 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1656
1657                 /* count adjacent pages that we will read into */
1658                 contig_pages = 0;
1659                 expected_index = 
1660                         list_entry(page_list->prev, struct page, lru)->index;
1661                 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1662                         if (tmp_page->index == expected_index) {
1663                                 contig_pages++;
1664                                 expected_index++;
1665                         } else
1666                                 break; 
1667                 }
1668                 if (contig_pages + i >  num_pages)
1669                         contig_pages = num_pages - i;
1670
1671                 /* for reads over a certain size could initiate async
1672                    read ahead */
1673
1674                 read_size = contig_pages * PAGE_CACHE_SIZE;
1675                 /* Read size needs to be in multiples of one page */
1676                 read_size = min_t(const unsigned int, read_size,
1677                                   cifs_sb->rsize & PAGE_CACHE_MASK);
1678
1679                 rc = -EAGAIN;
1680                 while (rc == -EAGAIN) {
1681                         if ((open_file->invalidHandle) && 
1682                             (!open_file->closePend)) {
1683                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1684                                         file, TRUE);
1685                                 if (rc != 0)
1686                                         break;
1687                         }
1688
1689                         rc = CIFSSMBRead(xid, pTcon,
1690                                          open_file->netfid,
1691                                          read_size, offset,
1692                                          &bytes_read, &smb_read_data,
1693                                          &buf_type);
1694                         /* BB more RC checks ? */
1695                         if (rc== -EAGAIN) {
1696                                 if (smb_read_data) {
1697                                         if(buf_type == CIFS_SMALL_BUFFER)
1698                                                 cifs_small_buf_release(smb_read_data);
1699                                         else if(buf_type == CIFS_LARGE_BUFFER)
1700                                                 cifs_buf_release(smb_read_data);
1701                                         smb_read_data = NULL;
1702                                 }
1703                         }
1704                 }
1705                 if ((rc < 0) || (smb_read_data == NULL)) {
1706                         cFYI(1, ("Read error in readpages: %d", rc));
1707                         /* clean up remaing pages off list */
1708                         while (!list_empty(page_list) && (i < num_pages)) {
1709                                 page = list_entry(page_list->prev, struct page,
1710                                                   lru);
1711                                 list_del(&page->lru);
1712                                 page_cache_release(page);
1713                         }
1714                         break;
1715                 } else if (bytes_read > 0) {
1716                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1717                         cifs_copy_cache_pages(mapping, page_list, bytes_read,
1718                                 smb_read_data + 4 /* RFC1001 hdr */ +
1719                                 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1720
1721                         i +=  bytes_read >> PAGE_CACHE_SHIFT;
1722                         cifs_stats_bytes_read(pTcon, bytes_read);
1723                         if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1724                                 i++; /* account for partial page */
1725
1726                                 /* server copy of file can have smaller size 
1727                                    than client */
1728                                 /* BB do we need to verify this common case ? 
1729                                    this case is ok - if we are at server EOF 
1730                                    we will hit it on next read */
1731
1732                         /* while (!list_empty(page_list) && (i < num_pages)) {
1733                                         page = list_entry(page_list->prev, 
1734                                                           struct page, list);
1735                                         list_del(&page->list);
1736                                         page_cache_release(page);
1737                                 }
1738                                 break; */
1739                         }
1740                 } else {
1741                         cFYI(1, ("No bytes read (%d) at offset %lld . "
1742                                  "Cleaning remaining pages from readahead list",
1743                                  bytes_read, offset));
1744                         /* BB turn off caching and do new lookup on 
1745                            file size at server? */
1746                         while (!list_empty(page_list) && (i < num_pages)) {
1747                                 page = list_entry(page_list->prev, struct page,
1748                                                   lru);
1749                                 list_del(&page->lru);
1750
1751                                 /* BB removeme - replace with zero of page? */
1752                                 page_cache_release(page);
1753                         }
1754                         break;
1755                 }
1756                 if (smb_read_data) {
1757                         if(buf_type == CIFS_SMALL_BUFFER)
1758                                 cifs_small_buf_release(smb_read_data);
1759                         else if(buf_type == CIFS_LARGE_BUFFER)
1760                                 cifs_buf_release(smb_read_data);
1761                         smb_read_data = NULL;
1762                 }
1763                 bytes_read = 0;
1764         }
1765
1766         pagevec_lru_add(&lru_pvec);
1767
1768 /* need to free smb_read_data buf before exit */
1769         if (smb_read_data) {
1770                 if(buf_type == CIFS_SMALL_BUFFER)
1771                         cifs_small_buf_release(smb_read_data);
1772                 else if(buf_type == CIFS_LARGE_BUFFER)
1773                         cifs_buf_release(smb_read_data);
1774                 smb_read_data = NULL;
1775         } 
1776
1777         FreeXid(xid);
1778         return rc;
1779 }
1780
1781 static int cifs_readpage_worker(struct file *file, struct page *page,
1782         loff_t *poffset)
1783 {
1784         char *read_data;
1785         int rc;
1786
1787         page_cache_get(page);
1788         read_data = kmap(page);
1789         /* for reads over a certain size could initiate async read ahead */
1790                                                                                                                            
1791         rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1792                                                                                                                            
1793         if (rc < 0)
1794                 goto io_error;
1795         else
1796                 cFYI(1, ("Bytes read %d ",rc));
1797                                                                                                                            
1798         file->f_dentry->d_inode->i_atime =
1799                 current_fs_time(file->f_dentry->d_inode->i_sb);
1800                                                                                                                            
1801         if (PAGE_CACHE_SIZE > rc)
1802                 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
1803
1804         flush_dcache_page(page);
1805         SetPageUptodate(page);
1806         rc = 0;
1807                                                                                                                            
1808 io_error:
1809         kunmap(page);
1810         page_cache_release(page);
1811         return rc;
1812 }
1813
1814 static int cifs_readpage(struct file *file, struct page *page)
1815 {
1816         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1817         int rc = -EACCES;
1818         int xid;
1819
1820         xid = GetXid();
1821
1822         if (file->private_data == NULL) {
1823                 FreeXid(xid);
1824                 return -EBADF;
1825         }
1826
1827         cFYI(1, ("readpage %p at offset %d 0x%x\n", 
1828                  page, (int)offset, (int)offset));
1829
1830         rc = cifs_readpage_worker(file, page, &offset);
1831
1832         unlock_page(page);
1833
1834         FreeXid(xid);
1835         return rc;
1836 }
1837
1838 /* We do not want to update the file size from server for inodes
1839    open for write - to avoid races with writepage extending
1840    the file - in the future we could consider allowing
1841    refreshing the inode only on increases in the file size 
1842    but this is tricky to do without racing with writebehind
1843    page caching in the current Linux kernel design */
1844 int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1845 {
1846         struct cifsFileInfo *open_file = NULL;
1847
1848         if (cifsInode)
1849                 open_file =  find_writable_file(cifsInode);
1850  
1851         if(open_file) {
1852                 struct cifs_sb_info *cifs_sb;
1853
1854                 /* there is not actually a write pending so let
1855                 this handle go free and allow it to
1856                 be closable if needed */
1857                 atomic_dec(&open_file->wrtPending);
1858
1859                 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
1860                 if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) {
1861                         /* since no page cache to corrupt on directio 
1862                         we can change size safely */
1863                         return 1;
1864                 }
1865
1866                 return 0;
1867         } else
1868                 return 1;
1869 }
1870
1871 static int cifs_prepare_write(struct file *file, struct page *page,
1872         unsigned from, unsigned to)
1873 {
1874         int rc = 0;
1875         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1876         cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1877         if (!PageUptodate(page)) {
1878         /*      if (to - from != PAGE_CACHE_SIZE) {
1879                         void *kaddr = kmap_atomic(page, KM_USER0);
1880                         memset(kaddr, 0, from);
1881                         memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1882                         flush_dcache_page(page);
1883                         kunmap_atomic(kaddr, KM_USER0);
1884                 } */
1885                 /* If we are writing a full page it will be up to date,
1886                    no need to read from the server */
1887                 if ((to == PAGE_CACHE_SIZE) && (from == 0))
1888                         SetPageUptodate(page);
1889
1890                 /* might as well read a page, it is fast enough */
1891                 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
1892                         rc = cifs_readpage_worker(file, page, &offset);
1893                 } else {
1894                 /* should we try using another file handle if there is one -
1895                    how would we lock it to prevent close of that handle
1896                    racing with this read?
1897                    In any case this will be written out by commit_write */
1898                 }
1899         }
1900
1901         /* BB should we pass any errors back? 
1902            e.g. if we do not have read access to the file */
1903         return 0;
1904 }
1905
1906 struct address_space_operations cifs_addr_ops = {
1907         .readpage = cifs_readpage,
1908         .readpages = cifs_readpages,
1909         .writepage = cifs_writepage,
1910         .writepages = cifs_writepages,
1911         .prepare_write = cifs_prepare_write,
1912         .commit_write = cifs_commit_write,
1913         .set_page_dirty = __set_page_dirty_nobuffers,
1914         /* .sync_page = cifs_sync_page, */
1915         /* .direct_IO = */
1916 };