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