Merge git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6
[sfrench/cifs-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/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         mutex_lock(&inode->i_sb->s_vfs_rename_mutex);
207         full_path = build_path_from_dentry(file->f_dentry);
208         mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);
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                         cifs_buf_release(ptmp);
559                 }
560                 ptmp = pCFileStruct->search_resume_name;
561                 if (ptmp) {
562                         cFYI(1, ("closedir free resume name"));
563                         pCFileStruct->search_resume_name = NULL;
564                         kfree(ptmp);
565                 }
566                 kfree(file->private_data);
567                 file->private_data = NULL;
568         }
569         /* BB can we lock the filestruct while this is going on? */
570         FreeXid(xid);
571         return rc;
572 }
573
574 int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
575 {
576         int rc, xid;
577         __u32 lockType = LOCKING_ANDX_LARGE_FILES;
578         __u32 numLock = 0;
579         __u32 numUnlock = 0;
580         __u64 length;
581         int wait_flag = FALSE;
582         struct cifs_sb_info *cifs_sb;
583         struct cifsTconInfo *pTcon;
584
585         length = 1 + pfLock->fl_end - pfLock->fl_start;
586         rc = -EACCES;
587         xid = GetXid();
588
589         cFYI(1, ("Lock parm: 0x%x flockflags: "
590                  "0x%x flocktype: 0x%x start: %lld end: %lld",
591                 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
592                 pfLock->fl_end));
593
594         if (pfLock->fl_flags & FL_POSIX)
595                 cFYI(1, ("Posix "));
596         if (pfLock->fl_flags & FL_FLOCK)
597                 cFYI(1, ("Flock "));
598         if (pfLock->fl_flags & FL_SLEEP) {
599                 cFYI(1, ("Blocking lock "));
600                 wait_flag = TRUE;
601         }
602         if (pfLock->fl_flags & FL_ACCESS)
603                 cFYI(1, ("Process suspended by mandatory locking - "
604                          "not implemented yet "));
605         if (pfLock->fl_flags & FL_LEASE)
606                 cFYI(1, ("Lease on file - not implemented yet"));
607         if (pfLock->fl_flags & 
608             (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
609                 cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags));
610
611         if (pfLock->fl_type == F_WRLCK) {
612                 cFYI(1, ("F_WRLCK "));
613                 numLock = 1;
614         } else if (pfLock->fl_type == F_UNLCK) {
615                 cFYI(1, ("F_UNLCK "));
616                 numUnlock = 1;
617         } else if (pfLock->fl_type == F_RDLCK) {
618                 cFYI(1, ("F_RDLCK "));
619                 lockType |= LOCKING_ANDX_SHARED_LOCK;
620                 numLock = 1;
621         } else if (pfLock->fl_type == F_EXLCK) {
622                 cFYI(1, ("F_EXLCK "));
623                 numLock = 1;
624         } else if (pfLock->fl_type == F_SHLCK) {
625                 cFYI(1, ("F_SHLCK "));
626                 lockType |= LOCKING_ANDX_SHARED_LOCK;
627                 numLock = 1;
628         } else
629                 cFYI(1, ("Unknown type of lock "));
630
631         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
632         pTcon = cifs_sb->tcon;
633
634         if (file->private_data == NULL) {
635                 FreeXid(xid);
636                 return -EBADF;
637         }
638
639         if (IS_GETLK(cmd)) {
640                 rc = CIFSSMBLock(xid, pTcon,
641                                  ((struct cifsFileInfo *)file->
642                                   private_data)->netfid,
643                                  length,
644                                  pfLock->fl_start, 0, 1, lockType,
645                                  0 /* wait flag */ );
646                 if (rc == 0) {
647                         rc = CIFSSMBLock(xid, pTcon,
648                                          ((struct cifsFileInfo *) file->
649                                           private_data)->netfid,
650                                          length,
651                                          pfLock->fl_start, 1 /* numUnlock */ ,
652                                          0 /* numLock */ , lockType,
653                                          0 /* wait flag */ );
654                         pfLock->fl_type = F_UNLCK;
655                         if (rc != 0)
656                                 cERROR(1, ("Error unlocking previously locked "
657                                            "range %d during test of lock ",
658                                            rc));
659                         rc = 0;
660
661                 } else {
662                         /* if rc == ERR_SHARING_VIOLATION ? */
663                         rc = 0; /* do not change lock type to unlock
664                                    since range in use */
665                 }
666
667                 FreeXid(xid);
668                 return rc;
669         }
670
671         rc = CIFSSMBLock(xid, pTcon,
672                          ((struct cifsFileInfo *) file->private_data)->
673                          netfid, length,
674                          pfLock->fl_start, numUnlock, numLock, lockType,
675                          wait_flag);
676         if (pfLock->fl_flags & FL_POSIX)
677                 posix_lock_file_wait(file, pfLock);
678         FreeXid(xid);
679         return rc;
680 }
681
682 ssize_t cifs_user_write(struct file *file, const char __user *write_data,
683         size_t write_size, loff_t *poffset)
684 {
685         int rc = 0;
686         unsigned int bytes_written = 0;
687         unsigned int total_written;
688         struct cifs_sb_info *cifs_sb;
689         struct cifsTconInfo *pTcon;
690         int xid, long_op;
691         struct cifsFileInfo *open_file;
692
693         if (file->f_dentry == NULL)
694                 return -EBADF;
695
696         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
697         if (cifs_sb == NULL)
698                 return -EBADF;
699
700         pTcon = cifs_sb->tcon;
701
702         /* cFYI(1,
703            (" write %d bytes to offset %lld of %s", write_size,
704            *poffset, file->f_dentry->d_name.name)); */
705
706         if (file->private_data == NULL)
707                 return -EBADF;
708         else
709                 open_file = (struct cifsFileInfo *) file->private_data;
710         
711         xid = GetXid();
712         if (file->f_dentry->d_inode == NULL) {
713                 FreeXid(xid);
714                 return -EBADF;
715         }
716
717         if (*poffset > file->f_dentry->d_inode->i_size)
718                 long_op = 2; /* writes past end of file can take a long time */
719         else
720                 long_op = 1;
721
722         for (total_written = 0; write_size > total_written;
723              total_written += bytes_written) {
724                 rc = -EAGAIN;
725                 while (rc == -EAGAIN) {
726                         if (file->private_data == NULL) {
727                                 /* file has been closed on us */
728                                 FreeXid(xid);
729                         /* if we have gotten here we have written some data
730                            and blocked, and the file has been freed on us while
731                            we blocked so return what we managed to write */
732                                 return total_written;
733                         } 
734                         if (open_file->closePend) {
735                                 FreeXid(xid);
736                                 if (total_written)
737                                         return total_written;
738                                 else
739                                         return -EBADF;
740                         }
741                         if (open_file->invalidHandle) {
742                                 if ((file->f_dentry == NULL) ||
743                                     (file->f_dentry->d_inode == NULL)) {
744                                         FreeXid(xid);
745                                         return total_written;
746                                 }
747                                 /* we could deadlock if we called
748                                    filemap_fdatawait from here so tell
749                                    reopen_file not to flush data to server
750                                    now */
751                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
752                                         file, FALSE);
753                                 if (rc != 0)
754                                         break;
755                         }
756
757                         rc = CIFSSMBWrite(xid, pTcon,
758                                 open_file->netfid,
759                                 min_t(const int, cifs_sb->wsize,
760                                       write_size - total_written),
761                                 *poffset, &bytes_written,
762                                 NULL, write_data + total_written, long_op);
763                 }
764                 if (rc || (bytes_written == 0)) {
765                         if (total_written)
766                                 break;
767                         else {
768                                 FreeXid(xid);
769                                 return rc;
770                         }
771                 } else
772                         *poffset += bytes_written;
773                 long_op = FALSE; /* subsequent writes fast -
774                                     15 seconds is plenty */
775         }
776
777         cifs_stats_bytes_written(pTcon, total_written);
778
779         /* since the write may have blocked check these pointers again */
780         if (file->f_dentry) {
781                 if (file->f_dentry->d_inode) {
782                         struct inode *inode = file->f_dentry->d_inode;
783                         inode->i_ctime = inode->i_mtime =
784                                 current_fs_time(inode->i_sb);
785                         if (total_written > 0) {
786                                 if (*poffset > file->f_dentry->d_inode->i_size)
787                                         i_size_write(file->f_dentry->d_inode,
788                                         *poffset);
789                         }
790                         mark_inode_dirty_sync(file->f_dentry->d_inode);
791                 }
792         }
793         FreeXid(xid);
794         return total_written;
795 }
796
797 static ssize_t cifs_write(struct file *file, const char *write_data,
798         size_t write_size, loff_t *poffset)
799 {
800         int rc = 0;
801         unsigned int bytes_written = 0;
802         unsigned int total_written;
803         struct cifs_sb_info *cifs_sb;
804         struct cifsTconInfo *pTcon;
805         int xid, long_op;
806         struct cifsFileInfo *open_file;
807
808         if (file->f_dentry == NULL)
809                 return -EBADF;
810
811         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
812         if (cifs_sb == NULL)
813                 return -EBADF;
814
815         pTcon = cifs_sb->tcon;
816
817         cFYI(1,("write %zd bytes to offset %lld of %s", write_size,
818            *poffset, file->f_dentry->d_name.name));
819
820         if (file->private_data == NULL)
821                 return -EBADF;
822         else
823                 open_file = (struct cifsFileInfo *)file->private_data;
824         
825         xid = GetXid();
826         if (file->f_dentry->d_inode == NULL) {
827                 FreeXid(xid);
828                 return -EBADF;
829         }
830
831         if (*poffset > file->f_dentry->d_inode->i_size)
832                 long_op = 2; /* writes past end of file can take a long time */
833         else
834                 long_op = 1;
835
836         for (total_written = 0; write_size > total_written;
837              total_written += bytes_written) {
838                 rc = -EAGAIN;
839                 while (rc == -EAGAIN) {
840                         if (file->private_data == NULL) {
841                                 /* file has been closed on us */
842                                 FreeXid(xid);
843                         /* if we have gotten here we have written some data
844                            and blocked, and the file has been freed on us
845                            while we blocked so return what we managed to 
846                            write */
847                                 return total_written;
848                         } 
849                         if (open_file->closePend) {
850                                 FreeXid(xid);
851                                 if (total_written)
852                                         return total_written;
853                                 else
854                                         return -EBADF;
855                         }
856                         if (open_file->invalidHandle) {
857                                 if ((file->f_dentry == NULL) ||
858                                    (file->f_dentry->d_inode == NULL)) {
859                                         FreeXid(xid);
860                                         return total_written;
861                                 }
862                                 /* we could deadlock if we called
863                                    filemap_fdatawait from here so tell
864                                    reopen_file not to flush data to 
865                                    server now */
866                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
867                                         file, FALSE);
868                                 if (rc != 0)
869                                         break;
870                         }
871                         /* BB FIXME We can not sign across two buffers yet */
872                         if((pTcon->ses->server->secMode & 
873                          (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
874                                 struct kvec iov[2];
875                                 unsigned int len;
876
877                                 len = min((size_t)cifs_sb->wsize,
878                                           write_size - total_written);
879                                 /* iov[0] is reserved for smb header */
880                                 iov[1].iov_base = (char *)write_data +
881                                                   total_written;
882                                 iov[1].iov_len = len;
883                                 rc = CIFSSMBWrite2(xid, pTcon,
884                                                 open_file->netfid, len,
885                                                 *poffset, &bytes_written,
886                                                 iov, 1, long_op);
887                         } else
888                         /* BB FIXME fixup indentation of line below */
889                         rc = CIFSSMBWrite(xid, pTcon,
890                                  open_file->netfid,
891                                  min_t(const int, cifs_sb->wsize, 
892                                        write_size - total_written),
893                                  *poffset, &bytes_written,
894                                  write_data + total_written, NULL, long_op);
895                 }
896                 if (rc || (bytes_written == 0)) {
897                         if (total_written)
898                                 break;
899                         else {
900                                 FreeXid(xid);
901                                 return rc;
902                         }
903                 } else
904                         *poffset += bytes_written;
905                 long_op = FALSE; /* subsequent writes fast - 
906                                     15 seconds is plenty */
907         }
908
909         cifs_stats_bytes_written(pTcon, total_written);
910
911         /* since the write may have blocked check these pointers again */
912         if (file->f_dentry) {
913                 if (file->f_dentry->d_inode) {
914                         file->f_dentry->d_inode->i_ctime = 
915                         file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
916                         if (total_written > 0) {
917                                 if (*poffset > file->f_dentry->d_inode->i_size)
918                                         i_size_write(file->f_dentry->d_inode, 
919                                                      *poffset);
920                         }
921                         mark_inode_dirty_sync(file->f_dentry->d_inode);
922                 }
923         }
924         FreeXid(xid);
925         return total_written;
926 }
927
928 struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
929 {
930         struct cifsFileInfo *open_file;
931         int rc;
932
933         read_lock(&GlobalSMBSeslock);
934         list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
935                 if (open_file->closePend)
936                         continue;
937                 if (open_file->pfile &&
938                     ((open_file->pfile->f_flags & O_RDWR) ||
939                      (open_file->pfile->f_flags & O_WRONLY))) {
940                         atomic_inc(&open_file->wrtPending);
941                         read_unlock(&GlobalSMBSeslock);
942                         if((open_file->invalidHandle) && 
943                            (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
944                                 rc = cifs_reopen_file(&cifs_inode->vfs_inode, 
945                                                       open_file->pfile, FALSE);
946                                 /* if it fails, try another handle - might be */
947                                 /* dangerous to hold up writepages with retry */
948                                 if(rc) {
949                                         cFYI(1,("failed on reopen file in wp"));
950                                         read_lock(&GlobalSMBSeslock);
951                                         /* can not use this handle, no write
952                                         pending on this one after all */
953                                         atomic_dec
954                                              (&open_file->wrtPending);
955                                         continue;
956                                 }
957                         }
958                         return open_file;
959                 }
960         }
961         read_unlock(&GlobalSMBSeslock);
962         return NULL;
963 }
964
965 static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
966 {
967         struct address_space *mapping = page->mapping;
968         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
969         char *write_data;
970         int rc = -EFAULT;
971         int bytes_written = 0;
972         struct cifs_sb_info *cifs_sb;
973         struct cifsTconInfo *pTcon;
974         struct inode *inode;
975         struct cifsFileInfo *open_file;
976
977         if (!mapping || !mapping->host)
978                 return -EFAULT;
979
980         inode = page->mapping->host;
981         cifs_sb = CIFS_SB(inode->i_sb);
982         pTcon = cifs_sb->tcon;
983
984         offset += (loff_t)from;
985         write_data = kmap(page);
986         write_data += from;
987
988         if ((to > PAGE_CACHE_SIZE) || (from > to)) {
989                 kunmap(page);
990                 return -EIO;
991         }
992
993         /* racing with truncate? */
994         if (offset > mapping->host->i_size) {
995                 kunmap(page);
996                 return 0; /* don't care */
997         }
998
999         /* check to make sure that we are not extending the file */
1000         if (mapping->host->i_size - offset < (loff_t)to)
1001                 to = (unsigned)(mapping->host->i_size - offset); 
1002
1003         open_file = find_writable_file(CIFS_I(mapping->host));
1004         if (open_file) {
1005                 bytes_written = cifs_write(open_file->pfile, write_data,
1006                                            to-from, &offset);
1007                 atomic_dec(&open_file->wrtPending);
1008                 /* Does mm or vfs already set times? */
1009                 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
1010                 if ((bytes_written > 0) && (offset)) {
1011                         rc = 0;
1012                 } else if (bytes_written < 0) {
1013                         if (rc != -EBADF)
1014                                 rc = bytes_written;
1015                 }
1016         } else {
1017                 cFYI(1, ("No writeable filehandles for inode"));
1018                 rc = -EIO;
1019         }
1020
1021         kunmap(page);
1022         return rc;
1023 }
1024
1025 static int cifs_writepages(struct address_space *mapping,
1026                            struct writeback_control *wbc)
1027 {
1028         struct backing_dev_info *bdi = mapping->backing_dev_info;
1029         unsigned int bytes_to_write;
1030         unsigned int bytes_written;
1031         struct cifs_sb_info *cifs_sb;
1032         int done = 0;
1033         pgoff_t end = -1;
1034         pgoff_t index;
1035         int is_range = 0;
1036         struct kvec iov[32];
1037         int len;
1038         int n_iov = 0;
1039         pgoff_t next;
1040         int nr_pages;
1041         __u64 offset = 0;
1042         struct cifsFileInfo *open_file;
1043         struct page *page;
1044         struct pagevec pvec;
1045         int rc = 0;
1046         int scanned = 0;
1047         int xid;
1048
1049         cifs_sb = CIFS_SB(mapping->host->i_sb);
1050         
1051         /*
1052          * If wsize is smaller that the page cache size, default to writing
1053          * one page at a time via cifs_writepage
1054          */
1055         if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1056                 return generic_writepages(mapping, wbc);
1057
1058         /* BB FIXME we do not have code to sign across multiple buffers yet,
1059            so go to older writepage style write which we can sign if needed */
1060         if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
1061                 if(cifs_sb->tcon->ses->server->secMode &
1062                           (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1063                         return generic_writepages(mapping, wbc);
1064
1065         /*
1066          * BB: Is this meaningful for a non-block-device file system?
1067          * If it is, we should test it again after we do I/O
1068          */
1069         if (wbc->nonblocking && bdi_write_congested(bdi)) {
1070                 wbc->encountered_congestion = 1;
1071                 return 0;
1072         }
1073
1074         xid = GetXid();
1075
1076         pagevec_init(&pvec, 0);
1077         if (wbc->sync_mode == WB_SYNC_NONE)
1078                 index = mapping->writeback_index; /* Start from prev offset */
1079         else {
1080                 index = 0;
1081                 scanned = 1;
1082         }
1083         if (wbc->start || wbc->end) {
1084                 index = wbc->start >> PAGE_CACHE_SHIFT;
1085                 end = wbc->end >> PAGE_CACHE_SHIFT;
1086                 is_range = 1;
1087                 scanned = 1;
1088         }
1089 retry:
1090         while (!done && (index <= end) &&
1091                (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
1092                         PAGECACHE_TAG_DIRTY,
1093                         min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1))) {
1094                 int first;
1095                 unsigned int i;
1096
1097                 first = -1;
1098                 next = 0;
1099                 n_iov = 0;
1100                 bytes_to_write = 0;
1101
1102                 for (i = 0; i < nr_pages; i++) {
1103                         page = pvec.pages[i];
1104                         /*
1105                          * At this point we hold neither mapping->tree_lock nor
1106                          * lock on the page itself: the page may be truncated or
1107                          * invalidated (changing page->mapping to NULL), or even
1108                          * swizzled back from swapper_space to tmpfs file
1109                          * mapping
1110                          */
1111
1112                         if (first < 0)
1113                                 lock_page(page);
1114                         else if (TestSetPageLocked(page))
1115                                 break;
1116
1117                         if (unlikely(page->mapping != mapping)) {
1118                                 unlock_page(page);
1119                                 break;
1120                         }
1121
1122                         if (unlikely(is_range) && (page->index > end)) {
1123                                 done = 1;
1124                                 unlock_page(page);
1125                                 break;
1126                         }
1127
1128                         if (next && (page->index != next)) {
1129                                 /* Not next consecutive page */
1130                                 unlock_page(page);
1131                                 break;
1132                         }
1133
1134                         if (wbc->sync_mode != WB_SYNC_NONE)
1135                                 wait_on_page_writeback(page);
1136
1137                         if (PageWriteback(page) ||
1138                                         !test_clear_page_dirty(page)) {
1139                                 unlock_page(page);
1140                                 break;
1141                         }
1142
1143                         if (page_offset(page) >= mapping->host->i_size) {
1144                                 done = 1;
1145                                 unlock_page(page);
1146                                 break;
1147                         }
1148
1149                         /*
1150                          * BB can we get rid of this?  pages are held by pvec
1151                          */
1152                         page_cache_get(page);
1153
1154                         len = min(mapping->host->i_size - page_offset(page),
1155                                   (loff_t)PAGE_CACHE_SIZE);
1156
1157                         /* reserve iov[0] for the smb header */
1158                         n_iov++;
1159                         iov[n_iov].iov_base = kmap(page);
1160                         iov[n_iov].iov_len = len;
1161                         bytes_to_write += len;
1162
1163                         if (first < 0) {
1164                                 first = i;
1165                                 offset = page_offset(page);
1166                         }
1167                         next = page->index + 1;
1168                         if (bytes_to_write + PAGE_CACHE_SIZE > cifs_sb->wsize)
1169                                 break;
1170                 }
1171                 if (n_iov) {
1172                         /* Search for a writable handle every time we call
1173                          * CIFSSMBWrite2.  We can't rely on the last handle
1174                          * we used to still be valid
1175                          */
1176                         open_file = find_writable_file(CIFS_I(mapping->host));
1177                         if (!open_file) {
1178                                 cERROR(1, ("No writable handles for inode"));
1179                                 rc = -EBADF;
1180                         } else {
1181                                 rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
1182                                                    open_file->netfid,
1183                                                    bytes_to_write, offset,
1184                                                    &bytes_written, iov, n_iov,
1185                                                    1);
1186                                 atomic_dec(&open_file->wrtPending);
1187                                 if (rc || bytes_written < bytes_to_write) {
1188                                         cERROR(1,("Write2 ret %d, written = %d",
1189                                                   rc, bytes_written));
1190                                         /* BB what if continued retry is
1191                                            requested via mount flags? */
1192                                         set_bit(AS_EIO, &mapping->flags);
1193                                 } else {
1194                                         cifs_stats_bytes_written(cifs_sb->tcon,
1195                                                                  bytes_written);
1196                                 }
1197                         }
1198                         for (i = 0; i < n_iov; i++) {
1199                                 page = pvec.pages[first + i];
1200                                 /* Should we also set page error on
1201                                 success rc but too little data written? */
1202                                 /* BB investigate retry logic on temporary
1203                                 server crash cases and how recovery works
1204                                 when page marked as error */ 
1205                                 if(rc)
1206                                         SetPageError(page);
1207                                 kunmap(page);
1208                                 unlock_page(page);
1209                                 page_cache_release(page);
1210                         }
1211                         if ((wbc->nr_to_write -= n_iov) <= 0)
1212                                 done = 1;
1213                         index = next;
1214                 }
1215                 pagevec_release(&pvec);
1216         }
1217         if (!scanned && !done) {
1218                 /*
1219                  * We hit the last page and there is more work to be done: wrap
1220                  * back to the start of the file
1221                  */
1222                 scanned = 1;
1223                 index = 0;
1224                 goto retry;
1225         }
1226         if (!is_range)
1227                 mapping->writeback_index = index;
1228
1229         FreeXid(xid);
1230
1231         return rc;
1232 }
1233
1234 static int cifs_writepage(struct page* page, struct writeback_control *wbc)
1235 {
1236         int rc = -EFAULT;
1237         int xid;
1238
1239         xid = GetXid();
1240 /* BB add check for wbc flags */
1241         page_cache_get(page);
1242         if (!PageUptodate(page)) {
1243                 cFYI(1, ("ppw - page not up to date"));
1244         }
1245         
1246         rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
1247         SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
1248         unlock_page(page);
1249         page_cache_release(page);       
1250         FreeXid(xid);
1251         return rc;
1252 }
1253
1254 static int cifs_commit_write(struct file *file, struct page *page,
1255         unsigned offset, unsigned to)
1256 {
1257         int xid;
1258         int rc = 0;
1259         struct inode *inode = page->mapping->host;
1260         loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
1261         char *page_data;
1262
1263         xid = GetXid();
1264         cFYI(1, ("commit write for page %p up to position %lld for %d", 
1265                  page, position, to));
1266         if (position > inode->i_size) {
1267                 i_size_write(inode, position);
1268                 /* if (file->private_data == NULL) {
1269                         rc = -EBADF;
1270                 } else {
1271                         open_file = (struct cifsFileInfo *)file->private_data;
1272                         cifs_sb = CIFS_SB(inode->i_sb);
1273                         rc = -EAGAIN;
1274                         while (rc == -EAGAIN) {
1275                                 if ((open_file->invalidHandle) && 
1276                                     (!open_file->closePend)) {
1277                                         rc = cifs_reopen_file(
1278                                                 file->f_dentry->d_inode, file);
1279                                         if (rc != 0)
1280                                                 break;
1281                                 }
1282                                 if (!open_file->closePend) {
1283                                         rc = CIFSSMBSetFileSize(xid,
1284                                                 cifs_sb->tcon, position,
1285                                                 open_file->netfid,
1286                                                 open_file->pid, FALSE);
1287                                 } else {
1288                                         rc = -EBADF;
1289                                         break;
1290                                 }
1291                         }
1292                         cFYI(1, (" SetEOF (commit write) rc = %d", rc));
1293                 } */
1294         }
1295         if (!PageUptodate(page)) {
1296                 position =  ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
1297                 /* can not rely on (or let) writepage write this data */
1298                 if (to < offset) {
1299                         cFYI(1, ("Illegal offsets, can not copy from %d to %d",
1300                                 offset, to));
1301                         FreeXid(xid);
1302                         return rc;
1303                 }
1304                 /* this is probably better than directly calling
1305                    partialpage_write since in this function the file handle is
1306                    known which we might as well leverage */
1307                 /* BB check if anything else missing out of ppw
1308                    such as updating last write time */
1309                 page_data = kmap(page);
1310                 rc = cifs_write(file, page_data + offset, to-offset,
1311                                 &position);
1312                 if (rc > 0)
1313                         rc = 0;
1314                 /* else if (rc < 0) should we set writebehind rc? */
1315                 kunmap(page);
1316         } else {        
1317                 set_page_dirty(page);
1318         }
1319
1320         FreeXid(xid);
1321         return rc;
1322 }
1323
1324 int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1325 {
1326         int xid;
1327         int rc = 0;
1328         struct inode *inode = file->f_dentry->d_inode;
1329
1330         xid = GetXid();
1331
1332         cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 
1333                 dentry->d_name.name, datasync));
1334         
1335         rc = filemap_fdatawrite(inode->i_mapping);
1336         if (rc == 0)
1337                 CIFS_I(inode)->write_behind_rc = 0;
1338         FreeXid(xid);
1339         return rc;
1340 }
1341
1342 /* static void cifs_sync_page(struct page *page)
1343 {
1344         struct address_space *mapping;
1345         struct inode *inode;
1346         unsigned long index = page->index;
1347         unsigned int rpages = 0;
1348         int rc = 0;
1349
1350         cFYI(1, ("sync page %p",page));
1351         mapping = page->mapping;
1352         if (!mapping)
1353                 return 0;
1354         inode = mapping->host;
1355         if (!inode)
1356                 return; */
1357
1358 /*      fill in rpages then 
1359         result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
1360
1361 /*      cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
1362
1363 #if 0
1364         if (rc < 0)
1365                 return rc;
1366         return 0;
1367 #endif
1368 } */
1369
1370 /*
1371  * As file closes, flush all cached write data for this inode checking
1372  * for write behind errors.
1373  */
1374 int cifs_flush(struct file *file)
1375 {
1376         struct inode * inode = file->f_dentry->d_inode;
1377         int rc = 0;
1378
1379         /* Rather than do the steps manually:
1380            lock the inode for writing
1381            loop through pages looking for write behind data (dirty pages)
1382            coalesce into contiguous 16K (or smaller) chunks to write to server
1383            send to server (prefer in parallel)
1384            deal with writebehind errors
1385            unlock inode for writing
1386            filemapfdatawrite appears easier for the time being */
1387
1388         rc = filemap_fdatawrite(inode->i_mapping);
1389         if (!rc) /* reset wb rc if we were able to write out dirty pages */
1390                 CIFS_I(inode)->write_behind_rc = 0;
1391                 
1392         cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc));
1393
1394         return rc;
1395 }
1396
1397 ssize_t cifs_user_read(struct file *file, char __user *read_data,
1398         size_t read_size, loff_t *poffset)
1399 {
1400         int rc = -EACCES;
1401         unsigned int bytes_read = 0;
1402         unsigned int total_read = 0;
1403         unsigned int current_read_size;
1404         struct cifs_sb_info *cifs_sb;
1405         struct cifsTconInfo *pTcon;
1406         int xid;
1407         struct cifsFileInfo *open_file;
1408         char *smb_read_data;
1409         char __user *current_offset;
1410         struct smb_com_read_rsp *pSMBr;
1411
1412         xid = GetXid();
1413         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1414         pTcon = cifs_sb->tcon;
1415
1416         if (file->private_data == NULL) {
1417                 FreeXid(xid);
1418                 return -EBADF;
1419         }
1420         open_file = (struct cifsFileInfo *)file->private_data;
1421
1422         if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
1423                 cFYI(1, ("attempting read on write only file instance"));
1424         }
1425         for (total_read = 0, current_offset = read_data;
1426              read_size > total_read;
1427              total_read += bytes_read, current_offset += bytes_read) {
1428                 current_read_size = min_t(const int, read_size - total_read, 
1429                                           cifs_sb->rsize);
1430                 rc = -EAGAIN;
1431                 smb_read_data = NULL;
1432                 while (rc == -EAGAIN) {
1433                         int buf_type = CIFS_NO_BUFFER;
1434                         if ((open_file->invalidHandle) && 
1435                             (!open_file->closePend)) {
1436                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1437                                         file, TRUE);
1438                                 if (rc != 0)
1439                                         break;
1440                         }
1441                         rc = CIFSSMBRead(xid, pTcon,
1442                                          open_file->netfid,
1443                                          current_read_size, *poffset,
1444                                          &bytes_read, &smb_read_data,
1445                                          &buf_type);
1446                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1447                         if (smb_read_data) {
1448                                 if (copy_to_user(current_offset,
1449                                                 smb_read_data +
1450                                                 4 /* RFC1001 length field */ +
1451                                                 le16_to_cpu(pSMBr->DataOffset),
1452                                                 bytes_read)) {
1453                                         rc = -EFAULT;
1454                                 }
1455
1456                                 if(buf_type == CIFS_SMALL_BUFFER)
1457                                         cifs_small_buf_release(smb_read_data);
1458                                 else if(buf_type == CIFS_LARGE_BUFFER)
1459                                         cifs_buf_release(smb_read_data);
1460                                 smb_read_data = NULL;
1461                         }
1462                 }
1463                 if (rc || (bytes_read == 0)) {
1464                         if (total_read) {
1465                                 break;
1466                         } else {
1467                                 FreeXid(xid);
1468                                 return rc;
1469                         }
1470                 } else {
1471                         cifs_stats_bytes_read(pTcon, bytes_read);
1472                         *poffset += bytes_read;
1473                 }
1474         }
1475         FreeXid(xid);
1476         return total_read;
1477 }
1478
1479
1480 static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1481         loff_t *poffset)
1482 {
1483         int rc = -EACCES;
1484         unsigned int bytes_read = 0;
1485         unsigned int total_read;
1486         unsigned int current_read_size;
1487         struct cifs_sb_info *cifs_sb;
1488         struct cifsTconInfo *pTcon;
1489         int xid;
1490         char *current_offset;
1491         struct cifsFileInfo *open_file;
1492         int buf_type = CIFS_NO_BUFFER;
1493
1494         xid = GetXid();
1495         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1496         pTcon = cifs_sb->tcon;
1497
1498         if (file->private_data == NULL) {
1499                 FreeXid(xid);
1500                 return -EBADF;
1501         }
1502         open_file = (struct cifsFileInfo *)file->private_data;
1503
1504         if ((file->f_flags & O_ACCMODE) == O_WRONLY)
1505                 cFYI(1, ("attempting read on write only file instance"));
1506
1507         for (total_read = 0, current_offset = read_data; 
1508              read_size > total_read;
1509              total_read += bytes_read, current_offset += bytes_read) {
1510                 current_read_size = min_t(const int, read_size - total_read,
1511                                           cifs_sb->rsize);
1512                 /* For windows me and 9x we do not want to request more
1513                 than it negotiated since it will refuse the read then */
1514                 if((pTcon->ses) && 
1515                         !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
1516                         current_read_size = min_t(const int, current_read_size,
1517                                         pTcon->ses->server->maxBuf - 128);
1518                 }
1519                 rc = -EAGAIN;
1520                 while (rc == -EAGAIN) {
1521                         if ((open_file->invalidHandle) && 
1522                             (!open_file->closePend)) {
1523                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1524                                         file, TRUE);
1525                                 if (rc != 0)
1526                                         break;
1527                         }
1528                         rc = CIFSSMBRead(xid, pTcon,
1529                                          open_file->netfid,
1530                                          current_read_size, *poffset,
1531                                          &bytes_read, &current_offset,
1532                                          &buf_type);
1533                 }
1534                 if (rc || (bytes_read == 0)) {
1535                         if (total_read) {
1536                                 break;
1537                         } else {
1538                                 FreeXid(xid);
1539                                 return rc;
1540                         }
1541                 } else {
1542                         cifs_stats_bytes_read(pTcon, total_read);
1543                         *poffset += bytes_read;
1544                 }
1545         }
1546         FreeXid(xid);
1547         return total_read;
1548 }
1549
1550 int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1551 {
1552         struct dentry *dentry = file->f_dentry;
1553         int rc, xid;
1554
1555         xid = GetXid();
1556         rc = cifs_revalidate(dentry);
1557         if (rc) {
1558                 cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
1559                 FreeXid(xid);
1560                 return rc;
1561         }
1562         rc = generic_file_mmap(file, vma);
1563         FreeXid(xid);
1564         return rc;
1565 }
1566
1567
1568 static void cifs_copy_cache_pages(struct address_space *mapping, 
1569         struct list_head *pages, int bytes_read, char *data,
1570         struct pagevec *plru_pvec)
1571 {
1572         struct page *page;
1573         char *target;
1574
1575         while (bytes_read > 0) {
1576                 if (list_empty(pages))
1577                         break;
1578
1579                 page = list_entry(pages->prev, struct page, lru);
1580                 list_del(&page->lru);
1581
1582                 if (add_to_page_cache(page, mapping, page->index,
1583                                       GFP_KERNEL)) {
1584                         page_cache_release(page);
1585                         cFYI(1, ("Add page cache failed"));
1586                         data += PAGE_CACHE_SIZE;
1587                         bytes_read -= PAGE_CACHE_SIZE;
1588                         continue;
1589                 }
1590
1591                 target = kmap_atomic(page,KM_USER0);
1592
1593                 if (PAGE_CACHE_SIZE > bytes_read) {
1594                         memcpy(target, data, bytes_read);
1595                         /* zero the tail end of this partial page */
1596                         memset(target + bytes_read, 0, 
1597                                PAGE_CACHE_SIZE - bytes_read);
1598                         bytes_read = 0;
1599                 } else {
1600                         memcpy(target, data, PAGE_CACHE_SIZE);
1601                         bytes_read -= PAGE_CACHE_SIZE;
1602                 }
1603                 kunmap_atomic(target, KM_USER0);
1604
1605                 flush_dcache_page(page);
1606                 SetPageUptodate(page);
1607                 unlock_page(page);
1608                 if (!pagevec_add(plru_pvec, page))
1609                         __pagevec_lru_add(plru_pvec);
1610                 data += PAGE_CACHE_SIZE;
1611         }
1612         return;
1613 }
1614
1615 static int cifs_readpages(struct file *file, struct address_space *mapping,
1616         struct list_head *page_list, unsigned num_pages)
1617 {
1618         int rc = -EACCES;
1619         int xid;
1620         loff_t offset;
1621         struct page *page;
1622         struct cifs_sb_info *cifs_sb;
1623         struct cifsTconInfo *pTcon;
1624         int bytes_read = 0;
1625         unsigned int read_size,i;
1626         char *smb_read_data = NULL;
1627         struct smb_com_read_rsp *pSMBr;
1628         struct pagevec lru_pvec;
1629         struct cifsFileInfo *open_file;
1630         int buf_type = CIFS_NO_BUFFER;
1631
1632         xid = GetXid();
1633         if (file->private_data == NULL) {
1634                 FreeXid(xid);
1635                 return -EBADF;
1636         }
1637         open_file = (struct cifsFileInfo *)file->private_data;
1638         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1639         pTcon = cifs_sb->tcon;
1640
1641         pagevec_init(&lru_pvec, 0);
1642
1643         for (i = 0; i < num_pages; ) {
1644                 unsigned contig_pages;
1645                 struct page *tmp_page;
1646                 unsigned long expected_index;
1647
1648                 if (list_empty(page_list))
1649                         break;
1650
1651                 page = list_entry(page_list->prev, struct page, lru);
1652                 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1653
1654                 /* count adjacent pages that we will read into */
1655                 contig_pages = 0;
1656                 expected_index = 
1657                         list_entry(page_list->prev, struct page, lru)->index;
1658                 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1659                         if (tmp_page->index == expected_index) {
1660                                 contig_pages++;
1661                                 expected_index++;
1662                         } else
1663                                 break; 
1664                 }
1665                 if (contig_pages + i >  num_pages)
1666                         contig_pages = num_pages - i;
1667
1668                 /* for reads over a certain size could initiate async
1669                    read ahead */
1670
1671                 read_size = contig_pages * PAGE_CACHE_SIZE;
1672                 /* Read size needs to be in multiples of one page */
1673                 read_size = min_t(const unsigned int, read_size,
1674                                   cifs_sb->rsize & PAGE_CACHE_MASK);
1675
1676                 rc = -EAGAIN;
1677                 while (rc == -EAGAIN) {
1678                         if ((open_file->invalidHandle) && 
1679                             (!open_file->closePend)) {
1680                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1681                                         file, TRUE);
1682                                 if (rc != 0)
1683                                         break;
1684                         }
1685
1686                         rc = CIFSSMBRead(xid, pTcon,
1687                                          open_file->netfid,
1688                                          read_size, offset,
1689                                          &bytes_read, &smb_read_data,
1690                                          &buf_type);
1691                         /* BB more RC checks ? */
1692                         if (rc== -EAGAIN) {
1693                                 if (smb_read_data) {
1694                                         if(buf_type == CIFS_SMALL_BUFFER)
1695                                                 cifs_small_buf_release(smb_read_data);
1696                                         else if(buf_type == CIFS_LARGE_BUFFER)
1697                                                 cifs_buf_release(smb_read_data);
1698                                         smb_read_data = NULL;
1699                                 }
1700                         }
1701                 }
1702                 if ((rc < 0) || (smb_read_data == NULL)) {
1703                         cFYI(1, ("Read error in readpages: %d", rc));
1704                         /* clean up remaing pages off list */
1705                         while (!list_empty(page_list) && (i < num_pages)) {
1706                                 page = list_entry(page_list->prev, struct page,
1707                                                   lru);
1708                                 list_del(&page->lru);
1709                                 page_cache_release(page);
1710                         }
1711                         break;
1712                 } else if (bytes_read > 0) {
1713                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1714                         cifs_copy_cache_pages(mapping, page_list, bytes_read,
1715                                 smb_read_data + 4 /* RFC1001 hdr */ +
1716                                 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1717
1718                         i +=  bytes_read >> PAGE_CACHE_SHIFT;
1719                         cifs_stats_bytes_read(pTcon, bytes_read);
1720                         if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1721                                 i++; /* account for partial page */
1722
1723                                 /* server copy of file can have smaller size 
1724                                    than client */
1725                                 /* BB do we need to verify this common case ? 
1726                                    this case is ok - if we are at server EOF 
1727                                    we will hit it on next read */
1728
1729                         /* while (!list_empty(page_list) && (i < num_pages)) {
1730                                         page = list_entry(page_list->prev, 
1731                                                           struct page, list);
1732                                         list_del(&page->list);
1733                                         page_cache_release(page);
1734                                 }
1735                                 break; */
1736                         }
1737                 } else {
1738                         cFYI(1, ("No bytes read (%d) at offset %lld . "
1739                                  "Cleaning remaining pages from readahead list",
1740                                  bytes_read, offset));
1741                         /* BB turn off caching and do new lookup on 
1742                            file size at server? */
1743                         while (!list_empty(page_list) && (i < num_pages)) {
1744                                 page = list_entry(page_list->prev, struct page,
1745                                                   lru);
1746                                 list_del(&page->lru);
1747
1748                                 /* BB removeme - replace with zero of page? */
1749                                 page_cache_release(page);
1750                         }
1751                         break;
1752                 }
1753                 if (smb_read_data) {
1754                         if(buf_type == CIFS_SMALL_BUFFER)
1755                                 cifs_small_buf_release(smb_read_data);
1756                         else if(buf_type == CIFS_LARGE_BUFFER)
1757                                 cifs_buf_release(smb_read_data);
1758                         smb_read_data = NULL;
1759                 }
1760                 bytes_read = 0;
1761         }
1762
1763         pagevec_lru_add(&lru_pvec);
1764
1765 /* need to free smb_read_data buf before exit */
1766         if (smb_read_data) {
1767                 if(buf_type == CIFS_SMALL_BUFFER)
1768                         cifs_small_buf_release(smb_read_data);
1769                 else if(buf_type == CIFS_LARGE_BUFFER)
1770                         cifs_buf_release(smb_read_data);
1771                 smb_read_data = NULL;
1772         } 
1773
1774         FreeXid(xid);
1775         return rc;
1776 }
1777
1778 static int cifs_readpage_worker(struct file *file, struct page *page,
1779         loff_t *poffset)
1780 {
1781         char *read_data;
1782         int rc;
1783
1784         page_cache_get(page);
1785         read_data = kmap(page);
1786         /* for reads over a certain size could initiate async read ahead */
1787                                                                                                                            
1788         rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1789                                                                                                                            
1790         if (rc < 0)
1791                 goto io_error;
1792         else
1793                 cFYI(1, ("Bytes read %d ",rc));
1794                                                                                                                            
1795         file->f_dentry->d_inode->i_atime =
1796                 current_fs_time(file->f_dentry->d_inode->i_sb);
1797                                                                                                                            
1798         if (PAGE_CACHE_SIZE > rc)
1799                 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
1800
1801         flush_dcache_page(page);
1802         SetPageUptodate(page);
1803         rc = 0;
1804                                                                                                                            
1805 io_error:
1806         kunmap(page);
1807         page_cache_release(page);
1808         return rc;
1809 }
1810
1811 static int cifs_readpage(struct file *file, struct page *page)
1812 {
1813         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1814         int rc = -EACCES;
1815         int xid;
1816
1817         xid = GetXid();
1818
1819         if (file->private_data == NULL) {
1820                 FreeXid(xid);
1821                 return -EBADF;
1822         }
1823
1824         cFYI(1, ("readpage %p at offset %d 0x%x\n", 
1825                  page, (int)offset, (int)offset));
1826
1827         rc = cifs_readpage_worker(file, page, &offset);
1828
1829         unlock_page(page);
1830
1831         FreeXid(xid);
1832         return rc;
1833 }
1834
1835 /* We do not want to update the file size from server for inodes
1836    open for write - to avoid races with writepage extending
1837    the file - in the future we could consider allowing
1838    refreshing the inode only on increases in the file size 
1839    but this is tricky to do without racing with writebehind
1840    page caching in the current Linux kernel design */
1841 int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1842 {
1843         struct cifsFileInfo *open_file = NULL;
1844
1845         if (cifsInode)
1846                 open_file =  find_writable_file(cifsInode);
1847  
1848         if(open_file) {
1849                 struct cifs_sb_info *cifs_sb;
1850
1851                 /* there is not actually a write pending so let
1852                 this handle go free and allow it to
1853                 be closable if needed */
1854                 atomic_dec(&open_file->wrtPending);
1855
1856                 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
1857                 if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) {
1858                         /* since no page cache to corrupt on directio 
1859                         we can change size safely */
1860                         return 1;
1861                 }
1862
1863                 return 0;
1864         } else
1865                 return 1;
1866 }
1867
1868 static int cifs_prepare_write(struct file *file, struct page *page,
1869         unsigned from, unsigned to)
1870 {
1871         int rc = 0;
1872         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1873         cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1874         if (!PageUptodate(page)) {
1875         /*      if (to - from != PAGE_CACHE_SIZE) {
1876                         void *kaddr = kmap_atomic(page, KM_USER0);
1877                         memset(kaddr, 0, from);
1878                         memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1879                         flush_dcache_page(page);
1880                         kunmap_atomic(kaddr, KM_USER0);
1881                 } */
1882                 /* If we are writing a full page it will be up to date,
1883                    no need to read from the server */
1884                 if ((to == PAGE_CACHE_SIZE) && (from == 0))
1885                         SetPageUptodate(page);
1886
1887                 /* might as well read a page, it is fast enough */
1888                 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
1889                         rc = cifs_readpage_worker(file, page, &offset);
1890                 } else {
1891                 /* should we try using another file handle if there is one -
1892                    how would we lock it to prevent close of that handle
1893                    racing with this read?
1894                    In any case this will be written out by commit_write */
1895                 }
1896         }
1897
1898         /* BB should we pass any errors back? 
1899            e.g. if we do not have read access to the file */
1900         return 0;
1901 }
1902
1903 struct address_space_operations cifs_addr_ops = {
1904         .readpage = cifs_readpage,
1905         .readpages = cifs_readpages,
1906         .writepage = cifs_writepage,
1907         .writepages = cifs_writepages,
1908         .prepare_write = cifs_prepare_write,
1909         .commit_write = cifs_commit_write,
1910         .set_page_dirty = __set_page_dirty_nobuffers,
1911         /* .sync_page = cifs_sync_page, */
1912         /* .direct_IO = */
1913 };