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