[CIFS] Remove cifs_sb argument from *build_path_from_dentry
[safe/jmp/linux-2.6] / fs / cifs / file.c
1 /*
2  *   fs/cifs/file.c
3  *
4  *   vfs operations that deal with files
5  * 
6  *   Copyright (C) International Business Machines  Corp., 2002,2003
7  *   Author(s): Steve French (sfrench@us.ibm.com)
8  *
9  *   This library is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU Lesser General Public License as published
11  *   by the Free Software Foundation; either version 2.1 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This library is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU Lesser General Public License for more details.
18  *
19  *   You should have received a copy of the GNU Lesser General Public License
20  *   along with this library; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23 #include <linux/fs.h>
24 #include <linux/stat.h>
25 #include <linux/fcntl.h>
26 #include <linux/pagemap.h>
27 #include <linux/pagevec.h>
28 #include <linux/smp_lock.h>
29 #include <asm/div64.h>
30 #include "cifsfs.h"
31 #include "cifspdu.h"
32 #include "cifsglob.h"
33 #include "cifsproto.h"
34 #include "cifs_unicode.h"
35 #include "cifs_debug.h"
36 #include "cifs_fs_sb.h"
37
38 static inline struct cifsFileInfo *cifs_init_private(
39         struct cifsFileInfo *private_data, struct inode *inode,
40         struct file *file, __u16 netfid)
41 {
42         memset(private_data, 0, sizeof(struct cifsFileInfo));
43         private_data->netfid = netfid;
44         private_data->pid = current->tgid;      
45         init_MUTEX(&private_data->fh_sem);
46         private_data->pfile = file; /* needed for writepage */
47         private_data->pInode = inode;
48         private_data->invalidHandle = FALSE;
49         private_data->closePend = FALSE;
50
51         return private_data;
52 }
53
54 static inline int cifs_convert_flags(unsigned int flags)
55 {
56         if ((flags & O_ACCMODE) == O_RDONLY)
57                 return GENERIC_READ;
58         else if ((flags & O_ACCMODE) == O_WRONLY)
59                 return GENERIC_WRITE;
60         else if ((flags & O_ACCMODE) == O_RDWR) {
61                 /* GENERIC_ALL is too much permission to request
62                    can cause unnecessary access denied on create */
63                 /* return GENERIC_ALL; */
64                 return (GENERIC_READ | GENERIC_WRITE);
65         }
66
67         return 0x20197;
68 }
69
70 static inline int cifs_get_disposition(unsigned int flags)
71 {
72         if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
73                 return FILE_CREATE;
74         else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
75                 return FILE_OVERWRITE_IF;
76         else if ((flags & O_CREAT) == O_CREAT)
77                 return FILE_OPEN_IF;
78         else
79                 return FILE_OPEN;
80 }
81
82 /* all arguments to this function must be checked for validity in caller */
83 static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
84         struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
85         struct cifsTconInfo *pTcon, int *oplock, FILE_ALL_INFO *buf,
86         char *full_path, int xid)
87 {
88         struct timespec temp;
89         int rc;
90
91         /* want handles we can use to read with first
92            in the list so we do not have to walk the
93            list to search for one in prepare_write */
94         if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
95                 list_add_tail(&pCifsFile->flist, 
96                               &pCifsInode->openFileList);
97         } else {
98                 list_add(&pCifsFile->flist,
99                          &pCifsInode->openFileList);
100         }
101         write_unlock(&GlobalSMBSeslock);
102         write_unlock(&file->f_owner.lock);
103         if (pCifsInode->clientCanCacheRead) {
104                 /* we have the inode open somewhere else
105                    no need to discard cache data */
106                 goto client_can_cache;
107         }
108
109         /* BB need same check in cifs_create too? */
110         /* if not oplocked, invalidate inode pages if mtime or file
111            size changed */
112         temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
113         if (timespec_equal(&file->f_dentry->d_inode->i_mtime, &temp) && 
114                            (file->f_dentry->d_inode->i_size == 
115                             (loff_t)le64_to_cpu(buf->EndOfFile))) {
116                 cFYI(1, ("inode unchanged on server"));
117         } else {
118                 if (file->f_dentry->d_inode->i_mapping) {
119                 /* BB no need to lock inode until after invalidate
120                    since namei code should already have it locked? */
121                         filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
122                         filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
123                 }
124                 cFYI(1, ("invalidating remote inode since open detected it "
125                          "changed"));
126                 invalidate_remote_inode(file->f_dentry->d_inode);
127         }
128
129 client_can_cache:
130         if (pTcon->ses->capabilities & CAP_UNIX)
131                 rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
132                         full_path, inode->i_sb, xid);
133         else
134                 rc = cifs_get_inode_info(&file->f_dentry->d_inode,
135                         full_path, buf, inode->i_sb, xid);
136
137         if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
138                 pCifsInode->clientCanCacheAll = TRUE;
139                 pCifsInode->clientCanCacheRead = TRUE;
140                 cFYI(1, ("Exclusive Oplock granted on inode %p",
141                          file->f_dentry->d_inode));
142         } else if ((*oplock & 0xF) == OPLOCK_READ)
143                 pCifsInode->clientCanCacheRead = TRUE;
144
145         return rc;
146 }
147
148 int cifs_open(struct inode *inode, struct file *file)
149 {
150         int rc = -EACCES;
151         int xid, oplock;
152         struct cifs_sb_info *cifs_sb;
153         struct cifsTconInfo *pTcon;
154         struct cifsFileInfo *pCifsFile;
155         struct cifsInodeInfo *pCifsInode;
156         struct list_head *tmp;
157         char *full_path = NULL;
158         int desiredAccess;
159         int disposition;
160         __u16 netfid;
161         FILE_ALL_INFO *buf = NULL;
162
163         xid = GetXid();
164
165         cifs_sb = CIFS_SB(inode->i_sb);
166         pTcon = cifs_sb->tcon;
167
168         if (file->f_flags & O_CREAT) {
169                 /* search inode for this file and fill in file->private_data */
170                 pCifsInode = CIFS_I(file->f_dentry->d_inode);
171                 read_lock(&GlobalSMBSeslock);
172                 list_for_each(tmp, &pCifsInode->openFileList) {
173                         pCifsFile = list_entry(tmp, struct cifsFileInfo,
174                                                flist);
175                         if ((pCifsFile->pfile == NULL) &&
176                             (pCifsFile->pid == current->tgid)) {
177                                 /* mode set in cifs_create */
178
179                                 /* needed for writepage */
180                                 pCifsFile->pfile = file;
181                                 
182                                 file->private_data = pCifsFile;
183                                 break;
184                         }
185                 }
186                 read_unlock(&GlobalSMBSeslock);
187                 if (file->private_data != NULL) {
188                         rc = 0;
189                         FreeXid(xid);
190                         return rc;
191                 } else {
192                         if (file->f_flags & O_EXCL)
193                                 cERROR(1, ("could not find file instance for "
194                                            "new file %p ", file));
195                 }
196         }
197
198         down(&inode->i_sb->s_vfs_rename_sem);
199         full_path = build_path_from_dentry(file->f_dentry);
200         up(&inode->i_sb->s_vfs_rename_sem);
201         if (full_path == NULL) {
202                 FreeXid(xid);
203                 return -ENOMEM;
204         }
205
206         cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
207                  inode, file->f_flags, full_path));
208         desiredAccess = cifs_convert_flags(file->f_flags);
209
210 /*********************************************************************
211  *  open flag mapping table:
212  *  
213  *      POSIX Flag            CIFS Disposition
214  *      ----------            ---------------- 
215  *      O_CREAT               FILE_OPEN_IF
216  *      O_CREAT | O_EXCL      FILE_CREATE
217  *      O_CREAT | O_TRUNC     FILE_OVERWRITE_IF
218  *      O_TRUNC               FILE_OVERWRITE
219  *      none of the above     FILE_OPEN
220  *
221  *      Note that there is not a direct match between disposition
222  *      FILE_SUPERSEDE (ie create whether or not file exists although 
223  *      O_CREAT | O_TRUNC is similar but truncates the existing
224  *      file rather than creating a new file as FILE_SUPERSEDE does
225  *      (which uses the attributes / metadata passed in on open call)
226  *?
227  *?  O_SYNC is a reasonable match to CIFS writethrough flag  
228  *?  and the read write flags match reasonably.  O_LARGEFILE
229  *?  is irrelevant because largefile support is always used
230  *?  by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
231  *       O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
232  *********************************************************************/
233
234         disposition = cifs_get_disposition(file->f_flags);
235
236         if (oplockEnabled)
237                 oplock = REQ_OPLOCK;
238         else
239                 oplock = FALSE;
240
241         /* BB pass O_SYNC flag through on file attributes .. BB */
242
243         /* Also refresh inode by passing in file_info buf returned by SMBOpen
244            and calling get_inode_info with returned buf (at least helps
245            non-Unix server case) */
246
247         /* BB we can not do this if this is the second open of a file 
248            and the first handle has writebehind data, we might be 
249            able to simply do a filemap_fdatawrite/filemap_fdatawait first */
250         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
251         if (!buf) {
252                 rc = -ENOMEM;
253                 goto out;
254         }
255         rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
256                          CREATE_NOT_DIR, &netfid, &oplock, buf,
257                          cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
258                                  & CIFS_MOUNT_MAP_SPECIAL_CHR);
259         if (rc == -EIO) {
260                 /* Old server, try legacy style OpenX */
261                 rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
262                         desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
263                         cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
264                                 & CIFS_MOUNT_MAP_SPECIAL_CHR);
265         }
266         if (rc) {
267                 cFYI(1, ("cifs_open returned 0x%x ", rc));
268                 goto out;
269         }
270         file->private_data =
271                 kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
272         if (file->private_data == NULL) {
273                 rc = -ENOMEM;
274                 goto out;
275         }
276         pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
277         write_lock(&file->f_owner.lock);
278         write_lock(&GlobalSMBSeslock);
279         list_add(&pCifsFile->tlist, &pTcon->openFileList);
280
281         pCifsInode = CIFS_I(file->f_dentry->d_inode);
282         if (pCifsInode) {
283                 rc = cifs_open_inode_helper(inode, file, pCifsInode,
284                                             pCifsFile, pTcon,
285                                             &oplock, buf, full_path, xid);
286         } else {
287                 write_unlock(&GlobalSMBSeslock);
288                 write_unlock(&file->f_owner.lock);
289         }
290
291         if (oplock & CIFS_CREATE_ACTION) {           
292                 /* time to set mode which we can not set earlier due to
293                    problems creating new read-only files */
294                 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
295                         CIFSSMBUnixSetPerms(xid, pTcon, full_path,
296                                             inode->i_mode,
297                                             (__u64)-1, (__u64)-1, 0 /* dev */,
298                                             cifs_sb->local_nls,
299                                             cifs_sb->mnt_cifs_flags & 
300                                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
301                 } else {
302                         /* BB implement via Windows security descriptors eg
303                            CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
304                                               -1, -1, local_nls);
305                            in the meantime could set r/o dos attribute when
306                            perms are eg: mode & 0222 == 0 */
307                 }
308         }
309
310 out:
311         kfree(buf);
312         kfree(full_path);
313         FreeXid(xid);
314         return rc;
315 }
316
317 /* Try to reaquire byte range locks that were released when session */
318 /* to server was lost */
319 static int cifs_relock_file(struct cifsFileInfo *cifsFile)
320 {
321         int rc = 0;
322
323 /* BB list all locks open on this file and relock */
324
325         return rc;
326 }
327
328 static int cifs_reopen_file(struct inode *inode, struct file *file, 
329         int can_flush)
330 {
331         int rc = -EACCES;
332         int xid, oplock;
333         struct cifs_sb_info *cifs_sb;
334         struct cifsTconInfo *pTcon;
335         struct cifsFileInfo *pCifsFile;
336         struct cifsInodeInfo *pCifsInode;
337         char *full_path = NULL;
338         int desiredAccess;
339         int disposition = FILE_OPEN;
340         __u16 netfid;
341
342         if (inode == NULL)
343                 return -EBADF;
344         if (file->private_data) {
345                 pCifsFile = (struct cifsFileInfo *)file->private_data;
346         } else
347                 return -EBADF;
348
349         xid = GetXid();
350         down(&pCifsFile->fh_sem);
351         if (pCifsFile->invalidHandle == FALSE) {
352                 up(&pCifsFile->fh_sem);
353                 FreeXid(xid);
354                 return 0;
355         }
356
357         if (file->f_dentry == NULL) {
358                 up(&pCifsFile->fh_sem);
359                 cFYI(1, ("failed file reopen, no valid name if dentry freed"));
360                 FreeXid(xid);
361                 return -EBADF;
362         }
363         cifs_sb = CIFS_SB(inode->i_sb);
364         pTcon = cifs_sb->tcon;
365 /* can not grab rename sem here because various ops, including
366    those that already have the rename sem can end up causing writepage
367    to get called and if the server was down that means we end up here,
368    and we can never tell if the caller already has the rename_sem */
369         full_path = build_path_from_dentry(file->f_dentry);
370         if (full_path == NULL) {
371                 up(&pCifsFile->fh_sem);
372                 FreeXid(xid);
373                 return -ENOMEM;
374         }
375
376         cFYI(1, (" inode = 0x%p file flags are 0x%x for %s",
377                  inode, file->f_flags,full_path));
378         desiredAccess = cifs_convert_flags(file->f_flags);
379
380         if (oplockEnabled)
381                 oplock = REQ_OPLOCK;
382         else
383                 oplock = FALSE;
384
385         /* Can not refresh inode by passing in file_info buf to be returned
386            by SMBOpen and then calling get_inode_info with returned buf 
387            since file might have write behind data that needs to be flushed 
388            and server version of file size can be stale. If we knew for sure
389            that inode was not dirty locally we could do this */
390
391 /*      buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
392         if (buf == 0) {
393                 up(&pCifsFile->fh_sem);
394                 kfree(full_path);
395                 FreeXid(xid);
396                 return -ENOMEM;
397         } */
398         rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
399                          CREATE_NOT_DIR, &netfid, &oplock, NULL,
400                          cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 
401                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
402         if (rc) {
403                 up(&pCifsFile->fh_sem);
404                 cFYI(1, ("cifs_open returned 0x%x ", rc));
405                 cFYI(1, ("oplock: %d ", oplock));
406         } else {
407                 pCifsFile->netfid = netfid;
408                 pCifsFile->invalidHandle = FALSE;
409                 up(&pCifsFile->fh_sem);
410                 pCifsInode = CIFS_I(inode);
411                 if (pCifsInode) {
412                         if (can_flush) {
413                                 filemap_fdatawrite(inode->i_mapping);
414                                 filemap_fdatawait(inode->i_mapping);
415                         /* temporarily disable caching while we
416                            go to server to get inode info */
417                                 pCifsInode->clientCanCacheAll = FALSE;
418                                 pCifsInode->clientCanCacheRead = FALSE;
419                                 if (pTcon->ses->capabilities & CAP_UNIX)
420                                         rc = cifs_get_inode_info_unix(&inode,
421                                                 full_path, inode->i_sb, xid);
422                                 else
423                                         rc = cifs_get_inode_info(&inode,
424                                                 full_path, NULL, inode->i_sb,
425                                                 xid);
426                         } /* else we are writing out data to server already
427                              and could deadlock if we tried to flush data, and
428                              since we do not know if we have data that would
429                              invalidate the current end of file on the server
430                              we can not go to the server to get the new inod
431                              info */
432                         if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
433                                 pCifsInode->clientCanCacheAll = TRUE;
434                                 pCifsInode->clientCanCacheRead = TRUE;
435                                 cFYI(1, ("Exclusive Oplock granted on inode %p",
436                                          file->f_dentry->d_inode));
437                         } else if ((oplock & 0xF) == OPLOCK_READ) {
438                                 pCifsInode->clientCanCacheRead = TRUE;
439                                 pCifsInode->clientCanCacheAll = FALSE;
440                         } else {
441                                 pCifsInode->clientCanCacheRead = FALSE;
442                                 pCifsInode->clientCanCacheAll = FALSE;
443                         }
444                         cifs_relock_file(pCifsFile);
445                 }
446         }
447
448         kfree(full_path);
449         FreeXid(xid);
450         return rc;
451 }
452
453 int cifs_close(struct inode *inode, struct file *file)
454 {
455         int rc = 0;
456         int xid;
457         struct cifs_sb_info *cifs_sb;
458         struct cifsTconInfo *pTcon;
459         struct cifsFileInfo *pSMBFile =
460                 (struct cifsFileInfo *)file->private_data;
461
462         xid = GetXid();
463
464         cifs_sb = CIFS_SB(inode->i_sb);
465         pTcon = cifs_sb->tcon;
466         if (pSMBFile) {
467                 pSMBFile->closePend = TRUE;
468                 write_lock(&file->f_owner.lock);
469                 if (pTcon) {
470                         /* no sense reconnecting to close a file that is
471                            already closed */
472                         if (pTcon->tidStatus != CifsNeedReconnect) {
473                                 write_unlock(&file->f_owner.lock);
474                                 rc = CIFSSMBClose(xid, pTcon,
475                                                   pSMBFile->netfid);
476                                 write_lock(&file->f_owner.lock);
477                         }
478                 }
479                 write_lock(&GlobalSMBSeslock);
480                 list_del(&pSMBFile->flist);
481                 list_del(&pSMBFile->tlist);
482                 write_unlock(&GlobalSMBSeslock);
483                 write_unlock(&file->f_owner.lock);
484                 kfree(pSMBFile->search_resume_name);
485                 kfree(file->private_data);
486                 file->private_data = NULL;
487         } else
488                 rc = -EBADF;
489
490         if (list_empty(&(CIFS_I(inode)->openFileList))) {
491                 cFYI(1, ("closing last open instance for inode %p", inode));
492                 /* if the file is not open we do not know if we can cache info
493                    on this inode, much less write behind and read ahead */
494                 CIFS_I(inode)->clientCanCacheRead = FALSE;
495                 CIFS_I(inode)->clientCanCacheAll  = FALSE;
496         }
497         if ((rc ==0) && CIFS_I(inode)->write_behind_rc)
498                 rc = CIFS_I(inode)->write_behind_rc;
499         FreeXid(xid);
500         return rc;
501 }
502
503 int cifs_closedir(struct inode *inode, struct file *file)
504 {
505         int rc = 0;
506         int xid;
507         struct cifsFileInfo *pCFileStruct =
508             (struct cifsFileInfo *)file->private_data;
509         char *ptmp;
510
511         cFYI(1, ("Closedir inode = 0x%p with ", inode));
512
513         xid = GetXid();
514
515         if (pCFileStruct) {
516                 struct cifsTconInfo *pTcon;
517                 struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_dentry->d_sb);
518
519                 pTcon = cifs_sb->tcon;
520
521                 cFYI(1, ("Freeing private data in close dir"));
522                 if ((pCFileStruct->srch_inf.endOfSearch == FALSE) &&
523                    (pCFileStruct->invalidHandle == FALSE)) {
524                         pCFileStruct->invalidHandle = TRUE;
525                         rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
526                         cFYI(1, ("Closing uncompleted readdir with rc %d",
527                                  rc));
528                         /* not much we can do if it fails anyway, ignore rc */
529                         rc = 0;
530                 }
531                 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
532                 if (ptmp) {
533    /* BB removeme BB */ cFYI(1, ("freeing smb buf in srch struct in closedir"));
534                         pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
535                         cifs_buf_release(ptmp);
536                 }
537                 ptmp = pCFileStruct->search_resume_name;
538                 if (ptmp) {
539    /* BB removeme BB */ cFYI(1, ("freeing resume name in closedir"));
540                         pCFileStruct->search_resume_name = NULL;
541                         kfree(ptmp);
542                 }
543                 kfree(file->private_data);
544                 file->private_data = NULL;
545         }
546         /* BB can we lock the filestruct while this is going on? */
547         FreeXid(xid);
548         return rc;
549 }
550
551 int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
552 {
553         int rc, xid;
554         __u32 lockType = LOCKING_ANDX_LARGE_FILES;
555         __u32 numLock = 0;
556         __u32 numUnlock = 0;
557         __u64 length;
558         int wait_flag = FALSE;
559         struct cifs_sb_info *cifs_sb;
560         struct cifsTconInfo *pTcon;
561
562         length = 1 + pfLock->fl_end - pfLock->fl_start;
563         rc = -EACCES;
564         xid = GetXid();
565
566         cFYI(1, ("Lock parm: 0x%x flockflags: "
567                  "0x%x flocktype: 0x%x start: %lld end: %lld",
568                 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
569                 pfLock->fl_end));
570
571         if (pfLock->fl_flags & FL_POSIX)
572                 cFYI(1, ("Posix "));
573         if (pfLock->fl_flags & FL_FLOCK)
574                 cFYI(1, ("Flock "));
575         if (pfLock->fl_flags & FL_SLEEP) {
576                 cFYI(1, ("Blocking lock "));
577                 wait_flag = TRUE;
578         }
579         if (pfLock->fl_flags & FL_ACCESS)
580                 cFYI(1, ("Process suspended by mandatory locking - "
581                          "not implemented yet "));
582         if (pfLock->fl_flags & FL_LEASE)
583                 cFYI(1, ("Lease on file - not implemented yet"));
584         if (pfLock->fl_flags & 
585             (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
586                 cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags));
587
588         if (pfLock->fl_type == F_WRLCK) {
589                 cFYI(1, ("F_WRLCK "));
590                 numLock = 1;
591         } else if (pfLock->fl_type == F_UNLCK) {
592                 cFYI(1, ("F_UNLCK "));
593                 numUnlock = 1;
594         } else if (pfLock->fl_type == F_RDLCK) {
595                 cFYI(1, ("F_RDLCK "));
596                 lockType |= LOCKING_ANDX_SHARED_LOCK;
597                 numLock = 1;
598         } else if (pfLock->fl_type == F_EXLCK) {
599                 cFYI(1, ("F_EXLCK "));
600                 numLock = 1;
601         } else if (pfLock->fl_type == F_SHLCK) {
602                 cFYI(1, ("F_SHLCK "));
603                 lockType |= LOCKING_ANDX_SHARED_LOCK;
604                 numLock = 1;
605         } else
606                 cFYI(1, ("Unknown type of lock "));
607
608         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
609         pTcon = cifs_sb->tcon;
610
611         if (file->private_data == NULL) {
612                 FreeXid(xid);
613                 return -EBADF;
614         }
615
616         if (IS_GETLK(cmd)) {
617                 rc = CIFSSMBLock(xid, pTcon,
618                                  ((struct cifsFileInfo *)file->
619                                   private_data)->netfid,
620                                  length,
621                                  pfLock->fl_start, 0, 1, lockType,
622                                  0 /* wait flag */ );
623                 if (rc == 0) {
624                         rc = CIFSSMBLock(xid, pTcon,
625                                          ((struct cifsFileInfo *) file->
626                                           private_data)->netfid,
627                                          length,
628                                          pfLock->fl_start, 1 /* numUnlock */ ,
629                                          0 /* numLock */ , lockType,
630                                          0 /* wait flag */ );
631                         pfLock->fl_type = F_UNLCK;
632                         if (rc != 0)
633                                 cERROR(1, ("Error unlocking previously locked "
634                                            "range %d during test of lock ",
635                                            rc));
636                         rc = 0;
637
638                 } else {
639                         /* if rc == ERR_SHARING_VIOLATION ? */
640                         rc = 0; /* do not change lock type to unlock
641                                    since range in use */
642                 }
643
644                 FreeXid(xid);
645                 return rc;
646         }
647
648         rc = CIFSSMBLock(xid, pTcon,
649                          ((struct cifsFileInfo *) file->private_data)->
650                          netfid, length,
651                          pfLock->fl_start, numUnlock, numLock, lockType,
652                          wait_flag);
653         if (rc == 0 && (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
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
1216                         rc = CIFSSMBRead(xid, pTcon,
1217                                  open_file->netfid,
1218                                  current_read_size, *poffset,
1219                                  &bytes_read, &smb_read_data);
1220                         if(rc == -EINVAL) {
1221                                 rc = SMBLegacyRead(xid, pTcon,
1222                                         open_file->netfid,
1223                                         current_read_size, *poffset,
1224                                         &bytes_read, &smb_read_data);
1225                         }
1226                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1227                         if (copy_to_user(current_offset, 
1228                                          smb_read_data + 4 /* RFC1001 hdr */
1229                                          + le16_to_cpu(pSMBr->DataOffset), 
1230                                          bytes_read)) {
1231                                 rc = -EFAULT;
1232                                 FreeXid(xid);
1233                                 return rc;
1234             }
1235                         if (smb_read_data) {
1236                                 cifs_buf_release(smb_read_data);
1237                                 smb_read_data = NULL;
1238                         }
1239                 }
1240                 if (rc || (bytes_read == 0)) {
1241                         if (total_read) {
1242                                 break;
1243                         } else {
1244                                 FreeXid(xid);
1245                                 return rc;
1246                         }
1247                 } else {
1248                         cifs_stats_bytes_read(pTcon, bytes_read);
1249                         *poffset += bytes_read;
1250                 }
1251         }
1252         FreeXid(xid);
1253         return total_read;
1254 }
1255
1256
1257 static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1258         loff_t *poffset)
1259 {
1260         int rc = -EACCES;
1261         unsigned int bytes_read = 0;
1262         unsigned int total_read;
1263         unsigned int current_read_size;
1264         struct cifs_sb_info *cifs_sb;
1265         struct cifsTconInfo *pTcon;
1266         int xid;
1267         char *current_offset;
1268         struct cifsFileInfo *open_file;
1269
1270         xid = GetXid();
1271         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1272         pTcon = cifs_sb->tcon;
1273
1274         if (file->private_data == NULL) {
1275                 FreeXid(xid);
1276                 return -EBADF;
1277         }
1278         open_file = (struct cifsFileInfo *)file->private_data;
1279
1280         if ((file->f_flags & O_ACCMODE) == O_WRONLY)
1281                 cFYI(1, ("attempting read on write only file instance"));
1282
1283         for (total_read = 0, current_offset = read_data; 
1284              read_size > total_read;
1285              total_read += bytes_read, current_offset += bytes_read) {
1286                 current_read_size = min_t(const int, read_size - total_read,
1287                                           cifs_sb->rsize);
1288                 rc = -EAGAIN;
1289                 while (rc == -EAGAIN) {
1290                         if ((open_file->invalidHandle) && 
1291                             (!open_file->closePend)) {
1292                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1293                                         file, TRUE);
1294                                 if (rc != 0)
1295                                         break;
1296                         }
1297
1298                         rc = CIFSSMBRead(xid, pTcon,
1299                                  open_file->netfid,
1300                                  current_read_size, *poffset,
1301                                  &bytes_read, &current_offset);
1302                         if(rc == -EINVAL) {
1303                                 rc = SMBLegacyRead(xid, pTcon,
1304                                         open_file->netfid,
1305                                         current_read_size, *poffset,
1306                                         &bytes_read, &current_offset);
1307                         }
1308                 }
1309                 if (rc || (bytes_read == 0)) {
1310                         if (total_read) {
1311                                 break;
1312                         } else {
1313                                 FreeXid(xid);
1314                                 return rc;
1315                         }
1316                 } else {
1317                         cifs_stats_bytes_read(pTcon, total_read);
1318                         *poffset += bytes_read;
1319                 }
1320         }
1321         FreeXid(xid);
1322         return total_read;
1323 }
1324
1325 int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1326 {
1327         struct dentry *dentry = file->f_dentry;
1328         int rc, xid;
1329
1330         xid = GetXid();
1331         rc = cifs_revalidate(dentry);
1332         if (rc) {
1333                 cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
1334                 FreeXid(xid);
1335                 return rc;
1336         }
1337         rc = generic_file_mmap(file, vma);
1338         FreeXid(xid);
1339         return rc;
1340 }
1341
1342
1343 static void cifs_copy_cache_pages(struct address_space *mapping, 
1344         struct list_head *pages, int bytes_read, char *data,
1345         struct pagevec *plru_pvec)
1346 {
1347         struct page *page;
1348         char *target;
1349
1350         while (bytes_read > 0) {
1351                 if (list_empty(pages))
1352                         break;
1353
1354                 page = list_entry(pages->prev, struct page, lru);
1355                 list_del(&page->lru);
1356
1357                 if (add_to_page_cache(page, mapping, page->index,
1358                                       GFP_KERNEL)) {
1359                         page_cache_release(page);
1360                         cFYI(1, ("Add page cache failed"));
1361                         data += PAGE_CACHE_SIZE;
1362                         bytes_read -= PAGE_CACHE_SIZE;
1363                         continue;
1364                 }
1365
1366                 target = kmap_atomic(page,KM_USER0);
1367
1368                 if (PAGE_CACHE_SIZE > bytes_read) {
1369                         memcpy(target, data, bytes_read);
1370                         /* zero the tail end of this partial page */
1371                         memset(target + bytes_read, 0, 
1372                                PAGE_CACHE_SIZE - bytes_read);
1373                         bytes_read = 0;
1374                 } else {
1375                         memcpy(target, data, PAGE_CACHE_SIZE);
1376                         bytes_read -= PAGE_CACHE_SIZE;
1377                 }
1378                 kunmap_atomic(target, KM_USER0);
1379
1380                 flush_dcache_page(page);
1381                 SetPageUptodate(page);
1382                 unlock_page(page);
1383                 if (!pagevec_add(plru_pvec, page))
1384                         __pagevec_lru_add(plru_pvec);
1385                 data += PAGE_CACHE_SIZE;
1386         }
1387         return;
1388 }
1389
1390 static int cifs_readpages(struct file *file, struct address_space *mapping,
1391         struct list_head *page_list, unsigned num_pages)
1392 {
1393         int rc = -EACCES;
1394         int xid;
1395         loff_t offset;
1396         struct page *page;
1397         struct cifs_sb_info *cifs_sb;
1398         struct cifsTconInfo *pTcon;
1399         int bytes_read = 0;
1400         unsigned int read_size,i;
1401         char *smb_read_data = NULL;
1402         struct smb_com_read_rsp *pSMBr;
1403         struct pagevec lru_pvec;
1404         struct cifsFileInfo *open_file;
1405
1406         xid = GetXid();
1407         if (file->private_data == NULL) {
1408                 FreeXid(xid);
1409                 return -EBADF;
1410         }
1411         open_file = (struct cifsFileInfo *)file->private_data;
1412         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1413         pTcon = cifs_sb->tcon;
1414
1415         pagevec_init(&lru_pvec, 0);
1416
1417         for (i = 0; i < num_pages; ) {
1418                 unsigned contig_pages;
1419                 struct page *tmp_page;
1420                 unsigned long expected_index;
1421
1422                 if (list_empty(page_list))
1423                         break;
1424
1425                 page = list_entry(page_list->prev, struct page, lru);
1426                 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1427
1428                 /* count adjacent pages that we will read into */
1429                 contig_pages = 0;
1430                 expected_index = 
1431                         list_entry(page_list->prev, struct page, lru)->index;
1432                 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1433                         if (tmp_page->index == expected_index) {
1434                                 contig_pages++;
1435                                 expected_index++;
1436                         } else
1437                                 break; 
1438                 }
1439                 if (contig_pages + i >  num_pages)
1440                         contig_pages = num_pages - i;
1441
1442                 /* for reads over a certain size could initiate async
1443                    read ahead */
1444
1445                 read_size = contig_pages * PAGE_CACHE_SIZE;
1446                 /* Read size needs to be in multiples of one page */
1447                 read_size = min_t(const unsigned int, read_size,
1448                                   cifs_sb->rsize & PAGE_CACHE_MASK);
1449
1450                 rc = -EAGAIN;
1451                 while (rc == -EAGAIN) {
1452                         if ((open_file->invalidHandle) && 
1453                             (!open_file->closePend)) {
1454                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1455                                         file, TRUE);
1456                                 if (rc != 0)
1457                                         break;
1458                         }
1459
1460                         rc = CIFSSMBRead(xid, pTcon,
1461                                 open_file->netfid,
1462                                 read_size, offset,
1463                                 &bytes_read, &smb_read_data);
1464                         if (rc == -EINVAL) {
1465                                 rc = SMBLegacyRead(xid, pTcon,
1466                                         open_file->netfid,
1467                                         read_size, offset,
1468                                         &bytes_read, &smb_read_data);
1469                         }
1470
1471                         /* BB more RC checks ? */
1472                         if (rc== -EAGAIN) {
1473                                 if (smb_read_data) {
1474                                         cifs_buf_release(smb_read_data);
1475                                         smb_read_data = NULL;
1476                                 }
1477                         }
1478                 }
1479                 if ((rc < 0) || (smb_read_data == NULL)) {
1480                         cFYI(1, ("Read error in readpages: %d", rc));
1481                         /* clean up remaing pages off list */
1482                         while (!list_empty(page_list) && (i < num_pages)) {
1483                                 page = list_entry(page_list->prev, struct page,
1484                                                   lru);
1485                                 list_del(&page->lru);
1486                                 page_cache_release(page);
1487                         }
1488                         break;
1489                 } else if (bytes_read > 0) {
1490                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1491                         cifs_copy_cache_pages(mapping, page_list, bytes_read,
1492                                 smb_read_data + 4 /* RFC1001 hdr */ +
1493                                 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1494
1495                         i +=  bytes_read >> PAGE_CACHE_SHIFT;
1496                         cifs_stats_bytes_read(pTcon, bytes_read);
1497                         if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1498                                 i++; /* account for partial page */
1499
1500                                 /* server copy of file can have smaller size 
1501                                    than client */
1502                                 /* BB do we need to verify this common case ? 
1503                                    this case is ok - if we are at server EOF 
1504                                    we will hit it on next read */
1505
1506                         /* while (!list_empty(page_list) && (i < num_pages)) {
1507                                         page = list_entry(page_list->prev, 
1508                                                           struct page, list);
1509                                         list_del(&page->list);
1510                                         page_cache_release(page);
1511                                 }
1512                                 break; */
1513                         }
1514                 } else {
1515                         cFYI(1, ("No bytes read (%d) at offset %lld . "
1516                                  "Cleaning remaining pages from readahead list",
1517                                  bytes_read, offset));
1518                         /* BB turn off caching and do new lookup on 
1519                            file size at server? */
1520                         while (!list_empty(page_list) && (i < num_pages)) {
1521                                 page = list_entry(page_list->prev, struct page,
1522                                                   lru);
1523                                 list_del(&page->lru);
1524
1525                                 /* BB removeme - replace with zero of page? */
1526                                 page_cache_release(page);
1527                         }
1528                         break;
1529                 }
1530                 if (smb_read_data) {
1531                         cifs_buf_release(smb_read_data);
1532                         smb_read_data = NULL;
1533                 }
1534                 bytes_read = 0;
1535         }
1536
1537         pagevec_lru_add(&lru_pvec);
1538
1539 /* need to free smb_read_data buf before exit */
1540         if (smb_read_data) {
1541                 cifs_buf_release(smb_read_data);
1542                 smb_read_data = NULL;
1543         } 
1544
1545         FreeXid(xid);
1546         return rc;
1547 }
1548
1549 static int cifs_readpage_worker(struct file *file, struct page *page,
1550         loff_t *poffset)
1551 {
1552         char *read_data;
1553         int rc;
1554
1555         page_cache_get(page);
1556         read_data = kmap(page);
1557         /* for reads over a certain size could initiate async read ahead */
1558                                                                                                                            
1559         rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1560                                                                                                                            
1561         if (rc < 0)
1562                 goto io_error;
1563         else
1564                 cFYI(1, ("Bytes read %d ",rc));
1565                                                                                                                            
1566         file->f_dentry->d_inode->i_atime =
1567                 current_fs_time(file->f_dentry->d_inode->i_sb);
1568                                                                                                                            
1569         if (PAGE_CACHE_SIZE > rc)
1570                 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
1571
1572         flush_dcache_page(page);
1573         SetPageUptodate(page);
1574         rc = 0;
1575                                                                                                                            
1576 io_error:
1577         kunmap(page);
1578         page_cache_release(page);
1579         return rc;
1580 }
1581
1582 static int cifs_readpage(struct file *file, struct page *page)
1583 {
1584         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1585         int rc = -EACCES;
1586         int xid;
1587
1588         xid = GetXid();
1589
1590         if (file->private_data == NULL) {
1591                 FreeXid(xid);
1592                 return -EBADF;
1593         }
1594
1595         cFYI(1, ("readpage %p at offset %d 0x%x\n", 
1596                  page, (int)offset, (int)offset));
1597
1598         rc = cifs_readpage_worker(file, page, &offset);
1599
1600         unlock_page(page);
1601
1602         FreeXid(xid);
1603         return rc;
1604 }
1605
1606 /* We do not want to update the file size from server for inodes
1607    open for write - to avoid races with writepage extending
1608    the file - in the future we could consider allowing
1609    refreshing the inode only on increases in the file size 
1610    but this is tricky to do without racing with writebehind
1611    page caching in the current Linux kernel design */
1612 int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1613 {
1614         struct list_head *tmp;
1615         struct list_head *tmp1;
1616         struct cifsFileInfo *open_file = NULL;
1617         int rc = TRUE;
1618
1619         if (cifsInode == NULL)
1620                 return rc;
1621
1622         read_lock(&GlobalSMBSeslock); 
1623         list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {            
1624                 open_file = list_entry(tmp, struct cifsFileInfo, flist);
1625                 if (open_file == NULL)
1626                         break;
1627                 if (open_file->closePend)
1628                         continue;
1629         /* We check if file is open for writing,   
1630            BB we could supplement this with a check to see if file size
1631            changes have been flushed to server - ie inode metadata dirty */
1632                 if ((open_file->pfile) && 
1633                     ((open_file->pfile->f_flags & O_RDWR) || 
1634                     (open_file->pfile->f_flags & O_WRONLY))) {
1635                         rc = FALSE;
1636                         break;
1637                 }
1638                 if (tmp->next == NULL) {
1639                         cFYI(1, ("File instance %p removed", tmp));
1640                         break;
1641                 }
1642         }
1643         read_unlock(&GlobalSMBSeslock);
1644         return rc;
1645 }
1646
1647
1648 static int cifs_prepare_write(struct file *file, struct page *page,
1649         unsigned from, unsigned to)
1650 {
1651         int rc = 0;
1652         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1653         cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1654         if (!PageUptodate(page)) {
1655         /*      if (to - from != PAGE_CACHE_SIZE) {
1656                         void *kaddr = kmap_atomic(page, KM_USER0);
1657                         memset(kaddr, 0, from);
1658                         memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1659                         flush_dcache_page(page);
1660                         kunmap_atomic(kaddr, KM_USER0);
1661                 } */
1662                 /* If we are writing a full page it will be up to date,
1663                    no need to read from the server */
1664                 if ((to == PAGE_CACHE_SIZE) && (from == 0))
1665                         SetPageUptodate(page);
1666
1667                 /* might as well read a page, it is fast enough */
1668                 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
1669                         rc = cifs_readpage_worker(file, page, &offset);
1670                 } else {
1671                 /* should we try using another file handle if there is one -
1672                    how would we lock it to prevent close of that handle
1673                    racing with this read?
1674                    In any case this will be written out by commit_write */
1675                 }
1676         }
1677
1678         /* BB should we pass any errors back? 
1679            e.g. if we do not have read access to the file */
1680         return 0;
1681 }
1682
1683 struct address_space_operations cifs_addr_ops = {
1684         .readpage = cifs_readpage,
1685         .readpages = cifs_readpages,
1686         .writepage = cifs_writepage,
1687         .prepare_write = cifs_prepare_write,
1688         .commit_write = cifs_commit_write,
1689         .set_page_dirty = __set_page_dirty_nobuffers,
1690         /* .sync_page = cifs_sync_page, */
1691         /* .direct_IO = */
1692 };