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