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