[CIFS] Add posix (advisory) byte range locking support to cifs client
[safe/jmp/linux-2.6] / fs / cifs / file.c
1 /*
2  *   fs/cifs/file.c
3  *
4  *   vfs operations that deal with files
5  * 
6  *   Copyright (C) International Business Machines  Corp., 2002,2003
7  *   Author(s): Steve French (sfrench@us.ibm.com)
8  *
9  *   This library is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU Lesser General Public License as published
11  *   by the Free Software Foundation; either version 2.1 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This library is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU Lesser General Public License for more details.
18  *
19  *   You should have received a copy of the GNU Lesser General Public License
20  *   along with this library; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23 #include <linux/fs.h>
24 #include <linux/backing-dev.h>
25 #include <linux/stat.h>
26 #include <linux/fcntl.h>
27 #include <linux/mpage.h>
28 #include <linux/pagemap.h>
29 #include <linux/pagevec.h>
30 #include <linux/smp_lock.h>
31 #include <linux/writeback.h>
32 #include <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                         if(pCFileStruct->srch_inf.smallBuf)
559                                 cifs_small_buf_release(ptmp);
560                         else
561                                 cifs_buf_release(ptmp);
562                 }
563                 ptmp = pCFileStruct->search_resume_name;
564                 if (ptmp) {
565                         cFYI(1, ("closedir free resume name"));
566                         pCFileStruct->search_resume_name = NULL;
567                         kfree(ptmp);
568                 }
569                 kfree(file->private_data);
570                 file->private_data = NULL;
571         }
572         /* BB can we lock the filestruct while this is going on? */
573         FreeXid(xid);
574         return rc;
575 }
576
577 int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
578 {
579         int rc, xid;
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         __u16 netfid;
587         __u8 lockType = LOCKING_ANDX_LARGE_FILES;
588
589         length = 1 + pfLock->fl_end - pfLock->fl_start;
590         rc = -EACCES;
591         xid = GetXid();
592
593         cFYI(1, ("Lock parm: 0x%x flockflags: "
594                  "0x%x flocktype: 0x%x start: %lld end: %lld",
595                 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
596                 pfLock->fl_end));
597
598         if (pfLock->fl_flags & FL_POSIX)
599                 cFYI(1, ("Posix"));
600         if (pfLock->fl_flags & FL_FLOCK)
601                 cFYI(1, ("Flock"));
602         if (pfLock->fl_flags & FL_SLEEP) {
603                 cFYI(1, ("Blocking lock"));
604                 wait_flag = TRUE;
605         }
606         if (pfLock->fl_flags & FL_ACCESS)
607                 cFYI(1, ("Process suspended by mandatory locking - "
608                          "not implemented yet "));
609         if (pfLock->fl_flags & FL_LEASE)
610                 cFYI(1, ("Lease on file - not implemented yet"));
611         if (pfLock->fl_flags & 
612             (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
613                 cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags));
614
615         if (pfLock->fl_type == F_WRLCK) {
616                 cFYI(1, ("F_WRLCK "));
617                 numLock = 1;
618         } else if (pfLock->fl_type == F_UNLCK) {
619                 cFYI(1, ("F_UNLCK"));
620                 numUnlock = 1;
621                 /* Check if unlock includes more than
622                 one lock range */
623         } else if (pfLock->fl_type == F_RDLCK) {
624                 cFYI(1, ("F_RDLCK"));
625                 lockType |= LOCKING_ANDX_SHARED_LOCK;
626                 numLock = 1;
627         } else if (pfLock->fl_type == F_EXLCK) {
628                 cFYI(1, ("F_EXLCK"));
629                 numLock = 1;
630         } else if (pfLock->fl_type == F_SHLCK) {
631                 cFYI(1, ("F_SHLCK"));
632                 lockType |= LOCKING_ANDX_SHARED_LOCK;
633                 numLock = 1;
634         } else
635                 cFYI(1, ("Unknown type of lock"));
636
637         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
638         pTcon = cifs_sb->tcon;
639
640         if (file->private_data == NULL) {
641                 FreeXid(xid);
642                 return -EBADF;
643         }
644         netfid = ((struct cifsFileInfo *)file->private_data)->netfid;
645
646
647         /* BB add code here to normalize offset and length to
648         account for negative length which we can not accept over the
649         wire */
650         if (IS_GETLK(cmd)) {
651                 if(experimEnabled && 
652                    (cifs_sb->tcon->ses->capabilities & CAP_UNIX)) {
653                         int posix_lock_type;
654                         if(lockType & LOCKING_ANDX_SHARED_LOCK)
655                                 posix_lock_type = CIFS_RDLCK;
656                         else
657                                 posix_lock_type = CIFS_WRLCK;
658                         rc = CIFSSMBPosixLock(xid, pTcon, netfid, 1 /* get */,
659                                         length, pfLock->fl_start,
660                                         posix_lock_type, wait_flag);
661                         FreeXid(xid);
662                         return rc;
663                 }
664
665                 /* BB we could chain these into one lock request BB */
666                 rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
667                                  0, 1, lockType, 0 /* wait flag */ );
668                 if (rc == 0) {
669                         rc = CIFSSMBLock(xid, pTcon, netfid, length, 
670                                          pfLock->fl_start, 1 /* numUnlock */ ,
671                                          0 /* numLock */ , lockType,
672                                          0 /* wait flag */ );
673                         pfLock->fl_type = F_UNLCK;
674                         if (rc != 0)
675                                 cERROR(1, ("Error unlocking previously locked "
676                                            "range %d during test of lock", rc));
677                         rc = 0;
678
679                 } else {
680                         /* if rc == ERR_SHARING_VIOLATION ? */
681                         rc = 0; /* do not change lock type to unlock
682                                    since range in use */
683                 }
684
685                 FreeXid(xid);
686                 return rc;
687         }
688         if (experimEnabled &&
689                 (cifs_sb->tcon->ses->capabilities & CAP_UNIX)) {
690                 int posix_lock_type;
691                 if(lockType & LOCKING_ANDX_SHARED_LOCK)
692                         posix_lock_type = CIFS_RDLCK;
693                 else
694                         posix_lock_type = CIFS_WRLCK;
695                 
696                 if(numUnlock == 1)
697                         posix_lock_type |= CIFS_UNLCK;
698                 else if(numLock == 0) {
699                         /* if no lock or unlock then nothing
700                         to do since we do not know what it is */
701                         FreeXid(xid);
702                         return -EOPNOTSUPP;
703                 }
704                 rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */,
705                                       length, pfLock->fl_start,
706                                       posix_lock_type, wait_flag);
707         } else
708                 rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start,
709                                 numUnlock, numLock, lockType, wait_flag);
710         if (pfLock->fl_flags & FL_POSIX)
711                 posix_lock_file_wait(file, pfLock);
712         FreeXid(xid);
713         return rc;
714 }
715
716 ssize_t cifs_user_write(struct file *file, const char __user *write_data,
717         size_t write_size, loff_t *poffset)
718 {
719         int rc = 0;
720         unsigned int bytes_written = 0;
721         unsigned int total_written;
722         struct cifs_sb_info *cifs_sb;
723         struct cifsTconInfo *pTcon;
724         int xid, long_op;
725         struct cifsFileInfo *open_file;
726
727         if (file->f_dentry == NULL)
728                 return -EBADF;
729
730         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
731         if (cifs_sb == NULL)
732                 return -EBADF;
733
734         pTcon = cifs_sb->tcon;
735
736         /* cFYI(1,
737            (" write %d bytes to offset %lld of %s", write_size,
738            *poffset, file->f_dentry->d_name.name)); */
739
740         if (file->private_data == NULL)
741                 return -EBADF;
742         else
743                 open_file = (struct cifsFileInfo *) file->private_data;
744         
745         xid = GetXid();
746         if (file->f_dentry->d_inode == NULL) {
747                 FreeXid(xid);
748                 return -EBADF;
749         }
750
751         if (*poffset > file->f_dentry->d_inode->i_size)
752                 long_op = 2; /* writes past end of file can take a long time */
753         else
754                 long_op = 1;
755
756         for (total_written = 0; write_size > total_written;
757              total_written += bytes_written) {
758                 rc = -EAGAIN;
759                 while (rc == -EAGAIN) {
760                         if (file->private_data == NULL) {
761                                 /* file has been closed on us */
762                                 FreeXid(xid);
763                         /* if we have gotten here we have written some data
764                            and blocked, and the file has been freed on us while
765                            we blocked so return what we managed to write */
766                                 return total_written;
767                         } 
768                         if (open_file->closePend) {
769                                 FreeXid(xid);
770                                 if (total_written)
771                                         return total_written;
772                                 else
773                                         return -EBADF;
774                         }
775                         if (open_file->invalidHandle) {
776                                 if ((file->f_dentry == NULL) ||
777                                     (file->f_dentry->d_inode == NULL)) {
778                                         FreeXid(xid);
779                                         return total_written;
780                                 }
781                                 /* we could deadlock if we called
782                                    filemap_fdatawait from here so tell
783                                    reopen_file not to flush data to server
784                                    now */
785                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
786                                         file, FALSE);
787                                 if (rc != 0)
788                                         break;
789                         }
790
791                         rc = CIFSSMBWrite(xid, pTcon,
792                                 open_file->netfid,
793                                 min_t(const int, cifs_sb->wsize,
794                                       write_size - total_written),
795                                 *poffset, &bytes_written,
796                                 NULL, write_data + total_written, long_op);
797                 }
798                 if (rc || (bytes_written == 0)) {
799                         if (total_written)
800                                 break;
801                         else {
802                                 FreeXid(xid);
803                                 return rc;
804                         }
805                 } else
806                         *poffset += bytes_written;
807                 long_op = FALSE; /* subsequent writes fast -
808                                     15 seconds is plenty */
809         }
810
811         cifs_stats_bytes_written(pTcon, total_written);
812
813         /* since the write may have blocked check these pointers again */
814         if (file->f_dentry) {
815                 if (file->f_dentry->d_inode) {
816                         struct inode *inode = file->f_dentry->d_inode;
817                         inode->i_ctime = inode->i_mtime =
818                                 current_fs_time(inode->i_sb);
819                         if (total_written > 0) {
820                                 if (*poffset > file->f_dentry->d_inode->i_size)
821                                         i_size_write(file->f_dentry->d_inode,
822                                         *poffset);
823                         }
824                         mark_inode_dirty_sync(file->f_dentry->d_inode);
825                 }
826         }
827         FreeXid(xid);
828         return total_written;
829 }
830
831 static ssize_t cifs_write(struct file *file, const char *write_data,
832         size_t write_size, loff_t *poffset)
833 {
834         int rc = 0;
835         unsigned int bytes_written = 0;
836         unsigned int total_written;
837         struct cifs_sb_info *cifs_sb;
838         struct cifsTconInfo *pTcon;
839         int xid, long_op;
840         struct cifsFileInfo *open_file;
841
842         if (file->f_dentry == NULL)
843                 return -EBADF;
844
845         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
846         if (cifs_sb == NULL)
847                 return -EBADF;
848
849         pTcon = cifs_sb->tcon;
850
851         cFYI(1,("write %zd bytes to offset %lld of %s", write_size,
852            *poffset, file->f_dentry->d_name.name));
853
854         if (file->private_data == NULL)
855                 return -EBADF;
856         else
857                 open_file = (struct cifsFileInfo *)file->private_data;
858         
859         xid = GetXid();
860         if (file->f_dentry->d_inode == NULL) {
861                 FreeXid(xid);
862                 return -EBADF;
863         }
864
865         if (*poffset > file->f_dentry->d_inode->i_size)
866                 long_op = 2; /* writes past end of file can take a long time */
867         else
868                 long_op = 1;
869
870         for (total_written = 0; write_size > total_written;
871              total_written += bytes_written) {
872                 rc = -EAGAIN;
873                 while (rc == -EAGAIN) {
874                         if (file->private_data == NULL) {
875                                 /* file has been closed on us */
876                                 FreeXid(xid);
877                         /* if we have gotten here we have written some data
878                            and blocked, and the file has been freed on us
879                            while we blocked so return what we managed to 
880                            write */
881                                 return total_written;
882                         } 
883                         if (open_file->closePend) {
884                                 FreeXid(xid);
885                                 if (total_written)
886                                         return total_written;
887                                 else
888                                         return -EBADF;
889                         }
890                         if (open_file->invalidHandle) {
891                                 if ((file->f_dentry == NULL) ||
892                                    (file->f_dentry->d_inode == NULL)) {
893                                         FreeXid(xid);
894                                         return total_written;
895                                 }
896                                 /* we could deadlock if we called
897                                    filemap_fdatawait from here so tell
898                                    reopen_file not to flush data to 
899                                    server now */
900                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
901                                         file, FALSE);
902                                 if (rc != 0)
903                                         break;
904                         }
905                         /* BB FIXME We can not sign across two buffers yet */
906                         if((pTcon->ses->server->secMode & 
907                          (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0) {
908                                 struct kvec iov[2];
909                                 unsigned int len;
910
911                                 len = min((size_t)cifs_sb->wsize,
912                                           write_size - total_written);
913                                 /* iov[0] is reserved for smb header */
914                                 iov[1].iov_base = (char *)write_data +
915                                                   total_written;
916                                 iov[1].iov_len = len;
917                                 rc = CIFSSMBWrite2(xid, pTcon,
918                                                 open_file->netfid, len,
919                                                 *poffset, &bytes_written,
920                                                 iov, 1, long_op);
921                         } else
922                         /* BB FIXME fixup indentation of line below */
923                         rc = CIFSSMBWrite(xid, pTcon,
924                                  open_file->netfid,
925                                  min_t(const int, cifs_sb->wsize, 
926                                        write_size - total_written),
927                                  *poffset, &bytes_written,
928                                  write_data + total_written, NULL, long_op);
929                 }
930                 if (rc || (bytes_written == 0)) {
931                         if (total_written)
932                                 break;
933                         else {
934                                 FreeXid(xid);
935                                 return rc;
936                         }
937                 } else
938                         *poffset += bytes_written;
939                 long_op = FALSE; /* subsequent writes fast - 
940                                     15 seconds is plenty */
941         }
942
943         cifs_stats_bytes_written(pTcon, total_written);
944
945         /* since the write may have blocked check these pointers again */
946         if (file->f_dentry) {
947                 if (file->f_dentry->d_inode) {
948                         file->f_dentry->d_inode->i_ctime = 
949                         file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
950                         if (total_written > 0) {
951                                 if (*poffset > file->f_dentry->d_inode->i_size)
952                                         i_size_write(file->f_dentry->d_inode, 
953                                                      *poffset);
954                         }
955                         mark_inode_dirty_sync(file->f_dentry->d_inode);
956                 }
957         }
958         FreeXid(xid);
959         return total_written;
960 }
961
962 struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
963 {
964         struct cifsFileInfo *open_file;
965         int rc;
966
967         read_lock(&GlobalSMBSeslock);
968         list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
969                 if (open_file->closePend)
970                         continue;
971                 if (open_file->pfile &&
972                     ((open_file->pfile->f_flags & O_RDWR) ||
973                      (open_file->pfile->f_flags & O_WRONLY))) {
974                         atomic_inc(&open_file->wrtPending);
975                         read_unlock(&GlobalSMBSeslock);
976                         if((open_file->invalidHandle) && 
977                            (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
978                                 rc = cifs_reopen_file(&cifs_inode->vfs_inode, 
979                                                       open_file->pfile, FALSE);
980                                 /* if it fails, try another handle - might be */
981                                 /* dangerous to hold up writepages with retry */
982                                 if(rc) {
983                                         cFYI(1,("failed on reopen file in wp"));
984                                         read_lock(&GlobalSMBSeslock);
985                                         /* can not use this handle, no write
986                                         pending on this one after all */
987                                         atomic_dec
988                                              (&open_file->wrtPending);
989                                         continue;
990                                 }
991                         }
992                         return open_file;
993                 }
994         }
995         read_unlock(&GlobalSMBSeslock);
996         return NULL;
997 }
998
999 static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
1000 {
1001         struct address_space *mapping = page->mapping;
1002         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1003         char *write_data;
1004         int rc = -EFAULT;
1005         int bytes_written = 0;
1006         struct cifs_sb_info *cifs_sb;
1007         struct cifsTconInfo *pTcon;
1008         struct inode *inode;
1009         struct cifsFileInfo *open_file;
1010
1011         if (!mapping || !mapping->host)
1012                 return -EFAULT;
1013
1014         inode = page->mapping->host;
1015         cifs_sb = CIFS_SB(inode->i_sb);
1016         pTcon = cifs_sb->tcon;
1017
1018         offset += (loff_t)from;
1019         write_data = kmap(page);
1020         write_data += from;
1021
1022         if ((to > PAGE_CACHE_SIZE) || (from > to)) {
1023                 kunmap(page);
1024                 return -EIO;
1025         }
1026
1027         /* racing with truncate? */
1028         if (offset > mapping->host->i_size) {
1029                 kunmap(page);
1030                 return 0; /* don't care */
1031         }
1032
1033         /* check to make sure that we are not extending the file */
1034         if (mapping->host->i_size - offset < (loff_t)to)
1035                 to = (unsigned)(mapping->host->i_size - offset); 
1036
1037         open_file = find_writable_file(CIFS_I(mapping->host));
1038         if (open_file) {
1039                 bytes_written = cifs_write(open_file->pfile, write_data,
1040                                            to-from, &offset);
1041                 atomic_dec(&open_file->wrtPending);
1042                 /* Does mm or vfs already set times? */
1043                 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
1044                 if ((bytes_written > 0) && (offset)) {
1045                         rc = 0;
1046                 } else if (bytes_written < 0) {
1047                         if (rc != -EBADF)
1048                                 rc = bytes_written;
1049                 }
1050         } else {
1051                 cFYI(1, ("No writeable filehandles for inode"));
1052                 rc = -EIO;
1053         }
1054
1055         kunmap(page);
1056         return rc;
1057 }
1058
1059 static int cifs_writepages(struct address_space *mapping,
1060                            struct writeback_control *wbc)
1061 {
1062         struct backing_dev_info *bdi = mapping->backing_dev_info;
1063         unsigned int bytes_to_write;
1064         unsigned int bytes_written;
1065         struct cifs_sb_info *cifs_sb;
1066         int done = 0;
1067         pgoff_t end = -1;
1068         pgoff_t index;
1069         int is_range = 0;
1070         struct kvec iov[32];
1071         int len;
1072         int n_iov = 0;
1073         pgoff_t next;
1074         int nr_pages;
1075         __u64 offset = 0;
1076         struct cifsFileInfo *open_file;
1077         struct page *page;
1078         struct pagevec pvec;
1079         int rc = 0;
1080         int scanned = 0;
1081         int xid;
1082
1083         cifs_sb = CIFS_SB(mapping->host->i_sb);
1084         
1085         /*
1086          * If wsize is smaller that the page cache size, default to writing
1087          * one page at a time via cifs_writepage
1088          */
1089         if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1090                 return generic_writepages(mapping, wbc);
1091
1092         /* BB FIXME we do not have code to sign across multiple buffers yet,
1093            so go to older writepage style write which we can sign if needed */
1094         if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
1095                 if(cifs_sb->tcon->ses->server->secMode &
1096                           (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1097                         return generic_writepages(mapping, wbc);
1098
1099         /*
1100          * BB: Is this meaningful for a non-block-device file system?
1101          * If it is, we should test it again after we do I/O
1102          */
1103         if (wbc->nonblocking && bdi_write_congested(bdi)) {
1104                 wbc->encountered_congestion = 1;
1105                 return 0;
1106         }
1107
1108         xid = GetXid();
1109
1110         pagevec_init(&pvec, 0);
1111         if (wbc->sync_mode == WB_SYNC_NONE)
1112                 index = mapping->writeback_index; /* Start from prev offset */
1113         else {
1114                 index = 0;
1115                 scanned = 1;
1116         }
1117         if (wbc->start || wbc->end) {
1118                 index = wbc->start >> PAGE_CACHE_SHIFT;
1119                 end = wbc->end >> PAGE_CACHE_SHIFT;
1120                 is_range = 1;
1121                 scanned = 1;
1122         }
1123 retry:
1124         while (!done && (index <= end) &&
1125                (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
1126                         PAGECACHE_TAG_DIRTY,
1127                         min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1))) {
1128                 int first;
1129                 unsigned int i;
1130
1131                 first = -1;
1132                 next = 0;
1133                 n_iov = 0;
1134                 bytes_to_write = 0;
1135
1136                 for (i = 0; i < nr_pages; i++) {
1137                         page = pvec.pages[i];
1138                         /*
1139                          * At this point we hold neither mapping->tree_lock nor
1140                          * lock on the page itself: the page may be truncated or
1141                          * invalidated (changing page->mapping to NULL), or even
1142                          * swizzled back from swapper_space to tmpfs file
1143                          * mapping
1144                          */
1145
1146                         if (first < 0)
1147                                 lock_page(page);
1148                         else if (TestSetPageLocked(page))
1149                                 break;
1150
1151                         if (unlikely(page->mapping != mapping)) {
1152                                 unlock_page(page);
1153                                 break;
1154                         }
1155
1156                         if (unlikely(is_range) && (page->index > end)) {
1157                                 done = 1;
1158                                 unlock_page(page);
1159                                 break;
1160                         }
1161
1162                         if (next && (page->index != next)) {
1163                                 /* Not next consecutive page */
1164                                 unlock_page(page);
1165                                 break;
1166                         }
1167
1168                         if (wbc->sync_mode != WB_SYNC_NONE)
1169                                 wait_on_page_writeback(page);
1170
1171                         if (PageWriteback(page) ||
1172                                         !test_clear_page_dirty(page)) {
1173                                 unlock_page(page);
1174                                 break;
1175                         }
1176
1177                         if (page_offset(page) >= mapping->host->i_size) {
1178                                 done = 1;
1179                                 unlock_page(page);
1180                                 break;
1181                         }
1182
1183                         /*
1184                          * BB can we get rid of this?  pages are held by pvec
1185                          */
1186                         page_cache_get(page);
1187
1188                         len = min(mapping->host->i_size - page_offset(page),
1189                                   (loff_t)PAGE_CACHE_SIZE);
1190
1191                         /* reserve iov[0] for the smb header */
1192                         n_iov++;
1193                         iov[n_iov].iov_base = kmap(page);
1194                         iov[n_iov].iov_len = len;
1195                         bytes_to_write += len;
1196
1197                         if (first < 0) {
1198                                 first = i;
1199                                 offset = page_offset(page);
1200                         }
1201                         next = page->index + 1;
1202                         if (bytes_to_write + PAGE_CACHE_SIZE > cifs_sb->wsize)
1203                                 break;
1204                 }
1205                 if (n_iov) {
1206                         /* Search for a writable handle every time we call
1207                          * CIFSSMBWrite2.  We can't rely on the last handle
1208                          * we used to still be valid
1209                          */
1210                         open_file = find_writable_file(CIFS_I(mapping->host));
1211                         if (!open_file) {
1212                                 cERROR(1, ("No writable handles for inode"));
1213                                 rc = -EBADF;
1214                         } else {
1215                                 rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
1216                                                    open_file->netfid,
1217                                                    bytes_to_write, offset,
1218                                                    &bytes_written, iov, n_iov,
1219                                                    1);
1220                                 atomic_dec(&open_file->wrtPending);
1221                                 if (rc || bytes_written < bytes_to_write) {
1222                                         cERROR(1,("Write2 ret %d, written = %d",
1223                                                   rc, bytes_written));
1224                                         /* BB what if continued retry is
1225                                            requested via mount flags? */
1226                                         set_bit(AS_EIO, &mapping->flags);
1227                                 } else {
1228                                         cifs_stats_bytes_written(cifs_sb->tcon,
1229                                                                  bytes_written);
1230                                 }
1231                         }
1232                         for (i = 0; i < n_iov; i++) {
1233                                 page = pvec.pages[first + i];
1234                                 /* Should we also set page error on
1235                                 success rc but too little data written? */
1236                                 /* BB investigate retry logic on temporary
1237                                 server crash cases and how recovery works
1238                                 when page marked as error */ 
1239                                 if(rc)
1240                                         SetPageError(page);
1241                                 kunmap(page);
1242                                 unlock_page(page);
1243                                 page_cache_release(page);
1244                         }
1245                         if ((wbc->nr_to_write -= n_iov) <= 0)
1246                                 done = 1;
1247                         index = next;
1248                 }
1249                 pagevec_release(&pvec);
1250         }
1251         if (!scanned && !done) {
1252                 /*
1253                  * We hit the last page and there is more work to be done: wrap
1254                  * back to the start of the file
1255                  */
1256                 scanned = 1;
1257                 index = 0;
1258                 goto retry;
1259         }
1260         if (!is_range)
1261                 mapping->writeback_index = index;
1262
1263         FreeXid(xid);
1264
1265         return rc;
1266 }
1267
1268 static int cifs_writepage(struct page* page, struct writeback_control *wbc)
1269 {
1270         int rc = -EFAULT;
1271         int xid;
1272
1273         xid = GetXid();
1274 /* BB add check for wbc flags */
1275         page_cache_get(page);
1276         if (!PageUptodate(page)) {
1277                 cFYI(1, ("ppw - page not up to date"));
1278         }
1279         
1280         rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
1281         SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
1282         unlock_page(page);
1283         page_cache_release(page);       
1284         FreeXid(xid);
1285         return rc;
1286 }
1287
1288 static int cifs_commit_write(struct file *file, struct page *page,
1289         unsigned offset, unsigned to)
1290 {
1291         int xid;
1292         int rc = 0;
1293         struct inode *inode = page->mapping->host;
1294         loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
1295         char *page_data;
1296
1297         xid = GetXid();
1298         cFYI(1, ("commit write for page %p up to position %lld for %d", 
1299                  page, position, to));
1300         if (position > inode->i_size) {
1301                 i_size_write(inode, position);
1302                 /* if (file->private_data == NULL) {
1303                         rc = -EBADF;
1304                 } else {
1305                         open_file = (struct cifsFileInfo *)file->private_data;
1306                         cifs_sb = CIFS_SB(inode->i_sb);
1307                         rc = -EAGAIN;
1308                         while (rc == -EAGAIN) {
1309                                 if ((open_file->invalidHandle) && 
1310                                     (!open_file->closePend)) {
1311                                         rc = cifs_reopen_file(
1312                                                 file->f_dentry->d_inode, file);
1313                                         if (rc != 0)
1314                                                 break;
1315                                 }
1316                                 if (!open_file->closePend) {
1317                                         rc = CIFSSMBSetFileSize(xid,
1318                                                 cifs_sb->tcon, position,
1319                                                 open_file->netfid,
1320                                                 open_file->pid, FALSE);
1321                                 } else {
1322                                         rc = -EBADF;
1323                                         break;
1324                                 }
1325                         }
1326                         cFYI(1, (" SetEOF (commit write) rc = %d", rc));
1327                 } */
1328         }
1329         if (!PageUptodate(page)) {
1330                 position =  ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
1331                 /* can not rely on (or let) writepage write this data */
1332                 if (to < offset) {
1333                         cFYI(1, ("Illegal offsets, can not copy from %d to %d",
1334                                 offset, to));
1335                         FreeXid(xid);
1336                         return rc;
1337                 }
1338                 /* this is probably better than directly calling
1339                    partialpage_write since in this function the file handle is
1340                    known which we might as well leverage */
1341                 /* BB check if anything else missing out of ppw
1342                    such as updating last write time */
1343                 page_data = kmap(page);
1344                 rc = cifs_write(file, page_data + offset, to-offset,
1345                                 &position);
1346                 if (rc > 0)
1347                         rc = 0;
1348                 /* else if (rc < 0) should we set writebehind rc? */
1349                 kunmap(page);
1350         } else {        
1351                 set_page_dirty(page);
1352         }
1353
1354         FreeXid(xid);
1355         return rc;
1356 }
1357
1358 int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1359 {
1360         int xid;
1361         int rc = 0;
1362         struct inode *inode = file->f_dentry->d_inode;
1363
1364         xid = GetXid();
1365
1366         cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 
1367                 dentry->d_name.name, datasync));
1368         
1369         rc = filemap_fdatawrite(inode->i_mapping);
1370         if (rc == 0)
1371                 CIFS_I(inode)->write_behind_rc = 0;
1372         FreeXid(xid);
1373         return rc;
1374 }
1375
1376 /* static int cifs_sync_page(struct page *page)
1377 {
1378         struct address_space *mapping;
1379         struct inode *inode;
1380         unsigned long index = page->index;
1381         unsigned int rpages = 0;
1382         int rc = 0;
1383
1384         cFYI(1, ("sync page %p",page));
1385         mapping = page->mapping;
1386         if (!mapping)
1387                 return 0;
1388         inode = mapping->host;
1389         if (!inode)
1390                 return 0; */
1391
1392 /*      fill in rpages then 
1393         result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
1394
1395 /*      cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
1396
1397         if (rc < 0)
1398                 return rc;
1399         return 0;
1400 } */
1401
1402 /*
1403  * As file closes, flush all cached write data for this inode checking
1404  * for write behind errors.
1405  */
1406 int cifs_flush(struct file *file)
1407 {
1408         struct inode * inode = file->f_dentry->d_inode;
1409         int rc = 0;
1410
1411         /* Rather than do the steps manually:
1412            lock the inode for writing
1413            loop through pages looking for write behind data (dirty pages)
1414            coalesce into contiguous 16K (or smaller) chunks to write to server
1415            send to server (prefer in parallel)
1416            deal with writebehind errors
1417            unlock inode for writing
1418            filemapfdatawrite appears easier for the time being */
1419
1420         rc = filemap_fdatawrite(inode->i_mapping);
1421         if (!rc) /* reset wb rc if we were able to write out dirty pages */
1422                 CIFS_I(inode)->write_behind_rc = 0;
1423                 
1424         cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc));
1425
1426         return rc;
1427 }
1428
1429 ssize_t cifs_user_read(struct file *file, char __user *read_data,
1430         size_t read_size, loff_t *poffset)
1431 {
1432         int rc = -EACCES;
1433         unsigned int bytes_read = 0;
1434         unsigned int total_read = 0;
1435         unsigned int current_read_size;
1436         struct cifs_sb_info *cifs_sb;
1437         struct cifsTconInfo *pTcon;
1438         int xid;
1439         struct cifsFileInfo *open_file;
1440         char *smb_read_data;
1441         char __user *current_offset;
1442         struct smb_com_read_rsp *pSMBr;
1443
1444         xid = GetXid();
1445         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1446         pTcon = cifs_sb->tcon;
1447
1448         if (file->private_data == NULL) {
1449                 FreeXid(xid);
1450                 return -EBADF;
1451         }
1452         open_file = (struct cifsFileInfo *)file->private_data;
1453
1454         if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
1455                 cFYI(1, ("attempting read on write only file instance"));
1456         }
1457         for (total_read = 0, current_offset = read_data;
1458              read_size > total_read;
1459              total_read += bytes_read, current_offset += bytes_read) {
1460                 current_read_size = min_t(const int, read_size - total_read, 
1461                                           cifs_sb->rsize);
1462                 rc = -EAGAIN;
1463                 smb_read_data = NULL;
1464                 while (rc == -EAGAIN) {
1465                         int buf_type = CIFS_NO_BUFFER;
1466                         if ((open_file->invalidHandle) && 
1467                             (!open_file->closePend)) {
1468                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1469                                         file, TRUE);
1470                                 if (rc != 0)
1471                                         break;
1472                         }
1473                         rc = CIFSSMBRead(xid, pTcon,
1474                                          open_file->netfid,
1475                                          current_read_size, *poffset,
1476                                          &bytes_read, &smb_read_data,
1477                                          &buf_type);
1478                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1479                         if (smb_read_data) {
1480                                 if (copy_to_user(current_offset,
1481                                                 smb_read_data +
1482                                                 4 /* RFC1001 length field */ +
1483                                                 le16_to_cpu(pSMBr->DataOffset),
1484                                                 bytes_read)) {
1485                                         rc = -EFAULT;
1486                                 }
1487
1488                                 if(buf_type == CIFS_SMALL_BUFFER)
1489                                         cifs_small_buf_release(smb_read_data);
1490                                 else if(buf_type == CIFS_LARGE_BUFFER)
1491                                         cifs_buf_release(smb_read_data);
1492                                 smb_read_data = NULL;
1493                         }
1494                 }
1495                 if (rc || (bytes_read == 0)) {
1496                         if (total_read) {
1497                                 break;
1498                         } else {
1499                                 FreeXid(xid);
1500                                 return rc;
1501                         }
1502                 } else {
1503                         cifs_stats_bytes_read(pTcon, bytes_read);
1504                         *poffset += bytes_read;
1505                 }
1506         }
1507         FreeXid(xid);
1508         return total_read;
1509 }
1510
1511
1512 static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1513         loff_t *poffset)
1514 {
1515         int rc = -EACCES;
1516         unsigned int bytes_read = 0;
1517         unsigned int total_read;
1518         unsigned int current_read_size;
1519         struct cifs_sb_info *cifs_sb;
1520         struct cifsTconInfo *pTcon;
1521         int xid;
1522         char *current_offset;
1523         struct cifsFileInfo *open_file;
1524         int buf_type = CIFS_NO_BUFFER;
1525
1526         xid = GetXid();
1527         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1528         pTcon = cifs_sb->tcon;
1529
1530         if (file->private_data == NULL) {
1531                 FreeXid(xid);
1532                 return -EBADF;
1533         }
1534         open_file = (struct cifsFileInfo *)file->private_data;
1535
1536         if ((file->f_flags & O_ACCMODE) == O_WRONLY)
1537                 cFYI(1, ("attempting read on write only file instance"));
1538
1539         for (total_read = 0, current_offset = read_data; 
1540              read_size > total_read;
1541              total_read += bytes_read, current_offset += bytes_read) {
1542                 current_read_size = min_t(const int, read_size - total_read,
1543                                           cifs_sb->rsize);
1544                 /* For windows me and 9x we do not want to request more
1545                 than it negotiated since it will refuse the read then */
1546                 if((pTcon->ses) && 
1547                         !(pTcon->ses->capabilities & CAP_LARGE_FILES)) {
1548                         current_read_size = min_t(const int, current_read_size,
1549                                         pTcon->ses->server->maxBuf - 128);
1550                 }
1551                 rc = -EAGAIN;
1552                 while (rc == -EAGAIN) {
1553                         if ((open_file->invalidHandle) && 
1554                             (!open_file->closePend)) {
1555                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1556                                         file, TRUE);
1557                                 if (rc != 0)
1558                                         break;
1559                         }
1560                         rc = CIFSSMBRead(xid, pTcon,
1561                                          open_file->netfid,
1562                                          current_read_size, *poffset,
1563                                          &bytes_read, &current_offset,
1564                                          &buf_type);
1565                 }
1566                 if (rc || (bytes_read == 0)) {
1567                         if (total_read) {
1568                                 break;
1569                         } else {
1570                                 FreeXid(xid);
1571                                 return rc;
1572                         }
1573                 } else {
1574                         cifs_stats_bytes_read(pTcon, total_read);
1575                         *poffset += bytes_read;
1576                 }
1577         }
1578         FreeXid(xid);
1579         return total_read;
1580 }
1581
1582 int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1583 {
1584         struct dentry *dentry = file->f_dentry;
1585         int rc, xid;
1586
1587         xid = GetXid();
1588         rc = cifs_revalidate(dentry);
1589         if (rc) {
1590                 cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
1591                 FreeXid(xid);
1592                 return rc;
1593         }
1594         rc = generic_file_mmap(file, vma);
1595         FreeXid(xid);
1596         return rc;
1597 }
1598
1599
1600 static void cifs_copy_cache_pages(struct address_space *mapping, 
1601         struct list_head *pages, int bytes_read, char *data,
1602         struct pagevec *plru_pvec)
1603 {
1604         struct page *page;
1605         char *target;
1606
1607         while (bytes_read > 0) {
1608                 if (list_empty(pages))
1609                         break;
1610
1611                 page = list_entry(pages->prev, struct page, lru);
1612                 list_del(&page->lru);
1613
1614                 if (add_to_page_cache(page, mapping, page->index,
1615                                       GFP_KERNEL)) {
1616                         page_cache_release(page);
1617                         cFYI(1, ("Add page cache failed"));
1618                         data += PAGE_CACHE_SIZE;
1619                         bytes_read -= PAGE_CACHE_SIZE;
1620                         continue;
1621                 }
1622
1623                 target = kmap_atomic(page,KM_USER0);
1624
1625                 if (PAGE_CACHE_SIZE > bytes_read) {
1626                         memcpy(target, data, bytes_read);
1627                         /* zero the tail end of this partial page */
1628                         memset(target + bytes_read, 0, 
1629                                PAGE_CACHE_SIZE - bytes_read);
1630                         bytes_read = 0;
1631                 } else {
1632                         memcpy(target, data, PAGE_CACHE_SIZE);
1633                         bytes_read -= PAGE_CACHE_SIZE;
1634                 }
1635                 kunmap_atomic(target, KM_USER0);
1636
1637                 flush_dcache_page(page);
1638                 SetPageUptodate(page);
1639                 unlock_page(page);
1640                 if (!pagevec_add(plru_pvec, page))
1641                         __pagevec_lru_add(plru_pvec);
1642                 data += PAGE_CACHE_SIZE;
1643         }
1644         return;
1645 }
1646
1647 static int cifs_readpages(struct file *file, struct address_space *mapping,
1648         struct list_head *page_list, unsigned num_pages)
1649 {
1650         int rc = -EACCES;
1651         int xid;
1652         loff_t offset;
1653         struct page *page;
1654         struct cifs_sb_info *cifs_sb;
1655         struct cifsTconInfo *pTcon;
1656         int bytes_read = 0;
1657         unsigned int read_size,i;
1658         char *smb_read_data = NULL;
1659         struct smb_com_read_rsp *pSMBr;
1660         struct pagevec lru_pvec;
1661         struct cifsFileInfo *open_file;
1662         int buf_type = CIFS_NO_BUFFER;
1663
1664         xid = GetXid();
1665         if (file->private_data == NULL) {
1666                 FreeXid(xid);
1667                 return -EBADF;
1668         }
1669         open_file = (struct cifsFileInfo *)file->private_data;
1670         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1671         pTcon = cifs_sb->tcon;
1672
1673         pagevec_init(&lru_pvec, 0);
1674
1675         for (i = 0; i < num_pages; ) {
1676                 unsigned contig_pages;
1677                 struct page *tmp_page;
1678                 unsigned long expected_index;
1679
1680                 if (list_empty(page_list))
1681                         break;
1682
1683                 page = list_entry(page_list->prev, struct page, lru);
1684                 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1685
1686                 /* count adjacent pages that we will read into */
1687                 contig_pages = 0;
1688                 expected_index = 
1689                         list_entry(page_list->prev, struct page, lru)->index;
1690                 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1691                         if (tmp_page->index == expected_index) {
1692                                 contig_pages++;
1693                                 expected_index++;
1694                         } else
1695                                 break; 
1696                 }
1697                 if (contig_pages + i >  num_pages)
1698                         contig_pages = num_pages - i;
1699
1700                 /* for reads over a certain size could initiate async
1701                    read ahead */
1702
1703                 read_size = contig_pages * PAGE_CACHE_SIZE;
1704                 /* Read size needs to be in multiples of one page */
1705                 read_size = min_t(const unsigned int, read_size,
1706                                   cifs_sb->rsize & PAGE_CACHE_MASK);
1707
1708                 rc = -EAGAIN;
1709                 while (rc == -EAGAIN) {
1710                         if ((open_file->invalidHandle) && 
1711                             (!open_file->closePend)) {
1712                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1713                                         file, TRUE);
1714                                 if (rc != 0)
1715                                         break;
1716                         }
1717
1718                         rc = CIFSSMBRead(xid, pTcon,
1719                                          open_file->netfid,
1720                                          read_size, offset,
1721                                          &bytes_read, &smb_read_data,
1722                                          &buf_type);
1723                         /* BB more RC checks ? */
1724                         if (rc== -EAGAIN) {
1725                                 if (smb_read_data) {
1726                                         if(buf_type == CIFS_SMALL_BUFFER)
1727                                                 cifs_small_buf_release(smb_read_data);
1728                                         else if(buf_type == CIFS_LARGE_BUFFER)
1729                                                 cifs_buf_release(smb_read_data);
1730                                         smb_read_data = NULL;
1731                                 }
1732                         }
1733                 }
1734                 if ((rc < 0) || (smb_read_data == NULL)) {
1735                         cFYI(1, ("Read error in readpages: %d", rc));
1736                         /* clean up remaing pages off list */
1737                         while (!list_empty(page_list) && (i < num_pages)) {
1738                                 page = list_entry(page_list->prev, struct page,
1739                                                   lru);
1740                                 list_del(&page->lru);
1741                                 page_cache_release(page);
1742                         }
1743                         break;
1744                 } else if (bytes_read > 0) {
1745                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1746                         cifs_copy_cache_pages(mapping, page_list, bytes_read,
1747                                 smb_read_data + 4 /* RFC1001 hdr */ +
1748                                 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1749
1750                         i +=  bytes_read >> PAGE_CACHE_SHIFT;
1751                         cifs_stats_bytes_read(pTcon, bytes_read);
1752                         if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1753                                 i++; /* account for partial page */
1754
1755                                 /* server copy of file can have smaller size 
1756                                    than client */
1757                                 /* BB do we need to verify this common case ? 
1758                                    this case is ok - if we are at server EOF 
1759                                    we will hit it on next read */
1760
1761                         /* while (!list_empty(page_list) && (i < num_pages)) {
1762                                         page = list_entry(page_list->prev, 
1763                                                           struct page, list);
1764                                         list_del(&page->list);
1765                                         page_cache_release(page);
1766                                 }
1767                                 break; */
1768                         }
1769                 } else {
1770                         cFYI(1, ("No bytes read (%d) at offset %lld . "
1771                                  "Cleaning remaining pages from readahead list",
1772                                  bytes_read, offset));
1773                         /* BB turn off caching and do new lookup on 
1774                            file size at server? */
1775                         while (!list_empty(page_list) && (i < num_pages)) {
1776                                 page = list_entry(page_list->prev, struct page,
1777                                                   lru);
1778                                 list_del(&page->lru);
1779
1780                                 /* BB removeme - replace with zero of page? */
1781                                 page_cache_release(page);
1782                         }
1783                         break;
1784                 }
1785                 if (smb_read_data) {
1786                         if(buf_type == CIFS_SMALL_BUFFER)
1787                                 cifs_small_buf_release(smb_read_data);
1788                         else if(buf_type == CIFS_LARGE_BUFFER)
1789                                 cifs_buf_release(smb_read_data);
1790                         smb_read_data = NULL;
1791                 }
1792                 bytes_read = 0;
1793         }
1794
1795         pagevec_lru_add(&lru_pvec);
1796
1797 /* need to free smb_read_data buf before exit */
1798         if (smb_read_data) {
1799                 if(buf_type == CIFS_SMALL_BUFFER)
1800                         cifs_small_buf_release(smb_read_data);
1801                 else if(buf_type == CIFS_LARGE_BUFFER)
1802                         cifs_buf_release(smb_read_data);
1803                 smb_read_data = NULL;
1804         } 
1805
1806         FreeXid(xid);
1807         return rc;
1808 }
1809
1810 static int cifs_readpage_worker(struct file *file, struct page *page,
1811         loff_t *poffset)
1812 {
1813         char *read_data;
1814         int rc;
1815
1816         page_cache_get(page);
1817         read_data = kmap(page);
1818         /* for reads over a certain size could initiate async read ahead */
1819                                                                                                                            
1820         rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1821                                                                                                                            
1822         if (rc < 0)
1823                 goto io_error;
1824         else
1825                 cFYI(1, ("Bytes read %d ",rc));
1826                                                                                                                            
1827         file->f_dentry->d_inode->i_atime =
1828                 current_fs_time(file->f_dentry->d_inode->i_sb);
1829                                                                                                                            
1830         if (PAGE_CACHE_SIZE > rc)
1831                 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
1832
1833         flush_dcache_page(page);
1834         SetPageUptodate(page);
1835         rc = 0;
1836                                                                                                                            
1837 io_error:
1838         kunmap(page);
1839         page_cache_release(page);
1840         return rc;
1841 }
1842
1843 static int cifs_readpage(struct file *file, struct page *page)
1844 {
1845         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1846         int rc = -EACCES;
1847         int xid;
1848
1849         xid = GetXid();
1850
1851         if (file->private_data == NULL) {
1852                 FreeXid(xid);
1853                 return -EBADF;
1854         }
1855
1856         cFYI(1, ("readpage %p at offset %d 0x%x\n", 
1857                  page, (int)offset, (int)offset));
1858
1859         rc = cifs_readpage_worker(file, page, &offset);
1860
1861         unlock_page(page);
1862
1863         FreeXid(xid);
1864         return rc;
1865 }
1866
1867 /* We do not want to update the file size from server for inodes
1868    open for write - to avoid races with writepage extending
1869    the file - in the future we could consider allowing
1870    refreshing the inode only on increases in the file size 
1871    but this is tricky to do without racing with writebehind
1872    page caching in the current Linux kernel design */
1873 int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1874 {
1875         struct cifsFileInfo *open_file = NULL;
1876
1877         if (cifsInode)
1878                 open_file =  find_writable_file(cifsInode);
1879  
1880         if(open_file) {
1881                 struct cifs_sb_info *cifs_sb;
1882
1883                 /* there is not actually a write pending so let
1884                 this handle go free and allow it to
1885                 be closable if needed */
1886                 atomic_dec(&open_file->wrtPending);
1887
1888                 cifs_sb = CIFS_SB(cifsInode->vfs_inode.i_sb);
1889                 if ( cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO ) {
1890                         /* since no page cache to corrupt on directio 
1891                         we can change size safely */
1892                         return 1;
1893                 }
1894
1895                 return 0;
1896         } else
1897                 return 1;
1898 }
1899
1900 static int cifs_prepare_write(struct file *file, struct page *page,
1901         unsigned from, unsigned to)
1902 {
1903         int rc = 0;
1904         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1905         cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1906         if (!PageUptodate(page)) {
1907         /*      if (to - from != PAGE_CACHE_SIZE) {
1908                         void *kaddr = kmap_atomic(page, KM_USER0);
1909                         memset(kaddr, 0, from);
1910                         memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1911                         flush_dcache_page(page);
1912                         kunmap_atomic(kaddr, KM_USER0);
1913                 } */
1914                 /* If we are writing a full page it will be up to date,
1915                    no need to read from the server */
1916                 if ((to == PAGE_CACHE_SIZE) && (from == 0))
1917                         SetPageUptodate(page);
1918
1919                 /* might as well read a page, it is fast enough */
1920                 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
1921                         rc = cifs_readpage_worker(file, page, &offset);
1922                 } else {
1923                 /* should we try using another file handle if there is one -
1924                    how would we lock it to prevent close of that handle
1925                    racing with this read?
1926                    In any case this will be written out by commit_write */
1927                 }
1928         }
1929
1930         /* BB should we pass any errors back? 
1931            e.g. if we do not have read access to the file */
1932         return 0;
1933 }
1934
1935 struct address_space_operations cifs_addr_ops = {
1936         .readpage = cifs_readpage,
1937         .readpages = cifs_readpages,
1938         .writepage = cifs_writepage,
1939         .writepages = cifs_writepages,
1940         .prepare_write = cifs_prepare_write,
1941         .commit_write = cifs_commit_write,
1942         .set_page_dirty = __set_page_dirty_nobuffers,
1943         /* .sync_page = cifs_sync_page, */
1944         /* .direct_IO = */
1945 };