]> err.no Git - linux-2.6/blob - fs/cifs/file.c
[CIFS] Add support for legacy servers part 4
[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 %d bytes to offset %lld of %s", write_size,
795            *poffset, file->f_dentry->d_name.name)); /* BB removeme BB */
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         int use_old_read = FALSE;
1187
1188         xid = GetXid();
1189         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1190         pTcon = cifs_sb->tcon;
1191
1192         if(pTcon->ses)
1193                 if((pTcon->ses->capabilities & CAP_LARGE_FILES) == 0)
1194                         use_old_read = TRUE;
1195
1196         if (file->private_data == NULL) {
1197                 FreeXid(xid);
1198                 return -EBADF;
1199         }
1200         open_file = (struct cifsFileInfo *)file->private_data;
1201
1202         if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
1203                 cFYI(1, ("attempting read on write only file instance"));
1204         }
1205         for (total_read = 0, current_offset = read_data;
1206              read_size > total_read;
1207              total_read += bytes_read, current_offset += bytes_read) {
1208                 current_read_size = min_t(const int, read_size - total_read, 
1209                                           cifs_sb->rsize);
1210                 rc = -EAGAIN;
1211                 smb_read_data = NULL;
1212                 while (rc == -EAGAIN) {
1213                         if ((open_file->invalidHandle) && 
1214                             (!open_file->closePend)) {
1215                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1216                                         file, TRUE);
1217                                 if (rc != 0)
1218                                         break;
1219                         }
1220                         if(use_old_read)
1221                                 rc = SMBLegacyRead(xid, pTcon,
1222                                         open_file->netfid,
1223                                         current_read_size, *poffset,
1224                                         &bytes_read, &smb_read_data);
1225                         else {
1226                                 rc = CIFSSMBRead(xid, pTcon,
1227                                         open_file->netfid,
1228                                         current_read_size, *poffset,
1229                                         &bytes_read, &smb_read_data);
1230                                 if(rc == -EINVAL) {
1231                                         use_old_read = TRUE;
1232                                         rc = -EAGAIN;
1233                                         continue;
1234                                 }
1235                         }
1236                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1237                         if (copy_to_user(current_offset, 
1238                                          smb_read_data + 4 /* RFC1001 hdr */
1239                                          + le16_to_cpu(pSMBr->DataOffset), 
1240                                          bytes_read)) {
1241                                 rc = -EFAULT;
1242                                 FreeXid(xid);
1243                                 return rc;
1244             }
1245                         if (smb_read_data) {
1246                                 cifs_buf_release(smb_read_data);
1247                                 smb_read_data = NULL;
1248                         }
1249                 }
1250                 if (rc || (bytes_read == 0)) {
1251                         if (total_read) {
1252                                 break;
1253                         } else {
1254                                 FreeXid(xid);
1255                                 return rc;
1256                         }
1257                 } else {
1258                         cifs_stats_bytes_read(pTcon, bytes_read);
1259                         *poffset += bytes_read;
1260                 }
1261         }
1262         FreeXid(xid);
1263         return total_read;
1264 }
1265
1266
1267 static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1268         loff_t *poffset)
1269 {
1270         int rc = -EACCES;
1271         unsigned int bytes_read = 0;
1272         unsigned int total_read;
1273         unsigned int current_read_size;
1274         struct cifs_sb_info *cifs_sb;
1275         struct cifsTconInfo *pTcon;
1276         int xid;
1277         char *current_offset;
1278         struct cifsFileInfo *open_file;
1279         int use_old_read = FALSE;
1280
1281         xid = GetXid();
1282         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1283         pTcon = cifs_sb->tcon;
1284
1285         if (file->private_data == NULL) {
1286                 FreeXid(xid);
1287                 return -EBADF;
1288         }
1289         open_file = (struct cifsFileInfo *)file->private_data;
1290         if(pTcon->ses)
1291                 if((pTcon->ses->capabilities & CAP_LARGE_FILES) == 0)
1292                         use_old_read = TRUE;
1293
1294         if ((file->f_flags & O_ACCMODE) == O_WRONLY)
1295                 cFYI(1, ("attempting read on write only file instance"));
1296
1297         for (total_read = 0, current_offset = read_data; 
1298              read_size > total_read;
1299              total_read += bytes_read, current_offset += bytes_read) {
1300                 current_read_size = min_t(const int, read_size - total_read,
1301                                           cifs_sb->rsize);
1302                 rc = -EAGAIN;
1303                 while (rc == -EAGAIN) {
1304                         if ((open_file->invalidHandle) && 
1305                             (!open_file->closePend)) {
1306                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1307                                         file, TRUE);
1308                                 if (rc != 0)
1309                                         break;
1310                         }
1311                         if(use_old_read) 
1312                                 rc = SMBLegacyRead(xid, pTcon,
1313                                          open_file->netfid,
1314                                          current_read_size, *poffset,
1315                                          &bytes_read, &current_offset);
1316                         else {
1317                                 rc = CIFSSMBRead(xid, pTcon,
1318                                         open_file->netfid,
1319                                         current_read_size, *poffset,
1320                                         &bytes_read, &current_offset);
1321                                 /* check if server disavows support for
1322                                    64 bit offsets */
1323                                 if(rc == -EINVAL) {
1324                                         rc = -EAGAIN;
1325                                         use_old_read = TRUE;
1326                                         continue;
1327                                 }
1328                         }
1329                 }
1330                 if (rc || (bytes_read == 0)) {
1331                         if (total_read) {
1332                                 break;
1333                         } else {
1334                                 FreeXid(xid);
1335                                 return rc;
1336                         }
1337                 } else {
1338                         cifs_stats_bytes_read(pTcon, total_read);
1339                         *poffset += bytes_read;
1340                 }
1341         }
1342         FreeXid(xid);
1343         return total_read;
1344 }
1345
1346 int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1347 {
1348         struct dentry *dentry = file->f_dentry;
1349         int rc, xid;
1350
1351         xid = GetXid();
1352         rc = cifs_revalidate(dentry);
1353         if (rc) {
1354                 cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
1355                 FreeXid(xid);
1356                 return rc;
1357         }
1358         rc = generic_file_mmap(file, vma);
1359         FreeXid(xid);
1360         return rc;
1361 }
1362
1363
1364 static void cifs_copy_cache_pages(struct address_space *mapping, 
1365         struct list_head *pages, int bytes_read, char *data,
1366         struct pagevec *plru_pvec)
1367 {
1368         struct page *page;
1369         char *target;
1370
1371         while (bytes_read > 0) {
1372                 if (list_empty(pages))
1373                         break;
1374
1375                 page = list_entry(pages->prev, struct page, lru);
1376                 list_del(&page->lru);
1377
1378                 if (add_to_page_cache(page, mapping, page->index,
1379                                       GFP_KERNEL)) {
1380                         page_cache_release(page);
1381                         cFYI(1, ("Add page cache failed"));
1382                         data += PAGE_CACHE_SIZE;
1383                         bytes_read -= PAGE_CACHE_SIZE;
1384                         continue;
1385                 }
1386
1387                 target = kmap_atomic(page,KM_USER0);
1388
1389                 if (PAGE_CACHE_SIZE > bytes_read) {
1390                         memcpy(target, data, bytes_read);
1391                         /* zero the tail end of this partial page */
1392                         memset(target + bytes_read, 0, 
1393                                PAGE_CACHE_SIZE - bytes_read);
1394                         bytes_read = 0;
1395                 } else {
1396                         memcpy(target, data, PAGE_CACHE_SIZE);
1397                         bytes_read -= PAGE_CACHE_SIZE;
1398                 }
1399                 kunmap_atomic(target, KM_USER0);
1400
1401                 flush_dcache_page(page);
1402                 SetPageUptodate(page);
1403                 unlock_page(page);
1404                 if (!pagevec_add(plru_pvec, page))
1405                         __pagevec_lru_add(plru_pvec);
1406                 data += PAGE_CACHE_SIZE;
1407         }
1408         return;
1409 }
1410
1411 static int cifs_readpages(struct file *file, struct address_space *mapping,
1412         struct list_head *page_list, unsigned num_pages)
1413 {
1414         int rc = -EACCES;
1415         int xid;
1416         loff_t offset;
1417         struct page *page;
1418         struct cifs_sb_info *cifs_sb;
1419         struct cifsTconInfo *pTcon;
1420         int bytes_read = 0;
1421         unsigned int read_size,i;
1422         char *smb_read_data = NULL;
1423         struct smb_com_read_rsp *pSMBr;
1424         struct pagevec lru_pvec;
1425         struct cifsFileInfo *open_file;
1426         int use_old_read = FALSE;
1427
1428         xid = GetXid();
1429         if (file->private_data == NULL) {
1430                 FreeXid(xid);
1431                 return -EBADF;
1432         }
1433         open_file = (struct cifsFileInfo *)file->private_data;
1434         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1435         pTcon = cifs_sb->tcon;
1436         if(pTcon->ses)
1437                 if((pTcon->ses->capabilities & CAP_LARGE_FILES) == 0)
1438                         use_old_read = TRUE;
1439         pagevec_init(&lru_pvec, 0);
1440
1441         for (i = 0; i < num_pages; ) {
1442                 unsigned contig_pages;
1443                 struct page *tmp_page;
1444                 unsigned long expected_index;
1445
1446                 if (list_empty(page_list))
1447                         break;
1448
1449                 page = list_entry(page_list->prev, struct page, lru);
1450                 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1451
1452                 /* count adjacent pages that we will read into */
1453                 contig_pages = 0;
1454                 expected_index = 
1455                         list_entry(page_list->prev, struct page, lru)->index;
1456                 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1457                         if (tmp_page->index == expected_index) {
1458                                 contig_pages++;
1459                                 expected_index++;
1460                         } else
1461                                 break; 
1462                 }
1463                 if (contig_pages + i >  num_pages)
1464                         contig_pages = num_pages - i;
1465
1466                 /* for reads over a certain size could initiate async
1467                    read ahead */
1468
1469                 read_size = contig_pages * PAGE_CACHE_SIZE;
1470                 /* Read size needs to be in multiples of one page */
1471                 read_size = min_t(const unsigned int, read_size,
1472                                   cifs_sb->rsize & PAGE_CACHE_MASK);
1473
1474                 rc = -EAGAIN;
1475                 while (rc == -EAGAIN) {
1476                         if ((open_file->invalidHandle) && 
1477                             (!open_file->closePend)) {
1478                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1479                                         file, TRUE);
1480                                 if (rc != 0)
1481                                         break;
1482                         }
1483
1484                         if(use_old_read)
1485                                 rc = SMBLegacyRead(xid, pTcon,
1486                                         open_file->netfid,
1487                                         read_size, offset,
1488                                         &bytes_read, &smb_read_data);
1489                         else {
1490                                 rc = CIFSSMBRead(xid, pTcon,
1491                                         open_file->netfid,
1492                                         read_size, offset,
1493                                         &bytes_read, &smb_read_data);
1494                                 if(rc == -EINVAL) {
1495                                         use_old_read = TRUE;
1496                                         rc = -EAGAIN;
1497                                         continue;
1498                                 }
1499                         }
1500
1501                         /* BB more RC checks ? */
1502                         if (rc== -EAGAIN) {
1503                                 if (smb_read_data) {
1504                                         cifs_buf_release(smb_read_data);
1505                                         smb_read_data = NULL;
1506                                 }
1507                         }
1508                 }
1509                 if ((rc < 0) || (smb_read_data == NULL)) {
1510                         cFYI(1, ("Read error in readpages: %d", rc));
1511                         /* clean up remaing pages off list */
1512                         while (!list_empty(page_list) && (i < num_pages)) {
1513                                 page = list_entry(page_list->prev, struct page,
1514                                                   lru);
1515                                 list_del(&page->lru);
1516                                 page_cache_release(page);
1517                         }
1518                         break;
1519                 } else if (bytes_read > 0) {
1520                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1521                         cifs_copy_cache_pages(mapping, page_list, bytes_read,
1522                                 smb_read_data + 4 /* RFC1001 hdr */ +
1523                                 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1524
1525                         i +=  bytes_read >> PAGE_CACHE_SHIFT;
1526                         cifs_stats_bytes_read(pTcon, bytes_read);
1527                         if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1528                                 i++; /* account for partial page */
1529
1530                                 /* server copy of file can have smaller size 
1531                                    than client */
1532                                 /* BB do we need to verify this common case ? 
1533                                    this case is ok - if we are at server EOF 
1534                                    we will hit it on next read */
1535
1536                         /* while (!list_empty(page_list) && (i < num_pages)) {
1537                                         page = list_entry(page_list->prev, 
1538                                                           struct page, list);
1539                                         list_del(&page->list);
1540                                         page_cache_release(page);
1541                                 }
1542                                 break; */
1543                         }
1544                 } else {
1545                         cFYI(1, ("No bytes read (%d) at offset %lld . "
1546                                  "Cleaning remaining pages from readahead list",
1547                                  bytes_read, offset));
1548                         /* BB turn off caching and do new lookup on 
1549                            file size at server? */
1550                         while (!list_empty(page_list) && (i < num_pages)) {
1551                                 page = list_entry(page_list->prev, struct page,
1552                                                   lru);
1553                                 list_del(&page->lru);
1554
1555                                 /* BB removeme - replace with zero of page? */
1556                                 page_cache_release(page);
1557                         }
1558                         break;
1559                 }
1560                 if (smb_read_data) {
1561                         cifs_buf_release(smb_read_data);
1562                         smb_read_data = NULL;
1563                 }
1564                 bytes_read = 0;
1565         }
1566
1567         pagevec_lru_add(&lru_pvec);
1568
1569 /* need to free smb_read_data buf before exit */
1570         if (smb_read_data) {
1571                 cifs_buf_release(smb_read_data);
1572                 smb_read_data = NULL;
1573         } 
1574
1575         FreeXid(xid);
1576         return rc;
1577 }
1578
1579 static int cifs_readpage_worker(struct file *file, struct page *page,
1580         loff_t *poffset)
1581 {
1582         char *read_data;
1583         int rc;
1584
1585         page_cache_get(page);
1586         read_data = kmap(page);
1587         /* for reads over a certain size could initiate async read ahead */
1588                                                                                                                            
1589         rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1590                                                                                                                            
1591         if (rc < 0)
1592                 goto io_error;
1593         else
1594                 cFYI(1, ("Bytes read %d ",rc));
1595                                                                                                                            
1596         file->f_dentry->d_inode->i_atime =
1597                 current_fs_time(file->f_dentry->d_inode->i_sb);
1598                                                                                                                            
1599         if (PAGE_CACHE_SIZE > rc)
1600                 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
1601
1602         flush_dcache_page(page);
1603         SetPageUptodate(page);
1604         rc = 0;
1605                                                                                                                            
1606 io_error:
1607         kunmap(page);
1608         page_cache_release(page);
1609         return rc;
1610 }
1611
1612 static int cifs_readpage(struct file *file, struct page *page)
1613 {
1614         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1615         int rc = -EACCES;
1616         int xid;
1617
1618         xid = GetXid();
1619
1620         if (file->private_data == NULL) {
1621                 FreeXid(xid);
1622                 return -EBADF;
1623         }
1624
1625         cFYI(1, ("readpage %p at offset %d 0x%x\n", 
1626                  page, (int)offset, (int)offset));
1627
1628         rc = cifs_readpage_worker(file, page, &offset);
1629
1630         unlock_page(page);
1631
1632         FreeXid(xid);
1633         return rc;
1634 }
1635
1636 /* We do not want to update the file size from server for inodes
1637    open for write - to avoid races with writepage extending
1638    the file - in the future we could consider allowing
1639    refreshing the inode only on increases in the file size 
1640    but this is tricky to do without racing with writebehind
1641    page caching in the current Linux kernel design */
1642 int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1643 {
1644         struct list_head *tmp;
1645         struct list_head *tmp1;
1646         struct cifsFileInfo *open_file = NULL;
1647         int rc = TRUE;
1648
1649         if (cifsInode == NULL)
1650                 return rc;
1651
1652         read_lock(&GlobalSMBSeslock); 
1653         list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {            
1654                 open_file = list_entry(tmp, struct cifsFileInfo, flist);
1655                 if (open_file == NULL)
1656                         break;
1657                 if (open_file->closePend)
1658                         continue;
1659         /* We check if file is open for writing,   
1660            BB we could supplement this with a check to see if file size
1661            changes have been flushed to server - ie inode metadata dirty */
1662                 if ((open_file->pfile) && 
1663                     ((open_file->pfile->f_flags & O_RDWR) || 
1664                     (open_file->pfile->f_flags & O_WRONLY))) {
1665                         rc = FALSE;
1666                         break;
1667                 }
1668                 if (tmp->next == NULL) {
1669                         cFYI(1, ("File instance %p removed", tmp));
1670                         break;
1671                 }
1672         }
1673         read_unlock(&GlobalSMBSeslock);
1674         return rc;
1675 }
1676
1677
1678 static int cifs_prepare_write(struct file *file, struct page *page,
1679         unsigned from, unsigned to)
1680 {
1681         int rc = 0;
1682         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1683         cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1684         if (!PageUptodate(page)) {
1685         /*      if (to - from != PAGE_CACHE_SIZE) {
1686                         void *kaddr = kmap_atomic(page, KM_USER0);
1687                         memset(kaddr, 0, from);
1688                         memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1689                         flush_dcache_page(page);
1690                         kunmap_atomic(kaddr, KM_USER0);
1691                 } */
1692                 /* If we are writing a full page it will be up to date,
1693                    no need to read from the server */
1694                 if ((to == PAGE_CACHE_SIZE) && (from == 0))
1695                         SetPageUptodate(page);
1696
1697                 /* might as well read a page, it is fast enough */
1698                 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
1699                         rc = cifs_readpage_worker(file, page, &offset);
1700                 } else {
1701                 /* should we try using another file handle if there is one -
1702                    how would we lock it to prevent close of that handle
1703                    racing with this read?
1704                    In any case this will be written out by commit_write */
1705                 }
1706         }
1707
1708         /* BB should we pass any errors back? 
1709            e.g. if we do not have read access to the file */
1710         return 0;
1711 }
1712
1713 struct address_space_operations cifs_addr_ops = {
1714         .readpage = cifs_readpage,
1715         .readpages = cifs_readpages,
1716         .writepage = cifs_writepage,
1717         .prepare_write = cifs_prepare_write,
1718         .commit_write = cifs_commit_write,
1719         .set_page_dirty = __set_page_dirty_nobuffers,
1720         /* .sync_page = cifs_sync_page, */
1721         /* .direct_IO = */
1722 };