[PATCH] cifs: ->readpages() fixes
[platform/adaptation/renesas_rcar/renesas_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/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         init_MUTEX(&private_data->lock_sem);
51         INIT_LIST_HEAD(&private_data->llist);
52         private_data->pfile = file; /* needed for writepage */
53         private_data->pInode = inode;
54         private_data->invalidHandle = FALSE;
55         private_data->closePend = FALSE;
56         /* we have to track num writers to the inode, since writepages
57         does not tell us which handle the write is for so there can
58         be a close (overlapping with write) of the filehandle that
59         cifs_writepages chose to use */
60         atomic_set(&private_data->wrtPending,0); 
61
62         return private_data;
63 }
64
65 static inline int cifs_convert_flags(unsigned int flags)
66 {
67         if ((flags & O_ACCMODE) == O_RDONLY)
68                 return GENERIC_READ;
69         else if ((flags & O_ACCMODE) == O_WRONLY)
70                 return GENERIC_WRITE;
71         else if ((flags & O_ACCMODE) == O_RDWR) {
72                 /* GENERIC_ALL is too much permission to request
73                    can cause unnecessary access denied on create */
74                 /* return GENERIC_ALL; */
75                 return (GENERIC_READ | GENERIC_WRITE);
76         }
77
78         return 0x20197;
79 }
80
81 static inline int cifs_get_disposition(unsigned int flags)
82 {
83         if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
84                 return FILE_CREATE;
85         else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
86                 return FILE_OVERWRITE_IF;
87         else if ((flags & O_CREAT) == O_CREAT)
88                 return FILE_OPEN_IF;
89         else if ((flags & O_TRUNC) == O_TRUNC)
90                 return FILE_OVERWRITE;
91         else
92                 return FILE_OPEN;
93 }
94
95 /* all arguments to this function must be checked for validity in caller */
96 static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
97         struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
98         struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
99         char *full_path, int xid)
100 {
101         struct timespec temp;
102         int rc;
103
104         /* want handles we can use to read with first
105            in the list so we do not have to walk the
106            list to search for one in prepare_write */
107         if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
108                 list_add_tail(&pCifsFile->flist, 
109                               &pCifsInode->openFileList);
110         } else {
111                 list_add(&pCifsFile->flist,
112                          &pCifsInode->openFileList);
113         }
114         write_unlock(&GlobalSMBSeslock);
115         if (pCifsInode->clientCanCacheRead) {
116                 /* we have the inode open somewhere else
117                    no need to discard cache data */
118                 goto client_can_cache;
119         }
120
121         /* BB need same check in cifs_create too? */
122         /* if not oplocked, invalidate inode pages if mtime or file
123            size changed */
124         temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
125         if (timespec_equal(&file->f_dentry->d_inode->i_mtime, &temp) && 
126                            (file->f_dentry->d_inode->i_size == 
127                             (loff_t)le64_to_cpu(buf->EndOfFile))) {
128                 cFYI(1, ("inode unchanged on server"));
129         } else {
130                 if (file->f_dentry->d_inode->i_mapping) {
131                 /* BB no need to lock inode until after invalidate
132                    since namei code should already have it locked? */
133                         filemap_write_and_wait(file->f_dentry->d_inode->i_mapping);
134                 }
135                 cFYI(1, ("invalidating remote inode since open detected it "
136                          "changed"));
137                 invalidate_remote_inode(file->f_dentry->d_inode);
138         }
139
140 client_can_cache:
141         if (pTcon->ses->capabilities & CAP_UNIX)
142                 rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
143                         full_path, inode->i_sb, xid);
144         else
145                 rc = cifs_get_inode_info(&file->f_dentry->d_inode,
146                         full_path, buf, inode->i_sb, xid);
147
148         if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
149                 pCifsInode->clientCanCacheAll = TRUE;
150                 pCifsInode->clientCanCacheRead = TRUE;
151                 cFYI(1, ("Exclusive Oplock granted on inode %p",
152                          file->f_dentry->d_inode));
153         } else if ((*oplock & 0xF) == OPLOCK_READ)
154                 pCifsInode->clientCanCacheRead = TRUE;
155
156         return rc;
157 }
158
159 int cifs_open(struct inode *inode, struct file *file)
160 {
161         int rc = -EACCES;
162         int xid, oplock;
163         struct cifs_sb_info *cifs_sb;
164         struct cifsTconInfo *pTcon;
165         struct cifsFileInfo *pCifsFile;
166         struct cifsInodeInfo *pCifsInode;
167         struct list_head *tmp;
168         char *full_path = NULL;
169         int desiredAccess;
170         int disposition;
171         __u16 netfid;
172         FILE_ALL_INFO *buf = NULL;
173
174         xid = GetXid();
175
176         cifs_sb = CIFS_SB(inode->i_sb);
177         pTcon = cifs_sb->tcon;
178
179         if (file->f_flags & O_CREAT) {
180                 /* search inode for this file and fill in file->private_data */
181                 pCifsInode = CIFS_I(file->f_dentry->d_inode);
182                 read_lock(&GlobalSMBSeslock);
183                 list_for_each(tmp, &pCifsInode->openFileList) {
184                         pCifsFile = list_entry(tmp, struct cifsFileInfo,
185                                                flist);
186                         if ((pCifsFile->pfile == NULL) &&
187                             (pCifsFile->pid == current->tgid)) {
188                                 /* mode set in cifs_create */
189
190                                 /* needed for writepage */
191                                 pCifsFile->pfile = file;
192                                 
193                                 file->private_data = pCifsFile;
194                                 break;
195                         }
196                 }
197                 read_unlock(&GlobalSMBSeslock);
198                 if (file->private_data != NULL) {
199                         rc = 0;
200                         FreeXid(xid);
201                         return rc;
202                 } else {
203                         if (file->f_flags & O_EXCL)
204                                 cERROR(1, ("could not find file instance for "
205                                            "new file %p", file));
206                 }
207         }
208
209         full_path = build_path_from_dentry(file->f_dentry);
210         if (full_path == NULL) {
211                 FreeXid(xid);
212                 return -ENOMEM;
213         }
214
215         cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
216                  inode, file->f_flags, full_path));
217         desiredAccess = cifs_convert_flags(file->f_flags);
218
219 /*********************************************************************
220  *  open flag mapping table:
221  *  
222  *      POSIX Flag            CIFS Disposition
223  *      ----------            ---------------- 
224  *      O_CREAT               FILE_OPEN_IF
225  *      O_CREAT | O_EXCL      FILE_CREATE
226  *      O_CREAT | O_TRUNC     FILE_OVERWRITE_IF
227  *      O_TRUNC               FILE_OVERWRITE
228  *      none of the above     FILE_OPEN
229  *
230  *      Note that there is not a direct match between disposition
231  *      FILE_SUPERSEDE (ie create whether or not file exists although 
232  *      O_CREAT | O_TRUNC is similar but truncates the existing
233  *      file rather than creating a new file as FILE_SUPERSEDE does
234  *      (which uses the attributes / metadata passed in on open call)
235  *?
236  *?  O_SYNC is a reasonable match to CIFS writethrough flag  
237  *?  and the read write flags match reasonably.  O_LARGEFILE
238  *?  is irrelevant because largefile support is always used
239  *?  by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
240  *       O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
241  *********************************************************************/
242
243         disposition = cifs_get_disposition(file->f_flags);
244
245         if (oplockEnabled)
246                 oplock = REQ_OPLOCK;
247         else
248                 oplock = FALSE;
249
250         /* BB pass O_SYNC flag through on file attributes .. BB */
251
252         /* Also refresh inode by passing in file_info buf returned by SMBOpen
253            and calling get_inode_info with returned buf (at least helps
254            non-Unix server case) */
255
256         /* BB we can not do this if this is the second open of a file 
257            and the first handle has writebehind data, we might be 
258            able to simply do a filemap_fdatawrite/filemap_fdatawait first */
259         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
260         if (!buf) {
261                 rc = -ENOMEM;
262                 goto out;
263         }
264
265         if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
266                 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, 
267                          desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
268                          cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
269                                  & CIFS_MOUNT_MAP_SPECIAL_CHR);
270         else
271                 rc = -EIO; /* no NT SMB support fall into legacy open below */
272
273         if (rc == -EIO) {
274                 /* Old server, try legacy style OpenX */
275                 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
276                         desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
277                         cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
278                                 & CIFS_MOUNT_MAP_SPECIAL_CHR);
279         }
280         if (rc) {
281                 cFYI(1, ("cifs_open returned 0x%x", rc));
282                 goto out;
283         }
284         file->private_data =
285                 kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
286         if (file->private_data == NULL) {
287                 rc = -ENOMEM;
288                 goto out;
289         }
290         pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
291         write_lock(&GlobalSMBSeslock);
292         list_add(&pCifsFile->tlist, &pTcon->openFileList);
293
294         pCifsInode = CIFS_I(file->f_dentry->d_inode);
295         if (pCifsInode) {
296                 rc = cifs_open_inode_helper(inode, file, pCifsInode,
297                                             pCifsFile, pTcon,
298                                             &oplock, buf, full_path, xid);
299         } else {
300                 write_unlock(&GlobalSMBSeslock);
301         }
302
303         if (oplock & CIFS_CREATE_ACTION) {           
304                 /* time to set mode which we can not set earlier due to
305                    problems creating new read-only files */
306                 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
307                         CIFSSMBUnixSetPerms(xid, pTcon, full_path,
308                                             inode->i_mode,
309                                             (__u64)-1, (__u64)-1, 0 /* dev */,
310                                             cifs_sb->local_nls,
311                                             cifs_sb->mnt_cifs_flags & 
312                                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
313                 } else {
314                         /* BB implement via Windows security descriptors eg
315                            CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
316                                               -1, -1, local_nls);
317                            in the meantime could set r/o dos attribute when
318                            perms are eg: mode & 0222 == 0 */
319                 }
320         }
321
322 out:
323         kfree(buf);
324         kfree(full_path);
325         FreeXid(xid);
326         return rc;
327 }
328
329 /* Try to reacquire byte range locks that were released when session */
330 /* to server was lost */
331 static int cifs_relock_file(struct cifsFileInfo *cifsFile)
332 {
333         int rc = 0;
334
335 /* BB list all locks open on this file and relock */
336
337         return rc;
338 }
339
340 static int cifs_reopen_file(struct inode *inode, struct file *file, 
341         int can_flush)
342 {
343         int rc = -EACCES;
344         int xid, oplock;
345         struct cifs_sb_info *cifs_sb;
346         struct cifsTconInfo *pTcon;
347         struct cifsFileInfo *pCifsFile;
348         struct cifsInodeInfo *pCifsInode;
349         char *full_path = NULL;
350         int desiredAccess;
351         int disposition = FILE_OPEN;
352         __u16 netfid;
353
354         if (inode == NULL)
355                 return -EBADF;
356         if (file->private_data) {
357                 pCifsFile = (struct cifsFileInfo *)file->private_data;
358         } else
359                 return -EBADF;
360
361         xid = GetXid();
362         down(&pCifsFile->fh_sem);
363         if (pCifsFile->invalidHandle == FALSE) {
364                 up(&pCifsFile->fh_sem);
365                 FreeXid(xid);
366                 return 0;
367         }
368
369         if (file->f_dentry == NULL) {
370                 up(&pCifsFile->fh_sem);
371                 cFYI(1, ("failed file reopen, no valid name if dentry freed"));
372                 FreeXid(xid);
373                 return -EBADF;
374         }
375         cifs_sb = CIFS_SB(inode->i_sb);
376         pTcon = cifs_sb->tcon;
377 /* can not grab rename sem here because various ops, including
378    those that already have the rename sem can end up causing writepage
379    to get called and if the server was down that means we end up here,
380    and we can never tell if the caller already has the rename_sem */
381         full_path = build_path_from_dentry(file->f_dentry);
382         if (full_path == NULL) {
383                 up(&pCifsFile->fh_sem);
384                 FreeXid(xid);
385                 return -ENOMEM;
386         }
387
388         cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
389                  inode, file->f_flags,full_path));
390         desiredAccess = cifs_convert_flags(file->f_flags);
391
392         if (oplockEnabled)
393                 oplock = REQ_OPLOCK;
394         else
395                 oplock = FALSE;
396
397         /* Can not refresh inode by passing in file_info buf to be returned
398            by SMBOpen and then calling get_inode_info with returned buf 
399            since file might have write behind data that needs to be flushed 
400            and server version of file size can be stale. If we knew for sure
401            that inode was not dirty locally we could do this */
402
403 /*      buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
404         if (buf == 0) {
405                 up(&pCifsFile->fh_sem);
406                 kfree(full_path);
407                 FreeXid(xid);
408                 return -ENOMEM;
409         } */
410         rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
411                          CREATE_NOT_DIR, &netfid, &oplock, NULL,
412                          cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 
413                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
414         if (rc) {
415                 up(&pCifsFile->fh_sem);
416                 cFYI(1, ("cifs_open returned 0x%x", rc));
417                 cFYI(1, ("oplock: %d", oplock));
418         } else {
419                 pCifsFile->netfid = netfid;
420                 pCifsFile->invalidHandle = FALSE;
421                 up(&pCifsFile->fh_sem);
422                 pCifsInode = CIFS_I(inode);
423                 if (pCifsInode) {
424                         if (can_flush) {
425                                 filemap_write_and_wait(inode->i_mapping);
426                         /* temporarily disable caching while we
427                            go to server to get inode info */
428                                 pCifsInode->clientCanCacheAll = FALSE;
429                                 pCifsInode->clientCanCacheRead = FALSE;
430                                 if (pTcon->ses->capabilities & CAP_UNIX)
431                                         rc = cifs_get_inode_info_unix(&inode,
432                                                 full_path, inode->i_sb, xid);
433                                 else
434                                         rc = cifs_get_inode_info(&inode,
435                                                 full_path, NULL, inode->i_sb,
436                                                 xid);
437                         } /* else we are writing out data to server already
438                              and could deadlock if we tried to flush data, and
439                              since we do not know if we have data that would
440                              invalidate the current end of file on the server
441                              we can not go to the server to get the new inod
442                              info */
443                         if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
444                                 pCifsInode->clientCanCacheAll = TRUE;
445                                 pCifsInode->clientCanCacheRead = TRUE;
446                                 cFYI(1, ("Exclusive Oplock granted on inode %p",
447                                          file->f_dentry->d_inode));
448                         } else if ((oplock & 0xF) == OPLOCK_READ) {
449                                 pCifsInode->clientCanCacheRead = TRUE;
450                                 pCifsInode->clientCanCacheAll = FALSE;
451                         } else {
452                                 pCifsInode->clientCanCacheRead = FALSE;
453                                 pCifsInode->clientCanCacheAll = FALSE;
454                         }
455                         cifs_relock_file(pCifsFile);
456                 }
457         }
458
459         kfree(full_path);
460         FreeXid(xid);
461         return rc;
462 }
463
464 int cifs_close(struct inode *inode, struct file *file)
465 {
466         int rc = 0;
467         int xid;
468         struct cifs_sb_info *cifs_sb;
469         struct cifsTconInfo *pTcon;
470         struct cifsFileInfo *pSMBFile =
471                 (struct cifsFileInfo *)file->private_data;
472
473         xid = GetXid();
474
475         cifs_sb = CIFS_SB(inode->i_sb);
476         pTcon = cifs_sb->tcon;
477         if (pSMBFile) {
478                 struct cifsLockInfo *li, *tmp;
479
480                 pSMBFile->closePend = TRUE;
481                 if (pTcon) {
482                         /* no sense reconnecting to close a file that is
483                            already closed */
484                         if (pTcon->tidStatus != CifsNeedReconnect) {
485                                 int timeout = 2;
486                                 while((atomic_read(&pSMBFile->wrtPending) != 0)
487                                          && (timeout < 1000) ) {
488                                         /* Give write a better chance to get to
489                                         server ahead of the close.  We do not
490                                         want to add a wait_q here as it would
491                                         increase the memory utilization as
492                                         the struct would be in each open file,
493                                         but this should give enough time to 
494                                         clear the socket */
495                                         cERROR(1,("close with pending writes"));
496                                         msleep(timeout);
497                                         timeout *= 4;
498                                 } 
499                                 rc = CIFSSMBClose(xid, pTcon,
500                                                   pSMBFile->netfid);
501                         }
502                 }
503
504                 /* Delete any outstanding lock records.
505                    We'll lose them when the file is closed anyway. */
506                 down(&pSMBFile->lock_sem);
507                 list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) {
508                         list_del(&li->llist);
509                         kfree(li);
510                 }
511                 up(&pSMBFile->lock_sem);
512
513                 write_lock(&GlobalSMBSeslock);
514                 list_del(&pSMBFile->flist);
515                 list_del(&pSMBFile->tlist);
516                 write_unlock(&GlobalSMBSeslock);
517                 kfree(pSMBFile->search_resume_name);
518                 kfree(file->private_data);
519                 file->private_data = NULL;
520         } else
521                 rc = -EBADF;
522
523         if (list_empty(&(CIFS_I(inode)->openFileList))) {
524                 cFYI(1, ("closing last open instance for inode %p", inode));
525                 /* if the file is not open we do not know if we can cache info
526                    on this inode, much less write behind and read ahead */
527                 CIFS_I(inode)->clientCanCacheRead = FALSE;
528                 CIFS_I(inode)->clientCanCacheAll  = FALSE;
529         }
530         if ((rc ==0) && CIFS_I(inode)->write_behind_rc)
531                 rc = CIFS_I(inode)->write_behind_rc;
532         FreeXid(xid);
533         return rc;
534 }
535
536 int cifs_closedir(struct inode *inode, struct file *file)
537 {
538         int rc = 0;
539         int xid;
540         struct cifsFileInfo *pCFileStruct =
541             (struct cifsFileInfo *)file->private_data;
542         char *ptmp;
543
544         cFYI(1, ("Closedir inode = 0x%p", inode));
545
546         xid = GetXid();
547
548         if (pCFileStruct) {
549                 struct cifsTconInfo *pTcon;
550                 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_dentry->d_sb);
551
552                 pTcon = cifs_sb->tcon;
553
554                 cFYI(1, ("Freeing private data in close dir"));
555                 if ((pCFileStruct->srch_inf.endOfSearch == FALSE) &&
556                    (pCFileStruct->invalidHandle == FALSE)) {
557                         pCFileStruct->invalidHandle = TRUE;
558                         rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
559                         cFYI(1, ("Closing uncompleted readdir with rc %d",
560                                  rc));
561                         /* not much we can do if it fails anyway, ignore rc */
562                         rc = 0;
563                 }
564                 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
565                 if (ptmp) {
566                         cFYI(1, ("closedir free smb buf in srch struct"));
567                         pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
568                         if(pCFileStruct->srch_inf.smallBuf)
569                                 cifs_small_buf_release(ptmp);
570                         else
571                                 cifs_buf_release(ptmp);
572                 }
573                 ptmp = pCFileStruct->search_resume_name;
574                 if (ptmp) {
575                         cFYI(1, ("closedir free resume name"));
576                         pCFileStruct->search_resume_name = NULL;
577                         kfree(ptmp);
578                 }
579                 kfree(file->private_data);
580                 file->private_data = NULL;
581         }
582         /* BB can we lock the filestruct while this is going on? */
583         FreeXid(xid);
584         return rc;
585 }
586
587 static int store_file_lock(struct cifsFileInfo *fid, __u64 len,
588                                 __u64 offset, __u8 lockType)
589 {
590         struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL);
591         if (li == NULL)
592                 return -ENOMEM;
593         li->offset = offset;
594         li->length = len;
595         li->type = lockType;
596         down(&fid->lock_sem);
597         list_add(&li->llist, &fid->llist);
598         up(&fid->lock_sem);
599         return 0;
600 }
601
602 int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
603 {
604         int rc, xid;
605         __u32 numLock = 0;
606         __u32 numUnlock = 0;
607         __u64 length;
608         int wait_flag = FALSE;
609         struct cifs_sb_info *cifs_sb;
610         struct cifsTconInfo *pTcon;
611         __u16 netfid;
612         __u8 lockType = LOCKING_ANDX_LARGE_FILES;
613         int posix_locking;
614
615         length = 1 + pfLock->fl_end - pfLock->fl_start;
616         rc = -EACCES;
617         xid = GetXid();
618
619         cFYI(1, ("Lock parm: 0x%x flockflags: "
620                  "0x%x flocktype: 0x%x start: %lld end: %lld",
621                 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
622                 pfLock->fl_end));
623
624         if (pfLock->fl_flags & FL_POSIX)
625                 cFYI(1, ("Posix"));
626         if (pfLock->fl_flags & FL_FLOCK)
627                 cFYI(1, ("Flock"));
628         if (pfLock->fl_flags & FL_SLEEP) {
629                 cFYI(1, ("Blocking lock"));
630                 wait_flag = TRUE;
631         }
632         if (pfLock->fl_flags & FL_ACCESS)
633                 cFYI(1, ("Process suspended by mandatory locking - "
634                          "not implemented yet"));
635         if (pfLock->fl_flags & FL_LEASE)
636                 cFYI(1, ("Lease on file - not implemented yet"));
637         if (pfLock->fl_flags & 
638             (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
639                 cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags));
640
641         if (pfLock->fl_type == F_WRLCK) {
642                 cFYI(1, ("F_WRLCK "));
643                 numLock = 1;
644         } else if (pfLock->fl_type == F_UNLCK) {
645                 cFYI(1, ("F_UNLCK"));
646                 numUnlock = 1;
647                 /* Check if unlock includes more than
648                 one lock range */
649         } else if (pfLock->fl_type == F_RDLCK) {
650                 cFYI(1, ("F_RDLCK"));
651                 lockType |= LOCKING_ANDX_SHARED_LOCK;
652                 numLock = 1;
653         } else if (pfLock->fl_type == F_EXLCK) {
654                 cFYI(1, ("F_EXLCK"));
655                 numLock = 1;
656         } else if (pfLock->fl_type == F_SHLCK) {
657                 cFYI(1, ("F_SHLCK"));
658                 lockType |= LOCKING_ANDX_SHARED_LOCK;
659                 numLock = 1;
660         } else
661                 cFYI(1, ("Unknown type of lock"));
662
663         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
664         pTcon = cifs_sb->tcon;
665
666         if (file->private_data == NULL) {
667                 FreeXid(xid);
668                 return -EBADF;
669         }
670         netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
671
672         posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
673                         (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability));
674
675         /* BB add code here to normalize offset and length to
676         account for negative length which we can not accept over the
677         wire */
678         if (IS_GETLK(cmd)) {
679                 if(posix_locking) {
680                         int posix_lock_type;
681                         if(lockType & LOCKING_ANDX_SHARED_LOCK)
682                                 posix_lock_type = CIFS_RDLCK;
683                         else
684                                 posix_lock_type = CIFS_WRLCK;
685                         rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */,
686                                         length, pfLock,
687                                         posix_lock_type, wait_flag);
688                         FreeXid(xid);
689                         return rc;
690                 }
691
692                 /* BB we could chain these into one lock request BB */
693                 rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
694                                  0, 1, lockType, 0 /* wait flag */ );
695                 if (rc == 0) {
696                         rc = CIFSSMBLock(xid, pTcon, netfid, length, 
697                                          pfLock->fl_start, 1 /* numUnlock */ ,
698                                          0 /* numLock */ , lockType,
699                                          0 /* wait flag */ );
700                         pfLock->fl_type = F_UNLCK;
701                         if (rc != 0)
702                                 cERROR(1, ("Error unlocking previously locked "
703                                            "range %d during test of lock", rc));
704                         rc = 0;
705
706                 } else {
707                         /* if rc == ERR_SHARING_VIOLATION ? */
708                         rc = 0; /* do not change lock type to unlock
709                                    since range in use */
710                 }
711
712                 FreeXid(xid);
713                 return rc;
714         }
715
716         if (!numLock && !numUnlock) {
717                 /* if no lock or unlock then nothing
718                 to do since we do not know what it is */
719                 FreeXid(xid);
720                 return -EOPNOTSUPP;
721         }
722
723         if (posix_locking) {
724                 int posix_lock_type;
725                 if(lockType & LOCKING_ANDX_SHARED_LOCK)
726                         posix_lock_type = CIFS_RDLCK;
727                 else
728                         posix_lock_type = CIFS_WRLCK;
729                 
730                 if(numUnlock == 1)
731                         posix_lock_type = CIFS_UNLCK;
732
733                 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
734                                       length, pfLock,
735                                       posix_lock_type, wait_flag);
736         } else {
737                 struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data;
738
739                 if (numLock) {
740                         rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
741                                         0, numLock, lockType, wait_flag);
742
743                         if (rc == 0) {
744                                 /* For Windows locks we must store them. */
745                                 rc = store_file_lock(fid, length,
746                                                 pfLock->fl_start, lockType);
747                         }
748                 } else if (numUnlock) {
749                         /* For each stored lock that this unlock overlaps
750                            completely, unlock it. */
751                         int stored_rc = 0;
752                         struct cifsLockInfo *li, *tmp;
753
754                         rc = 0;
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                         break;
1810                 } else if (bytes_read > 0) {
1811                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1812                         cifs_copy_cache_pages(mapping, page_list, bytes_read,
1813                                 smb_read_data + 4 /* RFC1001 hdr */ +
1814                                 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1815
1816                         i +=  bytes_read >> PAGE_CACHE_SHIFT;
1817                         cifs_stats_bytes_read(pTcon, bytes_read);
1818                         if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1819                                 i++; /* account for partial page */
1820
1821                                 /* server copy of file can have smaller size 
1822                                    than client */
1823                                 /* BB do we need to verify this common case ? 
1824                                    this case is ok - if we are at server EOF 
1825                                    we will hit it on next read */
1826
1827                                 /* break; */
1828                         }
1829                 } else {
1830                         cFYI(1, ("No bytes read (%d) at offset %lld . "
1831                                  "Cleaning remaining pages from readahead list",
1832                                  bytes_read, offset));
1833                         /* BB turn off caching and do new lookup on 
1834                            file size at server? */
1835                         break;
1836                 }
1837                 if (smb_read_data) {
1838                         if(buf_type == CIFS_SMALL_BUFFER)
1839                                 cifs_small_buf_release(smb_read_data);
1840                         else if(buf_type == CIFS_LARGE_BUFFER)
1841                                 cifs_buf_release(smb_read_data);
1842                         smb_read_data = NULL;
1843                 }
1844                 bytes_read = 0;
1845         }
1846
1847         pagevec_lru_add(&lru_pvec);
1848
1849 /* need to free smb_read_data buf before exit */
1850         if (smb_read_data) {
1851                 if(buf_type == CIFS_SMALL_BUFFER)
1852                         cifs_small_buf_release(smb_read_data);
1853                 else if(buf_type == CIFS_LARGE_BUFFER)
1854                         cifs_buf_release(smb_read_data);
1855                 smb_read_data = NULL;
1856         } 
1857
1858         FreeXid(xid);
1859         return rc;
1860 }
1861
1862 static int cifs_readpage_worker(struct file *file, struct page *page,
1863         loff_t *poffset)
1864 {
1865         char *read_data;
1866         int rc;
1867
1868         page_cache_get(page);
1869         read_data = kmap(page);
1870         /* for reads over a certain size could initiate async read ahead */
1871                                                                                                                            
1872         rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1873                                                                                                                            
1874         if (rc < 0)
1875                 goto io_error;
1876         else
1877                 cFYI(1, ("Bytes read %d",rc));
1878                                                                                                                            
1879         file->f_dentry->d_inode->i_atime =
1880                 current_fs_time(file->f_dentry->d_inode->i_sb);
1881                                                                                                                            
1882         if (PAGE_CACHE_SIZE > rc)
1883                 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
1884
1885         flush_dcache_page(page);
1886         SetPageUptodate(page);
1887         rc = 0;
1888                                                                                                                            
1889 io_error:
1890         kunmap(page);
1891         page_cache_release(page);
1892         return rc;
1893 }
1894
1895 static int cifs_readpage(struct file *file, struct page *page)
1896 {
1897         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1898         int rc = -EACCES;
1899         int xid;
1900
1901         xid = GetXid();
1902
1903         if (file->private_data == NULL) {
1904                 FreeXid(xid);
1905                 return -EBADF;
1906         }
1907
1908         cFYI(1, ("readpage %p at offset %d 0x%x\n", 
1909                  page, (int)offset, (int)offset));
1910
1911         rc = cifs_readpage_worker(file, page, &offset);
1912
1913         unlock_page(page);
1914
1915         FreeXid(xid);
1916         return rc;
1917 }
1918
1919 /* We do not want to update the file size from server for inodes
1920    open for write - to avoid races with writepage extending
1921    the file - in the future we could consider allowing
1922    refreshing the inode only on increases in the file size 
1923    but this is tricky to do without racing with writebehind
1924    page caching in the current Linux kernel design */
1925 int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1926 {
1927         struct cifsFileInfo *open_file = NULL;
1928
1929         if (cifsInode)
1930                 open_file =  find_writable_file(cifsInode);
1931  
1932         if(open_file) {
1933                 struct cifs_sb_info *cifs_sb;
1934
1935                 /* there is not actually a write pending so let
1936                 this handle go free and allow it to
1937                 be closable if needed */
1938                 atomic_dec(&open_file->wrtPending);
1939
1940                 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
1941                 if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) {
1942                         /* since no page cache to corrupt on directio 
1943                         we can change size safely */
1944                         return 1;
1945                 }
1946
1947                 return 0;
1948         } else
1949                 return 1;
1950 }
1951
1952 static int cifs_prepare_write(struct file *file, struct page *page,
1953         unsigned from, unsigned to)
1954 {
1955         int rc = 0;
1956         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1957         cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1958         if (!PageUptodate(page)) {
1959         /*      if (to - from != PAGE_CACHE_SIZE) {
1960                         void *kaddr = kmap_atomic(page, KM_USER0);
1961                         memset(kaddr, 0, from);
1962                         memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1963                         flush_dcache_page(page);
1964                         kunmap_atomic(kaddr, KM_USER0);
1965                 } */
1966                 /* If we are writing a full page it will be up to date,
1967                    no need to read from the server */
1968                 if ((to == PAGE_CACHE_SIZE) && (from == 0))
1969                         SetPageUptodate(page);
1970
1971                 /* might as well read a page, it is fast enough */
1972                 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
1973                         rc = cifs_readpage_worker(file, page, &offset);
1974                 } else {
1975                 /* should we try using another file handle if there is one -
1976                    how would we lock it to prevent close of that handle
1977                    racing with this read?
1978                    In any case this will be written out by commit_write */
1979                 }
1980         }
1981
1982         /* BB should we pass any errors back? 
1983            e.g. if we do not have read access to the file */
1984         return 0;
1985 }
1986
1987 const struct address_space_operations cifs_addr_ops = {
1988         .readpage = cifs_readpage,
1989         .readpages = cifs_readpages,
1990         .writepage = cifs_writepage,
1991         .writepages = cifs_writepages,
1992         .prepare_write = cifs_prepare_write,
1993         .commit_write = cifs_commit_write,
1994         .set_page_dirty = __set_page_dirty_nobuffers,
1995         /* .sync_page = cifs_sync_page, */
1996         /* .direct_IO = */
1997 };
1998
1999 /*
2000  * cifs_readpages requires the server to support a buffer large enough to
2001  * contain the header plus one complete page of data.  Otherwise, we need
2002  * to leave cifs_readpages out of the address space operations.
2003  */
2004 const struct address_space_operations cifs_addr_ops_smallbuf = {
2005         .readpage = cifs_readpage,
2006         .writepage = cifs_writepage,
2007         .writepages = cifs_writepages,
2008         .prepare_write = cifs_prepare_write,
2009         .commit_write = cifs_commit_write,
2010         .set_page_dirty = __set_page_dirty_nobuffers,
2011         /* .sync_page = cifs_sync_page, */
2012         /* .direct_IO = */
2013 };