Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-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 if ((flags & O_TRUNC) == O_TRUNC)
88                 return FILE_OVERWRITE;
89         else
90                 return FILE_OPEN;
91 }
92
93 /* all arguments to this function must be checked for validity in caller */
94 static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
95         struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
96         struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
97         char *full_path, int xid)
98 {
99         struct timespec temp;
100         int rc;
101
102         /* want handles we can use to read with first
103            in the list so we do not have to walk the
104            list to search for one in prepare_write */
105         if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
106                 list_add_tail(&pCifsFile->flist, 
107                               &pCifsInode->openFileList);
108         } else {
109                 list_add(&pCifsFile->flist,
110                          &pCifsInode->openFileList);
111         }
112         write_unlock(&GlobalSMBSeslock);
113         write_unlock(&file->f_owner.lock);
114         if (pCifsInode->clientCanCacheRead) {
115                 /* we have the inode open somewhere else
116                    no need to discard cache data */
117                 goto client_can_cache;
118         }
119
120         /* BB need same check in cifs_create too? */
121         /* if not oplocked, invalidate inode pages if mtime or file
122            size changed */
123         temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
124         if (timespec_equal(&file->f_dentry->d_inode->i_mtime, &temp) && 
125                            (file->f_dentry->d_inode->i_size == 
126                             (loff_t)le64_to_cpu(buf->EndOfFile))) {
127                 cFYI(1, ("inode unchanged on server"));
128         } else {
129                 if (file->f_dentry->d_inode->i_mapping) {
130                 /* BB no need to lock inode until after invalidate
131                    since namei code should already have it locked? */
132                         filemap_write_and_wait(file->f_dentry->d_inode->i_mapping);
133                 }
134                 cFYI(1, ("invalidating remote inode since open detected it "
135                          "changed"));
136                 invalidate_remote_inode(file->f_dentry->d_inode);
137         }
138
139 client_can_cache:
140         if (pTcon->ses->capabilities & CAP_UNIX)
141                 rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
142                         full_path, inode->i_sb, xid);
143         else
144                 rc = cifs_get_inode_info(&file->f_dentry->d_inode,
145                         full_path, buf, inode->i_sb, xid);
146
147         if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
148                 pCifsInode->clientCanCacheAll = TRUE;
149                 pCifsInode->clientCanCacheRead = TRUE;
150                 cFYI(1, ("Exclusive Oplock granted on inode %p",
151                          file->f_dentry->d_inode));
152         } else if ((*oplock & 0xF) == OPLOCK_READ)
153                 pCifsInode->clientCanCacheRead = TRUE;
154
155         return rc;
156 }
157
158 int cifs_open(struct inode *inode, struct file *file)
159 {
160         int rc = -EACCES;
161         int xid, oplock;
162         struct cifs_sb_info *cifs_sb;
163         struct cifsTconInfo *pTcon;
164         struct cifsFileInfo *pCifsFile;
165         struct cifsInodeInfo *pCifsInode;
166         struct list_head *tmp;
167         char *full_path = NULL;
168         int desiredAccess;
169         int disposition;
170         __u16 netfid;
171         FILE_ALL_INFO *buf = NULL;
172
173         xid = GetXid();
174
175         cifs_sb = CIFS_SB(inode->i_sb);
176         pTcon = cifs_sb->tcon;
177
178         if (file->f_flags & O_CREAT) {
179                 /* search inode for this file and fill in file->private_data */
180                 pCifsInode = CIFS_I(file->f_dentry->d_inode);
181                 read_lock(&GlobalSMBSeslock);
182                 list_for_each(tmp, &pCifsInode->openFileList) {
183                         pCifsFile = list_entry(tmp, struct cifsFileInfo,
184                                                flist);
185                         if ((pCifsFile->pfile == NULL) &&
186                             (pCifsFile->pid == current->tgid)) {
187                                 /* mode set in cifs_create */
188
189                                 /* needed for writepage */
190                                 pCifsFile->pfile = file;
191                                 
192                                 file->private_data = pCifsFile;
193                                 break;
194                         }
195                 }
196                 read_unlock(&GlobalSMBSeslock);
197                 if (file->private_data != NULL) {
198                         rc = 0;
199                         FreeXid(xid);
200                         return rc;
201                 } else {
202                         if (file->f_flags & O_EXCL)
203                                 cERROR(1, ("could not find file instance for "
204                                            "new file %p ", file));
205                 }
206         }
207
208         full_path = build_path_from_dentry(file->f_dentry);
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,
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,
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                         if(experimEnabled || (pTcon->ses->server &&
910                                 ((pTcon->ses->server->secMode & 
911                                 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
912                                 == 0))) {
913                                 struct kvec iov[2];
914                                 unsigned int len;
915
916                                 len = min((size_t)cifs_sb->wsize,
917                                           write_size - total_written);
918                                 /* iov[0] is reserved for smb header */
919                                 iov[1].iov_base = (char *)write_data +
920                                                   total_written;
921                                 iov[1].iov_len = len;
922                                 rc = CIFSSMBWrite2(xid, pTcon,
923                                                 open_file->netfid, len,
924                                                 *poffset, &bytes_written,
925                                                 iov, 1, long_op);
926                         } else
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,
933                                          NULL, long_op);
934                 }
935                 if (rc || (bytes_written == 0)) {
936                         if (total_written)
937                                 break;
938                         else {
939                                 FreeXid(xid);
940                                 return rc;
941                         }
942                 } else
943                         *poffset += bytes_written;
944                 long_op = FALSE; /* subsequent writes fast - 
945                                     15 seconds is plenty */
946         }
947
948         cifs_stats_bytes_written(pTcon, total_written);
949
950         /* since the write may have blocked check these pointers again */
951         if (file->f_dentry) {
952                 if (file->f_dentry->d_inode) {
953                         file->f_dentry->d_inode->i_ctime = 
954                         file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
955                         if (total_written > 0) {
956                                 if (*poffset > file->f_dentry->d_inode->i_size)
957                                         i_size_write(file->f_dentry->d_inode, 
958                                                      *poffset);
959                         }
960                         mark_inode_dirty_sync(file->f_dentry->d_inode);
961                 }
962         }
963         FreeXid(xid);
964         return total_written;
965 }
966
967 struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
968 {
969         struct cifsFileInfo *open_file;
970         int rc;
971
972         /* Having a null inode here (because mapping->host was set to zero by
973         the VFS or MM) should not happen but we had reports of on oops (due to
974         it being zero) during stress testcases so we need to check for it */
975
976         if(cifs_inode == NULL) {
977                 cERROR(1,("Null inode passed to cifs_writeable_file"));
978                 dump_stack();
979                 return NULL;
980         }
981
982         read_lock(&GlobalSMBSeslock);
983         list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
984                 if (open_file->closePend)
985                         continue;
986                 if (open_file->pfile &&
987                     ((open_file->pfile->f_flags & O_RDWR) ||
988                      (open_file->pfile->f_flags & O_WRONLY))) {
989                         atomic_inc(&open_file->wrtPending);
990                         read_unlock(&GlobalSMBSeslock);
991                         if((open_file->invalidHandle) && 
992                            (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
993                                 rc = cifs_reopen_file(&cifs_inode->vfs_inode, 
994                                                       open_file->pfile, FALSE);
995                                 /* if it fails, try another handle - might be */
996                                 /* dangerous to hold up writepages with retry */
997                                 if(rc) {
998                                         cFYI(1,("failed on reopen file in wp"));
999                                         read_lock(&GlobalSMBSeslock);
1000                                         /* can not use this handle, no write
1001                                         pending on this one after all */
1002                                         atomic_dec
1003                                              (&open_file->wrtPending);
1004                                         continue;
1005                                 }
1006                         }
1007                         return open_file;
1008                 }
1009         }
1010         read_unlock(&GlobalSMBSeslock);
1011         return NULL;
1012 }
1013
1014 static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1015 {
1016         struct address_space *mapping = page->mapping;
1017         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1018         char *write_data;
1019         int rc = -EFAULT;
1020         int bytes_written = 0;
1021         struct cifs_sb_info *cifs_sb;
1022         struct cifsTconInfo *pTcon;
1023         struct inode *inode;
1024         struct cifsFileInfo *open_file;
1025
1026         if (!mapping || !mapping->host)
1027                 return -EFAULT;
1028
1029         inode = page->mapping->host;
1030         cifs_sb = CIFS_SB(inode->i_sb);
1031         pTcon = cifs_sb->tcon;
1032
1033         offset += (loff_t)from;
1034         write_data = kmap(page);
1035         write_data += from;
1036
1037         if ((to > PAGE_CACHE_SIZE) || (from > to)) {
1038                 kunmap(page);
1039                 return -EIO;
1040         }
1041
1042         /* racing with truncate? */
1043         if (offset > mapping->host->i_size) {
1044                 kunmap(page);
1045                 return 0; /* don't care */
1046         }
1047
1048         /* check to make sure that we are not extending the file */
1049         if (mapping->host->i_size - offset < (loff_t)to)
1050                 to = (unsigned)(mapping->host->i_size - offset); 
1051
1052         open_file = find_writable_file(CIFS_I(mapping->host));
1053         if (open_file) {
1054                 bytes_written = cifs_write(open_file->pfile, write_data,
1055                                            to-from, &offset);
1056                 atomic_dec(&open_file->wrtPending);
1057                 /* Does mm or vfs already set times? */
1058                 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
1059                 if ((bytes_written > 0) && (offset)) {
1060                         rc = 0;
1061                 } else if (bytes_written < 0) {
1062                         if (rc != -EBADF)
1063                                 rc = bytes_written;
1064                 }
1065         } else {
1066                 cFYI(1, ("No writeable filehandles for inode"));
1067                 rc = -EIO;
1068         }
1069
1070         kunmap(page);
1071         return rc;
1072 }
1073
1074 static int cifs_writepages(struct address_space *mapping,
1075                            struct writeback_control *wbc)
1076 {
1077         struct backing_dev_info *bdi = mapping->backing_dev_info;
1078         unsigned int bytes_to_write;
1079         unsigned int bytes_written;
1080         struct cifs_sb_info *cifs_sb;
1081         int done = 0;
1082         pgoff_t end;
1083         pgoff_t index;
1084         int range_whole = 0;
1085         struct kvec iov[32];
1086         int len;
1087         int n_iov = 0;
1088         pgoff_t next;
1089         int nr_pages;
1090         __u64 offset = 0;
1091         struct cifsFileInfo *open_file;
1092         struct page *page;
1093         struct pagevec pvec;
1094         int rc = 0;
1095         int scanned = 0;
1096         int xid;
1097
1098         cifs_sb = CIFS_SB(mapping->host->i_sb);
1099         
1100         /*
1101          * If wsize is smaller that the page cache size, default to writing
1102          * one page at a time via cifs_writepage
1103          */
1104         if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1105                 return generic_writepages(mapping, wbc);
1106
1107         if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
1108                 if(cifs_sb->tcon->ses->server->secMode &
1109                           (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1110                         if(!experimEnabled)
1111                                 return generic_writepages(mapping, wbc);
1112
1113         /*
1114          * BB: Is this meaningful for a non-block-device file system?
1115          * If it is, we should test it again after we do I/O
1116          */
1117         if (wbc->nonblocking && bdi_write_congested(bdi)) {
1118                 wbc->encountered_congestion = 1;
1119                 return 0;
1120         }
1121
1122         xid = GetXid();
1123
1124         pagevec_init(&pvec, 0);
1125         if (wbc->range_cyclic) {
1126                 index = mapping->writeback_index; /* Start from prev offset */
1127                 end = -1;
1128         } else {
1129                 index = wbc->range_start >> PAGE_CACHE_SHIFT;
1130                 end = wbc->range_end >> PAGE_CACHE_SHIFT;
1131                 if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
1132                         range_whole = 1;
1133                 scanned = 1;
1134         }
1135 retry:
1136         while (!done && (index <= end) &&
1137                (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
1138                         PAGECACHE_TAG_DIRTY,
1139                         min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1))) {
1140                 int first;
1141                 unsigned int i;
1142
1143                 first = -1;
1144                 next = 0;
1145                 n_iov = 0;
1146                 bytes_to_write = 0;
1147
1148                 for (i = 0; i < nr_pages; i++) {
1149                         page = pvec.pages[i];
1150                         /*
1151                          * At this point we hold neither mapping->tree_lock nor
1152                          * lock on the page itself: the page may be truncated or
1153                          * invalidated (changing page->mapping to NULL), or even
1154                          * swizzled back from swapper_space to tmpfs file
1155                          * mapping
1156                          */
1157
1158                         if (first < 0)
1159                                 lock_page(page);
1160                         else if (TestSetPageLocked(page))
1161                                 break;
1162
1163                         if (unlikely(page->mapping != mapping)) {
1164                                 unlock_page(page);
1165                                 break;
1166                         }
1167
1168                         if (!wbc->range_cyclic && page->index > end) {
1169                                 done = 1;
1170                                 unlock_page(page);
1171                                 break;
1172                         }
1173
1174                         if (next && (page->index != next)) {
1175                                 /* Not next consecutive page */
1176                                 unlock_page(page);
1177                                 break;
1178                         }
1179
1180                         if (wbc->sync_mode != WB_SYNC_NONE)
1181                                 wait_on_page_writeback(page);
1182
1183                         if (PageWriteback(page) ||
1184                                         !test_clear_page_dirty(page)) {
1185                                 unlock_page(page);
1186                                 break;
1187                         }
1188
1189                         if (page_offset(page) >= mapping->host->i_size) {
1190                                 done = 1;
1191                                 unlock_page(page);
1192                                 break;
1193                         }
1194
1195                         /*
1196                          * BB can we get rid of this?  pages are held by pvec
1197                          */
1198                         page_cache_get(page);
1199
1200                         len = min(mapping->host->i_size - page_offset(page),
1201                                   (loff_t)PAGE_CACHE_SIZE);
1202
1203                         /* reserve iov[0] for the smb header */
1204                         n_iov++;
1205                         iov[n_iov].iov_base = kmap(page);
1206                         iov[n_iov].iov_len = len;
1207                         bytes_to_write += len;
1208
1209                         if (first < 0) {
1210                                 first = i;
1211                                 offset = page_offset(page);
1212                         }
1213                         next = page->index + 1;
1214                         if (bytes_to_write + PAGE_CACHE_SIZE > cifs_sb->wsize)
1215                                 break;
1216                 }
1217                 if (n_iov) {
1218                         /* Search for a writable handle every time we call
1219                          * CIFSSMBWrite2.  We can't rely on the last handle
1220                          * we used to still be valid
1221                          */
1222                         open_file = find_writable_file(CIFS_I(mapping->host));
1223                         if (!open_file) {
1224                                 cERROR(1, ("No writable handles for inode"));
1225                                 rc = -EBADF;
1226                         } else {
1227                                 rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
1228                                                    open_file->netfid,
1229                                                    bytes_to_write, offset,
1230                                                    &bytes_written, iov, n_iov,
1231                                                    1);
1232                                 atomic_dec(&open_file->wrtPending);
1233                                 if (rc || bytes_written < bytes_to_write) {
1234                                         cERROR(1,("Write2 ret %d, written = %d",
1235                                                   rc, bytes_written));
1236                                         /* BB what if continued retry is
1237                                            requested via mount flags? */
1238                                         set_bit(AS_EIO, &mapping->flags);
1239                                 } else {
1240                                         cifs_stats_bytes_written(cifs_sb->tcon,
1241                                                                  bytes_written);
1242                                 }
1243                         }
1244                         for (i = 0; i < n_iov; i++) {
1245                                 page = pvec.pages[first + i];
1246                                 /* Should we also set page error on
1247                                 success rc but too little data written? */
1248                                 /* BB investigate retry logic on temporary
1249                                 server crash cases and how recovery works
1250                                 when page marked as error */ 
1251                                 if(rc)
1252                                         SetPageError(page);
1253                                 kunmap(page);
1254                                 unlock_page(page);
1255                                 page_cache_release(page);
1256                         }
1257                         if ((wbc->nr_to_write -= n_iov) <= 0)
1258                                 done = 1;
1259                         index = next;
1260                 }
1261                 pagevec_release(&pvec);
1262         }
1263         if (!scanned && !done) {
1264                 /*
1265                  * We hit the last page and there is more work to be done: wrap
1266                  * back to the start of the file
1267                  */
1268                 scanned = 1;
1269                 index = 0;
1270                 goto retry;
1271         }
1272         if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
1273                 mapping->writeback_index = index;
1274
1275         FreeXid(xid);
1276
1277         return rc;
1278 }
1279
1280 static int cifs_writepage(struct page* page, struct writeback_control *wbc)
1281 {
1282         int rc = -EFAULT;
1283         int xid;
1284
1285         xid = GetXid();
1286 /* BB add check for wbc flags */
1287         page_cache_get(page);
1288         if (!PageUptodate(page)) {
1289                 cFYI(1, ("ppw - page not up to date"));
1290         }
1291         
1292         rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
1293         SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
1294         unlock_page(page);
1295         page_cache_release(page);       
1296         FreeXid(xid);
1297         return rc;
1298 }
1299
1300 static int cifs_commit_write(struct file *file, struct page *page,
1301         unsigned offset, unsigned to)
1302 {
1303         int xid;
1304         int rc = 0;
1305         struct inode *inode = page->mapping->host;
1306         loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
1307         char *page_data;
1308
1309         xid = GetXid();
1310         cFYI(1, ("commit write for page %p up to position %lld for %d", 
1311                  page, position, to));
1312         if (position > inode->i_size) {
1313                 i_size_write(inode, position);
1314                 /* if (file->private_data == NULL) {
1315                         rc = -EBADF;
1316                 } else {
1317                         open_file = (struct cifsFileInfo *)file->private_data;
1318                         cifs_sb = CIFS_SB(inode->i_sb);
1319                         rc = -EAGAIN;
1320                         while (rc == -EAGAIN) {
1321                                 if ((open_file->invalidHandle) && 
1322                                     (!open_file->closePend)) {
1323                                         rc = cifs_reopen_file(
1324                                                 file->f_dentry->d_inode, file);
1325                                         if (rc != 0)
1326                                                 break;
1327                                 }
1328                                 if (!open_file->closePend) {
1329                                         rc = CIFSSMBSetFileSize(xid,
1330                                                 cifs_sb->tcon, position,
1331                                                 open_file->netfid,
1332                                                 open_file->pid, FALSE);
1333                                 } else {
1334                                         rc = -EBADF;
1335                                         break;
1336                                 }
1337                         }
1338                         cFYI(1, (" SetEOF (commit write) rc = %d", rc));
1339                 } */
1340         }
1341         if (!PageUptodate(page)) {
1342                 position =  ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
1343                 /* can not rely on (or let) writepage write this data */
1344                 if (to < offset) {
1345                         cFYI(1, ("Illegal offsets, can not copy from %d to %d",
1346                                 offset, to));
1347                         FreeXid(xid);
1348                         return rc;
1349                 }
1350                 /* this is probably better than directly calling
1351                    partialpage_write since in this function the file handle is
1352                    known which we might as well leverage */
1353                 /* BB check if anything else missing out of ppw
1354                    such as updating last write time */
1355                 page_data = kmap(page);
1356                 rc = cifs_write(file, page_data + offset, to-offset,
1357                                 &position);
1358                 if (rc > 0)
1359                         rc = 0;
1360                 /* else if (rc < 0) should we set writebehind rc? */
1361                 kunmap(page);
1362         } else {        
1363                 set_page_dirty(page);
1364         }
1365
1366         FreeXid(xid);
1367         return rc;
1368 }
1369
1370 int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1371 {
1372         int xid;
1373         int rc = 0;
1374         struct inode *inode = file->f_dentry->d_inode;
1375
1376         xid = GetXid();
1377
1378         cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 
1379                 dentry->d_name.name, datasync));
1380         
1381         rc = filemap_fdatawrite(inode->i_mapping);
1382         if (rc == 0)
1383                 CIFS_I(inode)->write_behind_rc = 0;
1384         FreeXid(xid);
1385         return rc;
1386 }
1387
1388 /* static void cifs_sync_page(struct page *page)
1389 {
1390         struct address_space *mapping;
1391         struct inode *inode;
1392         unsigned long index = page->index;
1393         unsigned int rpages = 0;
1394         int rc = 0;
1395
1396         cFYI(1, ("sync page %p",page));
1397         mapping = page->mapping;
1398         if (!mapping)
1399                 return 0;
1400         inode = mapping->host;
1401         if (!inode)
1402                 return; */
1403
1404 /*      fill in rpages then 
1405         result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
1406
1407 /*      cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
1408
1409 #if 0
1410         if (rc < 0)
1411                 return rc;
1412         return 0;
1413 #endif
1414 } */
1415
1416 /*
1417  * As file closes, flush all cached write data for this inode checking
1418  * for write behind errors.
1419  */
1420 int cifs_flush(struct file *file, fl_owner_t id)
1421 {
1422         struct inode * inode = file->f_dentry->d_inode;
1423         int rc = 0;
1424
1425         /* Rather than do the steps manually:
1426            lock the inode for writing
1427            loop through pages looking for write behind data (dirty pages)
1428            coalesce into contiguous 16K (or smaller) chunks to write to server
1429            send to server (prefer in parallel)
1430            deal with writebehind errors
1431            unlock inode for writing
1432            filemapfdatawrite appears easier for the time being */
1433
1434         rc = filemap_fdatawrite(inode->i_mapping);
1435         if (!rc) /* reset wb rc if we were able to write out dirty pages */
1436                 CIFS_I(inode)->write_behind_rc = 0;
1437                 
1438         cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc));
1439
1440         return rc;
1441 }
1442
1443 ssize_t cifs_user_read(struct file *file, char __user *read_data,
1444         size_t read_size, loff_t *poffset)
1445 {
1446         int rc = -EACCES;
1447         unsigned int bytes_read = 0;
1448         unsigned int total_read = 0;
1449         unsigned int current_read_size;
1450         struct cifs_sb_info *cifs_sb;
1451         struct cifsTconInfo *pTcon;
1452         int xid;
1453         struct cifsFileInfo *open_file;
1454         char *smb_read_data;
1455         char __user *current_offset;
1456         struct smb_com_read_rsp *pSMBr;
1457
1458         xid = GetXid();
1459         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1460         pTcon = cifs_sb->tcon;
1461
1462         if (file->private_data == NULL) {
1463                 FreeXid(xid);
1464                 return -EBADF;
1465         }
1466         open_file = (struct cifsFileInfo *)file->private_data;
1467
1468         if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
1469                 cFYI(1, ("attempting read on write only file instance"));
1470         }
1471         for (total_read = 0, current_offset = read_data;
1472              read_size > total_read;
1473              total_read += bytes_read, current_offset += bytes_read) {
1474                 current_read_size = min_t(const int, read_size - total_read, 
1475                                           cifs_sb->rsize);
1476                 rc = -EAGAIN;
1477                 smb_read_data = NULL;
1478                 while (rc == -EAGAIN) {
1479                         int buf_type = CIFS_NO_BUFFER;
1480                         if ((open_file->invalidHandle) && 
1481                             (!open_file->closePend)) {
1482                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1483                                         file, TRUE);
1484                                 if (rc != 0)
1485                                         break;
1486                         }
1487                         rc = CIFSSMBRead(xid, pTcon,
1488                                          open_file->netfid,
1489                                          current_read_size, *poffset,
1490                                          &bytes_read, &smb_read_data,
1491                                          &buf_type);
1492                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1493                         if (smb_read_data) {
1494                                 if (copy_to_user(current_offset,
1495                                                 smb_read_data +
1496                                                 4 /* RFC1001 length field */ +
1497                                                 le16_to_cpu(pSMBr->DataOffset),
1498                                                 bytes_read)) {
1499                                         rc = -EFAULT;
1500                                 }
1501
1502                                 if(buf_type == CIFS_SMALL_BUFFER)
1503                                         cifs_small_buf_release(smb_read_data);
1504                                 else if(buf_type == CIFS_LARGE_BUFFER)
1505                                         cifs_buf_release(smb_read_data);
1506                                 smb_read_data = NULL;
1507                         }
1508                 }
1509                 if (rc || (bytes_read == 0)) {
1510                         if (total_read) {
1511                                 break;
1512                         } else {
1513                                 FreeXid(xid);
1514                                 return rc;
1515                         }
1516                 } else {
1517                         cifs_stats_bytes_read(pTcon, bytes_read);
1518                         *poffset += bytes_read;
1519                 }
1520         }
1521         FreeXid(xid);
1522         return total_read;
1523 }
1524
1525
1526 static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1527         loff_t *poffset)
1528 {
1529         int rc = -EACCES;
1530         unsigned int bytes_read = 0;
1531         unsigned int total_read;
1532         unsigned int current_read_size;
1533         struct cifs_sb_info *cifs_sb;
1534         struct cifsTconInfo *pTcon;
1535         int xid;
1536         char *current_offset;
1537         struct cifsFileInfo *open_file;
1538         int buf_type = CIFS_NO_BUFFER;
1539
1540         xid = GetXid();
1541         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1542         pTcon = cifs_sb->tcon;
1543
1544         if (file->private_data == NULL) {
1545                 FreeXid(xid);
1546                 return -EBADF;
1547         }
1548         open_file = (struct cifsFileInfo *)file->private_data;
1549
1550         if ((file->f_flags & O_ACCMODE) == O_WRONLY)
1551                 cFYI(1, ("attempting read on write only file instance"));
1552
1553         for (total_read = 0, current_offset = read_data; 
1554              read_size > total_read;
1555              total_read += bytes_read, current_offset += bytes_read) {
1556                 current_read_size = min_t(const int, read_size - total_read,
1557                                           cifs_sb->rsize);
1558                 /* For windows me and 9x we do not want to request more
1559                 than it negotiated since it will refuse the read then */
1560                 if((pTcon->ses) && 
1561                         !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
1562                         current_read_size = min_t(const int, current_read_size,
1563                                         pTcon->ses->server->maxBuf - 128);
1564                 }
1565                 rc = -EAGAIN;
1566                 while (rc == -EAGAIN) {
1567                         if ((open_file->invalidHandle) && 
1568                             (!open_file->closePend)) {
1569                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1570                                         file, TRUE);
1571                                 if (rc != 0)
1572                                         break;
1573                         }
1574                         rc = CIFSSMBRead(xid, pTcon,
1575                                          open_file->netfid,
1576                                          current_read_size, *poffset,
1577                                          &bytes_read, &current_offset,
1578                                          &buf_type);
1579                 }
1580                 if (rc || (bytes_read == 0)) {
1581                         if (total_read) {
1582                                 break;
1583                         } else {
1584                                 FreeXid(xid);
1585                                 return rc;
1586                         }
1587                 } else {
1588                         cifs_stats_bytes_read(pTcon, total_read);
1589                         *poffset += bytes_read;
1590                 }
1591         }
1592         FreeXid(xid);
1593         return total_read;
1594 }
1595
1596 int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1597 {
1598         struct dentry *dentry = file->f_dentry;
1599         int rc, xid;
1600
1601         xid = GetXid();
1602         rc = cifs_revalidate(dentry);
1603         if (rc) {
1604                 cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
1605                 FreeXid(xid);
1606                 return rc;
1607         }
1608         rc = generic_file_mmap(file, vma);
1609         FreeXid(xid);
1610         return rc;
1611 }
1612
1613
1614 static void cifs_copy_cache_pages(struct address_space *mapping, 
1615         struct list_head *pages, int bytes_read, char *data,
1616         struct pagevec *plru_pvec)
1617 {
1618         struct page *page;
1619         char *target;
1620
1621         while (bytes_read > 0) {
1622                 if (list_empty(pages))
1623                         break;
1624
1625                 page = list_entry(pages->prev, struct page, lru);
1626                 list_del(&page->lru);
1627
1628                 if (add_to_page_cache(page, mapping, page->index,
1629                                       GFP_KERNEL)) {
1630                         page_cache_release(page);
1631                         cFYI(1, ("Add page cache failed"));
1632                         data += PAGE_CACHE_SIZE;
1633                         bytes_read -= PAGE_CACHE_SIZE;
1634                         continue;
1635                 }
1636
1637                 target = kmap_atomic(page,KM_USER0);
1638
1639                 if (PAGE_CACHE_SIZE > bytes_read) {
1640                         memcpy(target, data, bytes_read);
1641                         /* zero the tail end of this partial page */
1642                         memset(target + bytes_read, 0, 
1643                                PAGE_CACHE_SIZE - bytes_read);
1644                         bytes_read = 0;
1645                 } else {
1646                         memcpy(target, data, PAGE_CACHE_SIZE);
1647                         bytes_read -= PAGE_CACHE_SIZE;
1648                 }
1649                 kunmap_atomic(target, KM_USER0);
1650
1651                 flush_dcache_page(page);
1652                 SetPageUptodate(page);
1653                 unlock_page(page);
1654                 if (!pagevec_add(plru_pvec, page))
1655                         __pagevec_lru_add(plru_pvec);
1656                 data += PAGE_CACHE_SIZE;
1657         }
1658         return;
1659 }
1660
1661 static int cifs_readpages(struct file *file, struct address_space *mapping,
1662         struct list_head *page_list, unsigned num_pages)
1663 {
1664         int rc = -EACCES;
1665         int xid;
1666         loff_t offset;
1667         struct page *page;
1668         struct cifs_sb_info *cifs_sb;
1669         struct cifsTconInfo *pTcon;
1670         int bytes_read = 0;
1671         unsigned int read_size,i;
1672         char *smb_read_data = NULL;
1673         struct smb_com_read_rsp *pSMBr;
1674         struct pagevec lru_pvec;
1675         struct cifsFileInfo *open_file;
1676         int buf_type = CIFS_NO_BUFFER;
1677
1678         xid = GetXid();
1679         if (file->private_data == NULL) {
1680                 FreeXid(xid);
1681                 return -EBADF;
1682         }
1683         open_file = (struct cifsFileInfo *)file->private_data;
1684         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1685         pTcon = cifs_sb->tcon;
1686
1687         pagevec_init(&lru_pvec, 0);
1688
1689         for (i = 0; i < num_pages; ) {
1690                 unsigned contig_pages;
1691                 struct page *tmp_page;
1692                 unsigned long expected_index;
1693
1694                 if (list_empty(page_list))
1695                         break;
1696
1697                 page = list_entry(page_list->prev, struct page, lru);
1698                 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1699
1700                 /* count adjacent pages that we will read into */
1701                 contig_pages = 0;
1702                 expected_index = 
1703                         list_entry(page_list->prev, struct page, lru)->index;
1704                 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1705                         if (tmp_page->index == expected_index) {
1706                                 contig_pages++;
1707                                 expected_index++;
1708                         } else
1709                                 break; 
1710                 }
1711                 if (contig_pages + i >  num_pages)
1712                         contig_pages = num_pages - i;
1713
1714                 /* for reads over a certain size could initiate async
1715                    read ahead */
1716
1717                 read_size = contig_pages * PAGE_CACHE_SIZE;
1718                 /* Read size needs to be in multiples of one page */
1719                 read_size = min_t(const unsigned int, read_size,
1720                                   cifs_sb->rsize & PAGE_CACHE_MASK);
1721
1722                 rc = -EAGAIN;
1723                 while (rc == -EAGAIN) {
1724                         if ((open_file->invalidHandle) && 
1725                             (!open_file->closePend)) {
1726                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1727                                         file, TRUE);
1728                                 if (rc != 0)
1729                                         break;
1730                         }
1731
1732                         rc = CIFSSMBRead(xid, pTcon,
1733                                          open_file->netfid,
1734                                          read_size, offset,
1735                                          &bytes_read, &smb_read_data,
1736                                          &buf_type);
1737                         /* BB more RC checks ? */
1738                         if (rc== -EAGAIN) {
1739                                 if (smb_read_data) {
1740                                         if(buf_type == CIFS_SMALL_BUFFER)
1741                                                 cifs_small_buf_release(smb_read_data);
1742                                         else if(buf_type == CIFS_LARGE_BUFFER)
1743                                                 cifs_buf_release(smb_read_data);
1744                                         smb_read_data = NULL;
1745                                 }
1746                         }
1747                 }
1748                 if ((rc < 0) || (smb_read_data == NULL)) {
1749                         cFYI(1, ("Read error in readpages: %d", rc));
1750                         /* clean up remaing pages off list */
1751                         while (!list_empty(page_list) && (i < num_pages)) {
1752                                 page = list_entry(page_list->prev, struct page,
1753                                                   lru);
1754                                 list_del(&page->lru);
1755                                 page_cache_release(page);
1756                         }
1757                         break;
1758                 } else if (bytes_read > 0) {
1759                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1760                         cifs_copy_cache_pages(mapping, page_list, bytes_read,
1761                                 smb_read_data + 4 /* RFC1001 hdr */ +
1762                                 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1763
1764                         i +=  bytes_read >> PAGE_CACHE_SHIFT;
1765                         cifs_stats_bytes_read(pTcon, bytes_read);
1766                         if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1767                                 i++; /* account for partial page */
1768
1769                                 /* server copy of file can have smaller size 
1770                                    than client */
1771                                 /* BB do we need to verify this common case ? 
1772                                    this case is ok - if we are at server EOF 
1773                                    we will hit it on next read */
1774
1775                         /* while (!list_empty(page_list) && (i < num_pages)) {
1776                                         page = list_entry(page_list->prev, 
1777                                                           struct page, list);
1778                                         list_del(&page->list);
1779                                         page_cache_release(page);
1780                                 }
1781                                 break; */
1782                         }
1783                 } else {
1784                         cFYI(1, ("No bytes read (%d) at offset %lld . "
1785                                  "Cleaning remaining pages from readahead list",
1786                                  bytes_read, offset));
1787                         /* BB turn off caching and do new lookup on 
1788                            file size at server? */
1789                         while (!list_empty(page_list) && (i < num_pages)) {
1790                                 page = list_entry(page_list->prev, struct page,
1791                                                   lru);
1792                                 list_del(&page->lru);
1793
1794                                 /* BB removeme - replace with zero of page? */
1795                                 page_cache_release(page);
1796                         }
1797                         break;
1798                 }
1799                 if (smb_read_data) {
1800                         if(buf_type == CIFS_SMALL_BUFFER)
1801                                 cifs_small_buf_release(smb_read_data);
1802                         else if(buf_type == CIFS_LARGE_BUFFER)
1803                                 cifs_buf_release(smb_read_data);
1804                         smb_read_data = NULL;
1805                 }
1806                 bytes_read = 0;
1807         }
1808
1809         pagevec_lru_add(&lru_pvec);
1810
1811 /* need to free smb_read_data buf before exit */
1812         if (smb_read_data) {
1813                 if(buf_type == CIFS_SMALL_BUFFER)
1814                         cifs_small_buf_release(smb_read_data);
1815                 else if(buf_type == CIFS_LARGE_BUFFER)
1816                         cifs_buf_release(smb_read_data);
1817                 smb_read_data = NULL;
1818         } 
1819
1820         FreeXid(xid);
1821         return rc;
1822 }
1823
1824 static int cifs_readpage_worker(struct file *file, struct page *page,
1825         loff_t *poffset)
1826 {
1827         char *read_data;
1828         int rc;
1829
1830         page_cache_get(page);
1831         read_data = kmap(page);
1832         /* for reads over a certain size could initiate async read ahead */
1833                                                                                                                            
1834         rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1835                                                                                                                            
1836         if (rc < 0)
1837                 goto io_error;
1838         else
1839                 cFYI(1, ("Bytes read %d ",rc));
1840                                                                                                                            
1841         file->f_dentry->d_inode->i_atime =
1842                 current_fs_time(file->f_dentry->d_inode->i_sb);
1843                                                                                                                            
1844         if (PAGE_CACHE_SIZE > rc)
1845                 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
1846
1847         flush_dcache_page(page);
1848         SetPageUptodate(page);
1849         rc = 0;
1850                                                                                                                            
1851 io_error:
1852         kunmap(page);
1853         page_cache_release(page);
1854         return rc;
1855 }
1856
1857 static int cifs_readpage(struct file *file, struct page *page)
1858 {
1859         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1860         int rc = -EACCES;
1861         int xid;
1862
1863         xid = GetXid();
1864
1865         if (file->private_data == NULL) {
1866                 FreeXid(xid);
1867                 return -EBADF;
1868         }
1869
1870         cFYI(1, ("readpage %p at offset %d 0x%x\n", 
1871                  page, (int)offset, (int)offset));
1872
1873         rc = cifs_readpage_worker(file, page, &offset);
1874
1875         unlock_page(page);
1876
1877         FreeXid(xid);
1878         return rc;
1879 }
1880
1881 /* We do not want to update the file size from server for inodes
1882    open for write - to avoid races with writepage extending
1883    the file - in the future we could consider allowing
1884    refreshing the inode only on increases in the file size 
1885    but this is tricky to do without racing with writebehind
1886    page caching in the current Linux kernel design */
1887 int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1888 {
1889         struct cifsFileInfo *open_file = NULL;
1890
1891         if (cifsInode)
1892                 open_file =  find_writable_file(cifsInode);
1893  
1894         if(open_file) {
1895                 struct cifs_sb_info *cifs_sb;
1896
1897                 /* there is not actually a write pending so let
1898                 this handle go free and allow it to
1899                 be closable if needed */
1900                 atomic_dec(&open_file->wrtPending);
1901
1902                 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
1903                 if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) {
1904                         /* since no page cache to corrupt on directio 
1905                         we can change size safely */
1906                         return 1;
1907                 }
1908
1909                 return 0;
1910         } else
1911                 return 1;
1912 }
1913
1914 static int cifs_prepare_write(struct file *file, struct page *page,
1915         unsigned from, unsigned to)
1916 {
1917         int rc = 0;
1918         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1919         cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1920         if (!PageUptodate(page)) {
1921         /*      if (to - from != PAGE_CACHE_SIZE) {
1922                         void *kaddr = kmap_atomic(page, KM_USER0);
1923                         memset(kaddr, 0, from);
1924                         memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1925                         flush_dcache_page(page);
1926                         kunmap_atomic(kaddr, KM_USER0);
1927                 } */
1928                 /* If we are writing a full page it will be up to date,
1929                    no need to read from the server */
1930                 if ((to == PAGE_CACHE_SIZE) && (from == 0))
1931                         SetPageUptodate(page);
1932
1933                 /* might as well read a page, it is fast enough */
1934                 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
1935                         rc = cifs_readpage_worker(file, page, &offset);
1936                 } else {
1937                 /* should we try using another file handle if there is one -
1938                    how would we lock it to prevent close of that handle
1939                    racing with this read?
1940                    In any case this will be written out by commit_write */
1941                 }
1942         }
1943
1944         /* BB should we pass any errors back? 
1945            e.g. if we do not have read access to the file */
1946         return 0;
1947 }
1948
1949 struct address_space_operations cifs_addr_ops = {
1950         .readpage = cifs_readpage,
1951         .readpages = cifs_readpages,
1952         .writepage = cifs_writepage,
1953         .writepages = cifs_writepages,
1954         .prepare_write = cifs_prepare_write,
1955         .commit_write = cifs_commit_write,
1956         .set_page_dirty = __set_page_dirty_nobuffers,
1957         /* .sync_page = cifs_sync_page, */
1958         /* .direct_IO = */
1959 };