]> err.no Git - linux-2.6/blob - fs/cifs/file.c
[CIFS] Fix compiler warnings
[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                                 rc = CIFSSMBWrite2(xid, pTcon,
853                                                 open_file->netfid,
854                                                 min_t(const int, cifs_sb->wsize,
855                                                     write_size - total_written),
856                                                 *poffset, &bytes_written,
857                                                 write_data + total_written, 
858                                                 long_op);
859                         } else
860                         /* BB FIXME fixup indentation of line below */
861 #endif                  
862                         rc = CIFSSMBWrite(xid, pTcon,
863                                  open_file->netfid,
864                                  min_t(const int, cifs_sb->wsize, 
865                                        write_size - total_written),
866                                  *poffset, &bytes_written,
867                                  write_data + total_written, NULL, long_op);
868                 }
869                 if (rc || (bytes_written == 0)) {
870                         if (total_written)
871                                 break;
872                         else {
873                                 FreeXid(xid);
874                                 return rc;
875                         }
876                 } else
877                         *poffset += bytes_written;
878                 long_op = FALSE; /* subsequent writes fast - 
879                                     15 seconds is plenty */
880         }
881
882         cifs_stats_bytes_written(pTcon, total_written);
883
884         /* since the write may have blocked check these pointers again */
885         if (file->f_dentry) {
886                 if (file->f_dentry->d_inode) {
887                         file->f_dentry->d_inode->i_ctime = 
888                         file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
889                         if (total_written > 0) {
890                                 if (*poffset > file->f_dentry->d_inode->i_size)
891                                         i_size_write(file->f_dentry->d_inode, 
892                                                      *poffset);
893                         }
894                         mark_inode_dirty_sync(file->f_dentry->d_inode);
895                 }
896         }
897         FreeXid(xid);
898         return total_written;
899 }
900
901 static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
902 {
903         struct address_space *mapping = page->mapping;
904         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
905         char *write_data;
906         int rc = -EFAULT;
907         int bytes_written = 0;
908         struct cifs_sb_info *cifs_sb;
909         struct cifsTconInfo *pTcon;
910         struct inode *inode;
911         struct cifsInodeInfo *cifsInode;
912         struct cifsFileInfo *open_file = NULL;
913         struct list_head *tmp;
914         struct list_head *tmp1;
915
916         if (!mapping || !mapping->host)
917                 return -EFAULT;
918
919         inode = page->mapping->host;
920         cifs_sb = CIFS_SB(inode->i_sb);
921         pTcon = cifs_sb->tcon;
922
923         offset += (loff_t)from;
924         write_data = kmap(page);
925         write_data += from;
926
927         if ((to > PAGE_CACHE_SIZE) || (from > to)) {
928                 kunmap(page);
929                 return -EIO;
930         }
931
932         /* racing with truncate? */
933         if (offset > mapping->host->i_size) {
934                 kunmap(page);
935                 return 0; /* don't care */
936         }
937
938         /* check to make sure that we are not extending the file */
939         if (mapping->host->i_size - offset < (loff_t)to)
940                 to = (unsigned)(mapping->host->i_size - offset); 
941
942         cifsInode = CIFS_I(mapping->host);
943         read_lock(&GlobalSMBSeslock); 
944         /* BB we should start at the end */
945         list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {            
946                 open_file = list_entry(tmp, struct cifsFileInfo, flist);
947                 if (open_file->closePend)
948                         continue;
949                 /* We check if file is open for writing first */
950                 if ((open_file->pfile) && 
951                    ((open_file->pfile->f_flags & O_RDWR) || 
952                         (open_file->pfile->f_flags & O_WRONLY))) {
953                         read_unlock(&GlobalSMBSeslock);
954                         bytes_written = cifs_write(open_file->pfile,
955                                                 write_data, to-from,
956                                                 &offset);
957                         read_lock(&GlobalSMBSeslock);
958                 /* Does mm or vfs already set times? */
959                         inode->i_atime = 
960                         inode->i_mtime = current_fs_time(inode->i_sb);
961                         if ((bytes_written > 0) && (offset)) {
962                                 rc = 0;
963                         } else if (bytes_written < 0) {
964                                 if (rc == -EBADF) {
965                                 /* have seen a case in which kernel seemed to
966                                    have closed/freed a file even with writes
967                                    active so we might as well see if there are
968                                    other file structs to try for the same
969                                    inode before giving up */
970                                         continue;
971                                 } else
972                                         rc = bytes_written;
973                         }
974                         break;  /* now that we found a valid file handle and
975                                    tried to write to it we are done, no sense
976                                    continuing to loop looking for another */
977                 }
978                 if (tmp->next == NULL) {
979                         cFYI(1, ("File instance %p removed", tmp));
980                         break;
981                 }
982         }
983         read_unlock(&GlobalSMBSeslock);
984         if (open_file == NULL) {
985                 cFYI(1, ("No writeable filehandles for inode"));
986                 rc = -EIO;
987         }
988
989         kunmap(page);
990         return rc;
991 }
992
993 #if 0
994 static int cifs_writepages(struct address_space *mapping,
995         struct writeback_control *wbc)
996 {
997         int rc = -EFAULT;
998         int xid;
999
1000         xid = GetXid();
1001
1002         /* Find contiguous pages then iterate through repeating
1003            call 16K write then Setpageuptodate or if LARGE_WRITE_X
1004            support then send larger writes via kevec so as to eliminate
1005            a memcpy */
1006         FreeXid(xid);
1007         return rc;
1008 }
1009 #endif
1010
1011 static int cifs_writepage(struct page* page, struct writeback_control *wbc)
1012 {
1013         int rc = -EFAULT;
1014         int xid;
1015
1016         xid = GetXid();
1017 /* BB add check for wbc flags */
1018         page_cache_get(page);
1019         if (!PageUptodate(page)) {
1020                 cFYI(1, ("ppw - page not up to date"));
1021         }
1022         
1023         rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
1024         SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
1025         unlock_page(page);
1026         page_cache_release(page);       
1027         FreeXid(xid);
1028         return rc;
1029 }
1030
1031 static int cifs_commit_write(struct file *file, struct page *page,
1032         unsigned offset, unsigned to)
1033 {
1034         int xid;
1035         int rc = 0;
1036         struct inode *inode = page->mapping->host;
1037         loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
1038         char *page_data;
1039
1040         xid = GetXid();
1041         cFYI(1, ("commit write for page %p up to position %lld for %d", 
1042                  page, position, to));
1043         if (position > inode->i_size) {
1044                 i_size_write(inode, position);
1045                 /* if (file->private_data == NULL) {
1046                         rc = -EBADF;
1047                 } else {
1048                         open_file = (struct cifsFileInfo *)file->private_data;
1049                         cifs_sb = CIFS_SB(inode->i_sb);
1050                         rc = -EAGAIN;
1051                         while (rc == -EAGAIN) {
1052                                 if ((open_file->invalidHandle) && 
1053                                     (!open_file->closePend)) {
1054                                         rc = cifs_reopen_file(
1055                                                 file->f_dentry->d_inode, file);
1056                                         if (rc != 0)
1057                                                 break;
1058                                 }
1059                                 if (!open_file->closePend) {
1060                                         rc = CIFSSMBSetFileSize(xid,
1061                                                 cifs_sb->tcon, position,
1062                                                 open_file->netfid,
1063                                                 open_file->pid, FALSE);
1064                                 } else {
1065                                         rc = -EBADF;
1066                                         break;
1067                                 }
1068                         }
1069                         cFYI(1, (" SetEOF (commit write) rc = %d", rc));
1070                 } */
1071         }
1072         if (!PageUptodate(page)) {
1073                 position =  ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
1074                 /* can not rely on (or let) writepage write this data */
1075                 if (to < offset) {
1076                         cFYI(1, ("Illegal offsets, can not copy from %d to %d",
1077                                 offset, to));
1078                         FreeXid(xid);
1079                         return rc;
1080                 }
1081                 /* this is probably better than directly calling
1082                    partialpage_write since in this function the file handle is
1083                    known which we might as well leverage */
1084                 /* BB check if anything else missing out of ppw
1085                    such as updating last write time */
1086                 page_data = kmap(page);
1087                 rc = cifs_write(file, page_data + offset, to-offset,
1088                                 &position);
1089                 if (rc > 0)
1090                         rc = 0;
1091                 /* else if (rc < 0) should we set writebehind rc? */
1092                 kunmap(page);
1093         } else {        
1094                 set_page_dirty(page);
1095         }
1096
1097         FreeXid(xid);
1098         return rc;
1099 }
1100
1101 int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1102 {
1103         int xid;
1104         int rc = 0;
1105         struct inode *inode = file->f_dentry->d_inode;
1106
1107         xid = GetXid();
1108
1109         cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 
1110                 dentry->d_name.name, datasync));
1111         
1112         rc = filemap_fdatawrite(inode->i_mapping);
1113         if (rc == 0)
1114                 CIFS_I(inode)->write_behind_rc = 0;
1115         FreeXid(xid);
1116         return rc;
1117 }
1118
1119 /* static int cifs_sync_page(struct page *page)
1120 {
1121         struct address_space *mapping;
1122         struct inode *inode;
1123         unsigned long index = page->index;
1124         unsigned int rpages = 0;
1125         int rc = 0;
1126
1127         cFYI(1, ("sync page %p",page));
1128         mapping = page->mapping;
1129         if (!mapping)
1130                 return 0;
1131         inode = mapping->host;
1132         if (!inode)
1133                 return 0; */
1134
1135 /*      fill in rpages then 
1136         result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
1137
1138 /*      cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
1139
1140         if (rc < 0)
1141                 return rc;
1142         return 0;
1143 } */
1144
1145 /*
1146  * As file closes, flush all cached write data for this inode checking
1147  * for write behind errors.
1148  */
1149 int cifs_flush(struct file *file)
1150 {
1151         struct inode * inode = file->f_dentry->d_inode;
1152         int rc = 0;
1153
1154         /* Rather than do the steps manually:
1155            lock the inode for writing
1156            loop through pages looking for write behind data (dirty pages)
1157            coalesce into contiguous 16K (or smaller) chunks to write to server
1158            send to server (prefer in parallel)
1159            deal with writebehind errors
1160            unlock inode for writing
1161            filemapfdatawrite appears easier for the time being */
1162
1163         rc = filemap_fdatawrite(inode->i_mapping);
1164         if (!rc) /* reset wb rc if we were able to write out dirty pages */
1165                 CIFS_I(inode)->write_behind_rc = 0;
1166                 
1167         cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc));
1168
1169         return rc;
1170 }
1171
1172 ssize_t cifs_user_read(struct file *file, char __user *read_data,
1173         size_t read_size, loff_t *poffset)
1174 {
1175         int rc = -EACCES;
1176         unsigned int bytes_read = 0;
1177         unsigned int total_read = 0;
1178         unsigned int current_read_size;
1179         struct cifs_sb_info *cifs_sb;
1180         struct cifsTconInfo *pTcon;
1181         int xid;
1182         struct cifsFileInfo *open_file;
1183         char *smb_read_data;
1184         char __user *current_offset;
1185         struct smb_com_read_rsp *pSMBr;
1186
1187         xid = GetXid();
1188         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1189         pTcon = cifs_sb->tcon;
1190
1191         if (file->private_data == NULL) {
1192                 FreeXid(xid);
1193                 return -EBADF;
1194         }
1195         open_file = (struct cifsFileInfo *)file->private_data;
1196
1197         if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
1198                 cFYI(1, ("attempting read on write only file instance"));
1199         }
1200         for (total_read = 0, current_offset = read_data;
1201              read_size > total_read;
1202              total_read += bytes_read, current_offset += bytes_read) {
1203                 current_read_size = min_t(const int, read_size - total_read, 
1204                                           cifs_sb->rsize);
1205                 rc = -EAGAIN;
1206                 smb_read_data = NULL;
1207                 while (rc == -EAGAIN) {
1208                         if ((open_file->invalidHandle) && 
1209                             (!open_file->closePend)) {
1210                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1211                                         file, TRUE);
1212                                 if (rc != 0)
1213                                         break;
1214                         }
1215                         rc = CIFSSMBRead(xid, pTcon,
1216                                         open_file->netfid,
1217                                         current_read_size, *poffset,
1218                                         &bytes_read, &smb_read_data);
1219                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1220                         if (copy_to_user(current_offset, 
1221                                          smb_read_data + 4 /* RFC1001 hdr */
1222                                          + le16_to_cpu(pSMBr->DataOffset), 
1223                                          bytes_read)) {
1224                                 rc = -EFAULT;
1225                                 FreeXid(xid);
1226                                 return rc;
1227             }
1228                         if (smb_read_data) {
1229                                 cifs_buf_release(smb_read_data);
1230                                 smb_read_data = NULL;
1231                         }
1232                 }
1233                 if (rc || (bytes_read == 0)) {
1234                         if (total_read) {
1235                                 break;
1236                         } else {
1237                                 FreeXid(xid);
1238                                 return rc;
1239                         }
1240                 } else {
1241                         cifs_stats_bytes_read(pTcon, bytes_read);
1242                         *poffset += bytes_read;
1243                 }
1244         }
1245         FreeXid(xid);
1246         return total_read;
1247 }
1248
1249
1250 static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1251         loff_t *poffset)
1252 {
1253         int rc = -EACCES;
1254         unsigned int bytes_read = 0;
1255         unsigned int total_read;
1256         unsigned int current_read_size;
1257         struct cifs_sb_info *cifs_sb;
1258         struct cifsTconInfo *pTcon;
1259         int xid;
1260         char *current_offset;
1261         struct cifsFileInfo *open_file;
1262
1263         xid = GetXid();
1264         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1265         pTcon = cifs_sb->tcon;
1266
1267         if (file->private_data == NULL) {
1268                 FreeXid(xid);
1269                 return -EBADF;
1270         }
1271         open_file = (struct cifsFileInfo *)file->private_data;
1272
1273         if ((file->f_flags & O_ACCMODE) == O_WRONLY)
1274                 cFYI(1, ("attempting read on write only file instance"));
1275
1276         for (total_read = 0, current_offset = read_data; 
1277              read_size > total_read;
1278              total_read += bytes_read, current_offset += bytes_read) {
1279                 current_read_size = min_t(const int, read_size - total_read,
1280                                           cifs_sb->rsize);
1281                 rc = -EAGAIN;
1282                 while (rc == -EAGAIN) {
1283                         if ((open_file->invalidHandle) && 
1284                             (!open_file->closePend)) {
1285                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1286                                         file, TRUE);
1287                                 if (rc != 0)
1288                                         break;
1289                         }
1290                         rc = CIFSSMBRead(xid, pTcon,
1291                                         open_file->netfid,
1292                                         current_read_size, *poffset,
1293                                         &bytes_read, &current_offset);
1294                 }
1295                 if (rc || (bytes_read == 0)) {
1296                         if (total_read) {
1297                                 break;
1298                         } else {
1299                                 FreeXid(xid);
1300                                 return rc;
1301                         }
1302                 } else {
1303                         cifs_stats_bytes_read(pTcon, total_read);
1304                         *poffset += bytes_read;
1305                 }
1306         }
1307         FreeXid(xid);
1308         return total_read;
1309 }
1310
1311 int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1312 {
1313         struct dentry *dentry = file->f_dentry;
1314         int rc, xid;
1315
1316         xid = GetXid();
1317         rc = cifs_revalidate(dentry);
1318         if (rc) {
1319                 cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
1320                 FreeXid(xid);
1321                 return rc;
1322         }
1323         rc = generic_file_mmap(file, vma);
1324         FreeXid(xid);
1325         return rc;
1326 }
1327
1328
1329 static void cifs_copy_cache_pages(struct address_space *mapping, 
1330         struct list_head *pages, int bytes_read, char *data,
1331         struct pagevec *plru_pvec)
1332 {
1333         struct page *page;
1334         char *target;
1335
1336         while (bytes_read > 0) {
1337                 if (list_empty(pages))
1338                         break;
1339
1340                 page = list_entry(pages->prev, struct page, lru);
1341                 list_del(&page->lru);
1342
1343                 if (add_to_page_cache(page, mapping, page->index,
1344                                       GFP_KERNEL)) {
1345                         page_cache_release(page);
1346                         cFYI(1, ("Add page cache failed"));
1347                         data += PAGE_CACHE_SIZE;
1348                         bytes_read -= PAGE_CACHE_SIZE;
1349                         continue;
1350                 }
1351
1352                 target = kmap_atomic(page,KM_USER0);
1353
1354                 if (PAGE_CACHE_SIZE > bytes_read) {
1355                         memcpy(target, data, bytes_read);
1356                         /* zero the tail end of this partial page */
1357                         memset(target + bytes_read, 0, 
1358                                PAGE_CACHE_SIZE - bytes_read);
1359                         bytes_read = 0;
1360                 } else {
1361                         memcpy(target, data, PAGE_CACHE_SIZE);
1362                         bytes_read -= PAGE_CACHE_SIZE;
1363                 }
1364                 kunmap_atomic(target, KM_USER0);
1365
1366                 flush_dcache_page(page);
1367                 SetPageUptodate(page);
1368                 unlock_page(page);
1369                 if (!pagevec_add(plru_pvec, page))
1370                         __pagevec_lru_add(plru_pvec);
1371                 data += PAGE_CACHE_SIZE;
1372         }
1373         return;
1374 }
1375
1376 static int cifs_readpages(struct file *file, struct address_space *mapping,
1377         struct list_head *page_list, unsigned num_pages)
1378 {
1379         int rc = -EACCES;
1380         int xid;
1381         loff_t offset;
1382         struct page *page;
1383         struct cifs_sb_info *cifs_sb;
1384         struct cifsTconInfo *pTcon;
1385         int bytes_read = 0;
1386         unsigned int read_size,i;
1387         char *smb_read_data = NULL;
1388         struct smb_com_read_rsp *pSMBr;
1389         struct pagevec lru_pvec;
1390         struct cifsFileInfo *open_file;
1391
1392         xid = GetXid();
1393         if (file->private_data == NULL) {
1394                 FreeXid(xid);
1395                 return -EBADF;
1396         }
1397         open_file = (struct cifsFileInfo *)file->private_data;
1398         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1399         pTcon = cifs_sb->tcon;
1400
1401         pagevec_init(&lru_pvec, 0);
1402
1403         for (i = 0; i < num_pages; ) {
1404                 unsigned contig_pages;
1405                 struct page *tmp_page;
1406                 unsigned long expected_index;
1407
1408                 if (list_empty(page_list))
1409                         break;
1410
1411                 page = list_entry(page_list->prev, struct page, lru);
1412                 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1413
1414                 /* count adjacent pages that we will read into */
1415                 contig_pages = 0;
1416                 expected_index = 
1417                         list_entry(page_list->prev, struct page, lru)->index;
1418                 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1419                         if (tmp_page->index == expected_index) {
1420                                 contig_pages++;
1421                                 expected_index++;
1422                         } else
1423                                 break; 
1424                 }
1425                 if (contig_pages + i >  num_pages)
1426                         contig_pages = num_pages - i;
1427
1428                 /* for reads over a certain size could initiate async
1429                    read ahead */
1430
1431                 read_size = contig_pages * PAGE_CACHE_SIZE;
1432                 /* Read size needs to be in multiples of one page */
1433                 read_size = min_t(const unsigned int, read_size,
1434                                   cifs_sb->rsize & PAGE_CACHE_MASK);
1435
1436                 rc = -EAGAIN;
1437                 while (rc == -EAGAIN) {
1438                         if ((open_file->invalidHandle) && 
1439                             (!open_file->closePend)) {
1440                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1441                                         file, TRUE);
1442                                 if (rc != 0)
1443                                         break;
1444                         }
1445
1446                         rc = CIFSSMBRead(xid, pTcon,
1447                                         open_file->netfid,
1448                                         read_size, offset,
1449                                         &bytes_read, &smb_read_data);
1450
1451                         /* BB more RC checks ? */
1452                         if (rc== -EAGAIN) {
1453                                 if (smb_read_data) {
1454                                         cifs_buf_release(smb_read_data);
1455                                         smb_read_data = NULL;
1456                                 }
1457                         }
1458                 }
1459                 if ((rc < 0) || (smb_read_data == NULL)) {
1460                         cFYI(1, ("Read error in readpages: %d", rc));
1461                         /* clean up remaing pages off list */
1462                         while (!list_empty(page_list) && (i < num_pages)) {
1463                                 page = list_entry(page_list->prev, struct page,
1464                                                   lru);
1465                                 list_del(&page->lru);
1466                                 page_cache_release(page);
1467                         }
1468                         break;
1469                 } else if (bytes_read > 0) {
1470                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1471                         cifs_copy_cache_pages(mapping, page_list, bytes_read,
1472                                 smb_read_data + 4 /* RFC1001 hdr */ +
1473                                 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1474
1475                         i +=  bytes_read >> PAGE_CACHE_SHIFT;
1476                         cifs_stats_bytes_read(pTcon, bytes_read);
1477                         if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1478                                 i++; /* account for partial page */
1479
1480                                 /* server copy of file can have smaller size 
1481                                    than client */
1482                                 /* BB do we need to verify this common case ? 
1483                                    this case is ok - if we are at server EOF 
1484                                    we will hit it on next read */
1485
1486                         /* while (!list_empty(page_list) && (i < num_pages)) {
1487                                         page = list_entry(page_list->prev, 
1488                                                           struct page, list);
1489                                         list_del(&page->list);
1490                                         page_cache_release(page);
1491                                 }
1492                                 break; */
1493                         }
1494                 } else {
1495                         cFYI(1, ("No bytes read (%d) at offset %lld . "
1496                                  "Cleaning remaining pages from readahead list",
1497                                  bytes_read, offset));
1498                         /* BB turn off caching and do new lookup on 
1499                            file size at server? */
1500                         while (!list_empty(page_list) && (i < num_pages)) {
1501                                 page = list_entry(page_list->prev, struct page,
1502                                                   lru);
1503                                 list_del(&page->lru);
1504
1505                                 /* BB removeme - replace with zero of page? */
1506                                 page_cache_release(page);
1507                         }
1508                         break;
1509                 }
1510                 if (smb_read_data) {
1511                         cifs_buf_release(smb_read_data);
1512                         smb_read_data = NULL;
1513                 }
1514                 bytes_read = 0;
1515         }
1516
1517         pagevec_lru_add(&lru_pvec);
1518
1519 /* need to free smb_read_data buf before exit */
1520         if (smb_read_data) {
1521                 cifs_buf_release(smb_read_data);
1522                 smb_read_data = NULL;
1523         } 
1524
1525         FreeXid(xid);
1526         return rc;
1527 }
1528
1529 static int cifs_readpage_worker(struct file *file, struct page *page,
1530         loff_t *poffset)
1531 {
1532         char *read_data;
1533         int rc;
1534
1535         page_cache_get(page);
1536         read_data = kmap(page);
1537         /* for reads over a certain size could initiate async read ahead */
1538                                                                                                                            
1539         rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1540                                                                                                                            
1541         if (rc < 0)
1542                 goto io_error;
1543         else
1544                 cFYI(1, ("Bytes read %d ",rc));
1545                                                                                                                            
1546         file->f_dentry->d_inode->i_atime =
1547                 current_fs_time(file->f_dentry->d_inode->i_sb);
1548                                                                                                                            
1549         if (PAGE_CACHE_SIZE > rc)
1550                 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
1551
1552         flush_dcache_page(page);
1553         SetPageUptodate(page);
1554         rc = 0;
1555                                                                                                                            
1556 io_error:
1557         kunmap(page);
1558         page_cache_release(page);
1559         return rc;
1560 }
1561
1562 static int cifs_readpage(struct file *file, struct page *page)
1563 {
1564         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1565         int rc = -EACCES;
1566         int xid;
1567
1568         xid = GetXid();
1569
1570         if (file->private_data == NULL) {
1571                 FreeXid(xid);
1572                 return -EBADF;
1573         }
1574
1575         cFYI(1, ("readpage %p at offset %d 0x%x\n", 
1576                  page, (int)offset, (int)offset));
1577
1578         rc = cifs_readpage_worker(file, page, &offset);
1579
1580         unlock_page(page);
1581
1582         FreeXid(xid);
1583         return rc;
1584 }
1585
1586 /* We do not want to update the file size from server for inodes
1587    open for write - to avoid races with writepage extending
1588    the file - in the future we could consider allowing
1589    refreshing the inode only on increases in the file size 
1590    but this is tricky to do without racing with writebehind
1591    page caching in the current Linux kernel design */
1592 int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1593 {
1594         struct list_head *tmp;
1595         struct list_head *tmp1;
1596         struct cifsFileInfo *open_file = NULL;
1597         int rc = TRUE;
1598
1599         if (cifsInode == NULL)
1600                 return rc;
1601
1602         read_lock(&GlobalSMBSeslock); 
1603         list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {            
1604                 open_file = list_entry(tmp, struct cifsFileInfo, flist);
1605                 if (open_file == NULL)
1606                         break;
1607                 if (open_file->closePend)
1608                         continue;
1609         /* We check if file is open for writing,   
1610            BB we could supplement this with a check to see if file size
1611            changes have been flushed to server - ie inode metadata dirty */
1612                 if ((open_file->pfile) && 
1613                     ((open_file->pfile->f_flags & O_RDWR) || 
1614                     (open_file->pfile->f_flags & O_WRONLY))) {
1615                         rc = FALSE;
1616                         break;
1617                 }
1618                 if (tmp->next == NULL) {
1619                         cFYI(1, ("File instance %p removed", tmp));
1620                         break;
1621                 }
1622         }
1623         read_unlock(&GlobalSMBSeslock);
1624         return rc;
1625 }
1626
1627
1628 static int cifs_prepare_write(struct file *file, struct page *page,
1629         unsigned from, unsigned to)
1630 {
1631         int rc = 0;
1632         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1633         cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1634         if (!PageUptodate(page)) {
1635         /*      if (to - from != PAGE_CACHE_SIZE) {
1636                         void *kaddr = kmap_atomic(page, KM_USER0);
1637                         memset(kaddr, 0, from);
1638                         memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1639                         flush_dcache_page(page);
1640                         kunmap_atomic(kaddr, KM_USER0);
1641                 } */
1642                 /* If we are writing a full page it will be up to date,
1643                    no need to read from the server */
1644                 if ((to == PAGE_CACHE_SIZE) && (from == 0))
1645                         SetPageUptodate(page);
1646
1647                 /* might as well read a page, it is fast enough */
1648                 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
1649                         rc = cifs_readpage_worker(file, page, &offset);
1650                 } else {
1651                 /* should we try using another file handle if there is one -
1652                    how would we lock it to prevent close of that handle
1653                    racing with this read?
1654                    In any case this will be written out by commit_write */
1655                 }
1656         }
1657
1658         /* BB should we pass any errors back? 
1659            e.g. if we do not have read access to the file */
1660         return 0;
1661 }
1662
1663 struct address_space_operations cifs_addr_ops = {
1664         .readpage = cifs_readpage,
1665         .readpages = cifs_readpages,
1666         .writepage = cifs_writepage,
1667         .prepare_write = cifs_prepare_write,
1668         .commit_write = cifs_commit_write,
1669         .set_page_dirty = __set_page_dirty_nobuffers,
1670         /* .sync_page = cifs_sync_page, */
1671         /* .direct_IO = */
1672 };