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