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