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