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