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