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