[PATCH] powerpc: Add support for the MPC83xx watchdog
[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    /* BB removeme BB */ cFYI(1, ("freeing smb buf in srch struct in closedir"));
557                         pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
558                         cifs_buf_release(ptmp);
559                 }
560                 ptmp = pCFileStruct->search_resume_name;
561                 if (ptmp) {
562    /* BB removeme BB */ cFYI(1, ("freeing resume name in closedir"));
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 #ifdef CONFIG_CIFS_EXPERIMENTAL
872                         /* BB FIXME We can not sign across two buffers yet */
873                         if((experimEnabled) && ((pTcon->ses->server->secMode & 
874                          (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) == 0)) {
875                                 struct kvec iov[2];
876                                 unsigned int len;
877
878                                 len = min((size_t)cifs_sb->wsize,
879                                           write_size - total_written);
880                                 /* iov[0] is reserved for smb header */
881                                 iov[1].iov_base = (char *)write_data +
882                                                   total_written;
883                                 iov[1].iov_len = len;
884                                 rc = CIFSSMBWrite2(xid, pTcon,
885                                                 open_file->netfid, len,
886                                                 *poffset, &bytes_written,
887                                                 iov, 1, long_op);
888                         } else
889                         /* BB FIXME fixup indentation of line below */
890 #endif                  
891                         rc = CIFSSMBWrite(xid, pTcon,
892                                  open_file->netfid,
893                                  min_t(const int, cifs_sb->wsize, 
894                                        write_size - total_written),
895                                  *poffset, &bytes_written,
896                                  write_data + total_written, NULL, long_op);
897                 }
898                 if (rc || (bytes_written == 0)) {
899                         if (total_written)
900                                 break;
901                         else {
902                                 FreeXid(xid);
903                                 return rc;
904                         }
905                 } else
906                         *poffset += bytes_written;
907                 long_op = FALSE; /* subsequent writes fast - 
908                                     15 seconds is plenty */
909         }
910
911         cifs_stats_bytes_written(pTcon, total_written);
912
913         /* since the write may have blocked check these pointers again */
914         if (file->f_dentry) {
915                 if (file->f_dentry->d_inode) {
916                         file->f_dentry->d_inode->i_ctime = 
917                         file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
918                         if (total_written > 0) {
919                                 if (*poffset > file->f_dentry->d_inode->i_size)
920                                         i_size_write(file->f_dentry->d_inode, 
921                                                      *poffset);
922                         }
923                         mark_inode_dirty_sync(file->f_dentry->d_inode);
924                 }
925         }
926         FreeXid(xid);
927         return total_written;
928 }
929
930 struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
931 {
932         struct cifsFileInfo *open_file;
933         int rc;
934
935         read_lock(&GlobalSMBSeslock);
936         list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
937                 if (open_file->closePend)
938                         continue;
939                 if (open_file->pfile &&
940                     ((open_file->pfile->f_flags & O_RDWR) ||
941                      (open_file->pfile->f_flags & O_WRONLY))) {
942                         atomic_inc(&open_file->wrtPending);
943                         read_unlock(&GlobalSMBSeslock);
944                         if((open_file->invalidHandle) && 
945                            (!open_file->closePend) /* BB fixme -since the second clause can not be true remove it BB */) {
946                                 rc = cifs_reopen_file(&cifs_inode->vfs_inode, 
947                                                       open_file->pfile, FALSE);
948                                 /* if it fails, try another handle - might be */
949                                 /* dangerous to hold up writepages with retry */
950                                 if(rc) {
951                                         cFYI(1,("failed on reopen file in wp"));
952                                         read_lock(&GlobalSMBSeslock);
953                                         /* can not use this handle, no write
954                                         pending on this one after all */
955                                         atomic_dec
956                                              (&open_file->wrtPending);
957                                         continue;
958                                 }
959                         }
960                         return open_file;
961                 }
962         }
963         read_unlock(&GlobalSMBSeslock);
964         return NULL;
965 }
966
967 static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
968 {
969         struct address_space *mapping = page->mapping;
970         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
971         char *write_data;
972         int rc = -EFAULT;
973         int bytes_written = 0;
974         struct cifs_sb_info *cifs_sb;
975         struct cifsTconInfo *pTcon;
976         struct inode *inode;
977         struct cifsFileInfo *open_file;
978
979         if (!mapping || !mapping->host)
980                 return -EFAULT;
981
982         inode = page->mapping->host;
983         cifs_sb = CIFS_SB(inode->i_sb);
984         pTcon = cifs_sb->tcon;
985
986         offset += (loff_t)from;
987         write_data = kmap(page);
988         write_data += from;
989
990         if ((to > PAGE_CACHE_SIZE) || (from > to)) {
991                 kunmap(page);
992                 return -EIO;
993         }
994
995         /* racing with truncate? */
996         if (offset > mapping->host->i_size) {
997                 kunmap(page);
998                 return 0; /* don't care */
999         }
1000
1001         /* check to make sure that we are not extending the file */
1002         if (mapping->host->i_size - offset < (loff_t)to)
1003                 to = (unsigned)(mapping->host->i_size - offset); 
1004
1005         open_file = find_writable_file(CIFS_I(mapping->host));
1006         if (open_file) {
1007                 bytes_written = cifs_write(open_file->pfile, write_data,
1008                                            to-from, &offset);
1009                 atomic_dec(&open_file->wrtPending);
1010                 /* Does mm or vfs already set times? */
1011                 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
1012                 if ((bytes_written > 0) && (offset)) {
1013                         rc = 0;
1014                 } else if (bytes_written < 0) {
1015                         if (rc != -EBADF)
1016                                 rc = bytes_written;
1017                 }
1018         } else {
1019                 cFYI(1, ("No writeable filehandles for inode"));
1020                 rc = -EIO;
1021         }
1022
1023         kunmap(page);
1024         return rc;
1025 }
1026
1027 #ifdef CONFIG_CIFS_EXPERIMENTAL
1028 static int cifs_writepages(struct address_space *mapping,
1029                            struct writeback_control *wbc)
1030 {
1031         struct backing_dev_info *bdi = mapping->backing_dev_info;
1032         unsigned int bytes_to_write;
1033         unsigned int bytes_written;
1034         struct cifs_sb_info *cifs_sb;
1035         int done = 0;
1036         pgoff_t end = -1;
1037         pgoff_t index;
1038         int is_range = 0;
1039         struct kvec iov[32];
1040         int len;
1041         int n_iov = 0;
1042         pgoff_t next;
1043         int nr_pages;
1044         __u64 offset = 0;
1045         struct cifsFileInfo *open_file;
1046         struct page *page;
1047         struct pagevec pvec;
1048         int rc = 0;
1049         int scanned = 0;
1050         int xid;
1051
1052         cifs_sb = CIFS_SB(mapping->host->i_sb);
1053         
1054         /*
1055          * If wsize is smaller that the page cache size, default to writing
1056          * one page at a time via cifs_writepage
1057          */
1058         if (cifs_sb->wsize < PAGE_CACHE_SIZE)
1059                 return generic_writepages(mapping, wbc);
1060
1061         /* BB FIXME we do not have code to sign across multiple buffers yet,
1062            so go to older writepage style write which we can sign if needed */
1063         if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
1064                 if(cifs_sb->tcon->ses->server->secMode &
1065                           (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1066                         return generic_writepages(mapping, wbc);
1067
1068         /*
1069          * BB: Is this meaningful for a non-block-device file system?
1070          * If it is, we should test it again after we do I/O
1071          */
1072         if (wbc->nonblocking && bdi_write_congested(bdi)) {
1073                 wbc->encountered_congestion = 1;
1074                 return 0;
1075         }
1076
1077         xid = GetXid();
1078
1079         pagevec_init(&pvec, 0);
1080         if (wbc->sync_mode == WB_SYNC_NONE)
1081                 index = mapping->writeback_index; /* Start from prev offset */
1082         else {
1083                 index = 0;
1084                 scanned = 1;
1085         }
1086         if (wbc->start || wbc->end) {
1087                 index = wbc->start >> PAGE_CACHE_SHIFT;
1088                 end = wbc->end >> PAGE_CACHE_SHIFT;
1089                 is_range = 1;
1090                 scanned = 1;
1091         }
1092 retry:
1093         while (!done && (index <= end) &&
1094                (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
1095                         PAGECACHE_TAG_DIRTY,
1096                         min(end - index, (pgoff_t)PAGEVEC_SIZE - 1) + 1))) {
1097                 int first;
1098                 unsigned int i;
1099
1100                 first = -1;
1101                 next = 0;
1102                 n_iov = 0;
1103                 bytes_to_write = 0;
1104
1105                 for (i = 0; i < nr_pages; i++) {
1106                         page = pvec.pages[i];
1107                         /*
1108                          * At this point we hold neither mapping->tree_lock nor
1109                          * lock on the page itself: the page may be truncated or
1110                          * invalidated (changing page->mapping to NULL), or even
1111                          * swizzled back from swapper_space to tmpfs file
1112                          * mapping
1113                          */
1114
1115                         if (first < 0)
1116                                 lock_page(page);
1117                         else if (TestSetPageLocked(page))
1118                                 break;
1119
1120                         if (unlikely(page->mapping != mapping)) {
1121                                 unlock_page(page);
1122                                 break;
1123                         }
1124
1125                         if (unlikely(is_range) && (page->index > end)) {
1126                                 done = 1;
1127                                 unlock_page(page);
1128                                 break;
1129                         }
1130
1131                         if (next && (page->index != next)) {
1132                                 /* Not next consecutive page */
1133                                 unlock_page(page);
1134                                 break;
1135                         }
1136
1137                         if (wbc->sync_mode != WB_SYNC_NONE)
1138                                 wait_on_page_writeback(page);
1139
1140                         if (PageWriteback(page) ||
1141                                         !test_clear_page_dirty(page)) {
1142                                 unlock_page(page);
1143                                 break;
1144                         }
1145
1146                         if (page_offset(page) >= mapping->host->i_size) {
1147                                 done = 1;
1148                                 unlock_page(page);
1149                                 break;
1150                         }
1151
1152                         /*
1153                          * BB can we get rid of this?  pages are held by pvec
1154                          */
1155                         page_cache_get(page);
1156
1157                         len = min(mapping->host->i_size - page_offset(page),
1158                                   (loff_t)PAGE_CACHE_SIZE);
1159
1160                         /* reserve iov[0] for the smb header */
1161                         n_iov++;
1162                         iov[n_iov].iov_base = kmap(page);
1163                         iov[n_iov].iov_len = len;
1164                         bytes_to_write += len;
1165
1166                         if (first < 0) {
1167                                 first = i;
1168                                 offset = page_offset(page);
1169                         }
1170                         next = page->index + 1;
1171                         if (bytes_to_write + PAGE_CACHE_SIZE > cifs_sb->wsize)
1172                                 break;
1173                 }
1174                 if (n_iov) {
1175                         /* Search for a writable handle every time we call
1176                          * CIFSSMBWrite2.  We can't rely on the last handle
1177                          * we used to still be valid
1178                          */
1179                         open_file = find_writable_file(CIFS_I(mapping->host));
1180                         if (!open_file) {
1181                                 cERROR(1, ("No writable handles for inode"));
1182                                 rc = -EBADF;
1183                         } else {
1184                                 rc = CIFSSMBWrite2(xid, cifs_sb->tcon,
1185                                                    open_file->netfid,
1186                                                    bytes_to_write, offset,
1187                                                    &bytes_written, iov, n_iov,
1188                                                    1);
1189                                 atomic_dec(&open_file->wrtPending);
1190                                 if (rc || bytes_written < bytes_to_write) {
1191                                         cERROR(1,("Write2 ret %d, written = %d",
1192                                                   rc, bytes_written));
1193                                         /* BB what if continued retry is
1194                                            requested via mount flags? */
1195                                         set_bit(AS_EIO, &mapping->flags);
1196                                         SetPageError(page);
1197                                 } else {
1198                                         cifs_stats_bytes_written(cifs_sb->tcon,
1199                                                                  bytes_written);
1200                                 }
1201                         }
1202                         for (i = 0; i < n_iov; i++) {
1203                                 page = pvec.pages[first + i];
1204                                 kunmap(page);
1205                                 unlock_page(page);
1206                                 page_cache_release(page);
1207                         }
1208                         if ((wbc->nr_to_write -= n_iov) <= 0)
1209                                 done = 1;
1210                         index = next;
1211                 }
1212                 pagevec_release(&pvec);
1213         }
1214         if (!scanned && !done) {
1215                 /*
1216                  * We hit the last page and there is more work to be done: wrap
1217                  * back to the start of the file
1218                  */
1219                 scanned = 1;
1220                 index = 0;
1221                 goto retry;
1222         }
1223         if (!is_range)
1224                 mapping->writeback_index = index;
1225
1226         FreeXid(xid);
1227
1228         return rc;
1229 }
1230 #endif
1231
1232 static int cifs_writepage(struct page* page, struct writeback_control *wbc)
1233 {
1234         int rc = -EFAULT;
1235         int xid;
1236
1237         xid = GetXid();
1238 /* BB add check for wbc flags */
1239         page_cache_get(page);
1240         if (!PageUptodate(page)) {
1241                 cFYI(1, ("ppw - page not up to date"));
1242         }
1243         
1244         rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
1245         SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
1246         unlock_page(page);
1247         page_cache_release(page);       
1248         FreeXid(xid);
1249         return rc;
1250 }
1251
1252 static int cifs_commit_write(struct file *file, struct page *page,
1253         unsigned offset, unsigned to)
1254 {
1255         int xid;
1256         int rc = 0;
1257         struct inode *inode = page->mapping->host;
1258         loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
1259         char *page_data;
1260
1261         xid = GetXid();
1262         cFYI(1, ("commit write for page %p up to position %lld for %d", 
1263                  page, position, to));
1264         if (position > inode->i_size) {
1265                 i_size_write(inode, position);
1266                 /* if (file->private_data == NULL) {
1267                         rc = -EBADF;
1268                 } else {
1269                         open_file = (struct cifsFileInfo *)file->private_data;
1270                         cifs_sb = CIFS_SB(inode->i_sb);
1271                         rc = -EAGAIN;
1272                         while (rc == -EAGAIN) {
1273                                 if ((open_file->invalidHandle) && 
1274                                     (!open_file->closePend)) {
1275                                         rc = cifs_reopen_file(
1276                                                 file->f_dentry->d_inode, file);
1277                                         if (rc != 0)
1278                                                 break;
1279                                 }
1280                                 if (!open_file->closePend) {
1281                                         rc = CIFSSMBSetFileSize(xid,
1282                                                 cifs_sb->tcon, position,
1283                                                 open_file->netfid,
1284                                                 open_file->pid, FALSE);
1285                                 } else {
1286                                         rc = -EBADF;
1287                                         break;
1288                                 }
1289                         }
1290                         cFYI(1, (" SetEOF (commit write) rc = %d", rc));
1291                 } */
1292         }
1293         if (!PageUptodate(page)) {
1294                 position =  ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
1295                 /* can not rely on (or let) writepage write this data */
1296                 if (to < offset) {
1297                         cFYI(1, ("Illegal offsets, can not copy from %d to %d",
1298                                 offset, to));
1299                         FreeXid(xid);
1300                         return rc;
1301                 }
1302                 /* this is probably better than directly calling
1303                    partialpage_write since in this function the file handle is
1304                    known which we might as well leverage */
1305                 /* BB check if anything else missing out of ppw
1306                    such as updating last write time */
1307                 page_data = kmap(page);
1308                 rc = cifs_write(file, page_data + offset, to-offset,
1309                                 &position);
1310                 if (rc > 0)
1311                         rc = 0;
1312                 /* else if (rc < 0) should we set writebehind rc? */
1313                 kunmap(page);
1314         } else {        
1315                 set_page_dirty(page);
1316         }
1317
1318         FreeXid(xid);
1319         return rc;
1320 }
1321
1322 int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1323 {
1324         int xid;
1325         int rc = 0;
1326         struct inode *inode = file->f_dentry->d_inode;
1327
1328         xid = GetXid();
1329
1330         cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 
1331                 dentry->d_name.name, datasync));
1332         
1333         rc = filemap_fdatawrite(inode->i_mapping);
1334         if (rc == 0)
1335                 CIFS_I(inode)->write_behind_rc = 0;
1336         FreeXid(xid);
1337         return rc;
1338 }
1339
1340 /* static int cifs_sync_page(struct page *page)
1341 {
1342         struct address_space *mapping;
1343         struct inode *inode;
1344         unsigned long index = page->index;
1345         unsigned int rpages = 0;
1346         int rc = 0;
1347
1348         cFYI(1, ("sync page %p",page));
1349         mapping = page->mapping;
1350         if (!mapping)
1351                 return 0;
1352         inode = mapping->host;
1353         if (!inode)
1354                 return 0; */
1355
1356 /*      fill in rpages then 
1357         result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
1358
1359 /*      cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
1360
1361         if (rc < 0)
1362                 return rc;
1363         return 0;
1364 } */
1365
1366 /*
1367  * As file closes, flush all cached write data for this inode checking
1368  * for write behind errors.
1369  */
1370 int cifs_flush(struct file *file)
1371 {
1372         struct inode * inode = file->f_dentry->d_inode;
1373         int rc = 0;
1374
1375         /* Rather than do the steps manually:
1376            lock the inode for writing
1377            loop through pages looking for write behind data (dirty pages)
1378            coalesce into contiguous 16K (or smaller) chunks to write to server
1379            send to server (prefer in parallel)
1380            deal with writebehind errors
1381            unlock inode for writing
1382            filemapfdatawrite appears easier for the time being */
1383
1384         rc = filemap_fdatawrite(inode->i_mapping);
1385         if (!rc) /* reset wb rc if we were able to write out dirty pages */
1386                 CIFS_I(inode)->write_behind_rc = 0;
1387                 
1388         cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc));
1389
1390         return rc;
1391 }
1392
1393 ssize_t cifs_user_read(struct file *file, char __user *read_data,
1394         size_t read_size, loff_t *poffset)
1395 {
1396         int rc = -EACCES;
1397         unsigned int bytes_read = 0;
1398         unsigned int total_read = 0;
1399         unsigned int current_read_size;
1400         struct cifs_sb_info *cifs_sb;
1401         struct cifsTconInfo *pTcon;
1402         int xid;
1403         struct cifsFileInfo *open_file;
1404         char *smb_read_data;
1405         char __user *current_offset;
1406         struct smb_com_read_rsp *pSMBr;
1407
1408         xid = GetXid();
1409         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1410         pTcon = cifs_sb->tcon;
1411
1412         if (file->private_data == NULL) {
1413                 FreeXid(xid);
1414                 return -EBADF;
1415         }
1416         open_file = (struct cifsFileInfo *)file->private_data;
1417
1418         if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
1419                 cFYI(1, ("attempting read on write only file instance"));
1420         }
1421         for (total_read = 0, current_offset = read_data;
1422              read_size > total_read;
1423              total_read += bytes_read, current_offset += bytes_read) {
1424                 current_read_size = min_t(const int, read_size - total_read, 
1425                                           cifs_sb->rsize);
1426                 rc = -EAGAIN;
1427                 smb_read_data = NULL;
1428                 while (rc == -EAGAIN) {
1429                         if ((open_file->invalidHandle) && 
1430                             (!open_file->closePend)) {
1431                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1432                                         file, TRUE);
1433                                 if (rc != 0)
1434                                         break;
1435                         }
1436                         rc = CIFSSMBRead(xid, pTcon,
1437                                         open_file->netfid,
1438                                         current_read_size, *poffset,
1439                                         &bytes_read, &smb_read_data);
1440                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1441                         if (copy_to_user(current_offset, 
1442                                          smb_read_data + 4 /* RFC1001 hdr */
1443                                          + le16_to_cpu(pSMBr->DataOffset), 
1444                                          bytes_read)) {
1445                                 rc = -EFAULT;
1446                                 FreeXid(xid);
1447                                 return rc;
1448             }
1449                         if (smb_read_data) {
1450                                 cifs_buf_release(smb_read_data);
1451                                 smb_read_data = NULL;
1452                         }
1453                 }
1454                 if (rc || (bytes_read == 0)) {
1455                         if (total_read) {
1456                                 break;
1457                         } else {
1458                                 FreeXid(xid);
1459                                 return rc;
1460                         }
1461                 } else {
1462                         cifs_stats_bytes_read(pTcon, bytes_read);
1463                         *poffset += bytes_read;
1464                 }
1465         }
1466         FreeXid(xid);
1467         return total_read;
1468 }
1469
1470
1471 static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1472         loff_t *poffset)
1473 {
1474         int rc = -EACCES;
1475         unsigned int bytes_read = 0;
1476         unsigned int total_read;
1477         unsigned int current_read_size;
1478         struct cifs_sb_info *cifs_sb;
1479         struct cifsTconInfo *pTcon;
1480         int xid;
1481         char *current_offset;
1482         struct cifsFileInfo *open_file;
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                 }
1523                 if (rc || (bytes_read == 0)) {
1524                         if (total_read) {
1525                                 break;
1526                         } else {
1527                                 FreeXid(xid);
1528                                 return rc;
1529                         }
1530                 } else {
1531                         cifs_stats_bytes_read(pTcon, total_read);
1532                         *poffset += bytes_read;
1533                 }
1534         }
1535         FreeXid(xid);
1536         return total_read;
1537 }
1538
1539 int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1540 {
1541         struct dentry *dentry = file->f_dentry;
1542         int rc, xid;
1543
1544         xid = GetXid();
1545         rc = cifs_revalidate(dentry);
1546         if (rc) {
1547                 cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
1548                 FreeXid(xid);
1549                 return rc;
1550         }
1551         rc = generic_file_mmap(file, vma);
1552         FreeXid(xid);
1553         return rc;
1554 }
1555
1556
1557 static void cifs_copy_cache_pages(struct address_space *mapping, 
1558         struct list_head *pages, int bytes_read, char *data,
1559         struct pagevec *plru_pvec)
1560 {
1561         struct page *page;
1562         char *target;
1563
1564         while (bytes_read > 0) {
1565                 if (list_empty(pages))
1566                         break;
1567
1568                 page = list_entry(pages->prev, struct page, lru);
1569                 list_del(&page->lru);
1570
1571                 if (add_to_page_cache(page, mapping, page->index,
1572                                       GFP_KERNEL)) {
1573                         page_cache_release(page);
1574                         cFYI(1, ("Add page cache failed"));
1575                         data += PAGE_CACHE_SIZE;
1576                         bytes_read -= PAGE_CACHE_SIZE;
1577                         continue;
1578                 }
1579
1580                 target = kmap_atomic(page,KM_USER0);
1581
1582                 if (PAGE_CACHE_SIZE > bytes_read) {
1583                         memcpy(target, data, bytes_read);
1584                         /* zero the tail end of this partial page */
1585                         memset(target + bytes_read, 0, 
1586                                PAGE_CACHE_SIZE - bytes_read);
1587                         bytes_read = 0;
1588                 } else {
1589                         memcpy(target, data, PAGE_CACHE_SIZE);
1590                         bytes_read -= PAGE_CACHE_SIZE;
1591                 }
1592                 kunmap_atomic(target, KM_USER0);
1593
1594                 flush_dcache_page(page);
1595                 SetPageUptodate(page);
1596                 unlock_page(page);
1597                 if (!pagevec_add(plru_pvec, page))
1598                         __pagevec_lru_add(plru_pvec);
1599                 data += PAGE_CACHE_SIZE;
1600         }
1601         return;
1602 }
1603
1604 static int cifs_readpages(struct file *file, struct address_space *mapping,
1605         struct list_head *page_list, unsigned num_pages)
1606 {
1607         int rc = -EACCES;
1608         int xid;
1609         loff_t offset;
1610         struct page *page;
1611         struct cifs_sb_info *cifs_sb;
1612         struct cifsTconInfo *pTcon;
1613         int bytes_read = 0;
1614         unsigned int read_size,i;
1615         char *smb_read_data = NULL;
1616         struct smb_com_read_rsp *pSMBr;
1617         struct pagevec lru_pvec;
1618         struct cifsFileInfo *open_file;
1619
1620         xid = GetXid();
1621         if (file->private_data == NULL) {
1622                 FreeXid(xid);
1623                 return -EBADF;
1624         }
1625         open_file = (struct cifsFileInfo *)file->private_data;
1626         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1627         pTcon = cifs_sb->tcon;
1628
1629         pagevec_init(&lru_pvec, 0);
1630
1631         for (i = 0; i < num_pages; ) {
1632                 unsigned contig_pages;
1633                 struct page *tmp_page;
1634                 unsigned long expected_index;
1635
1636                 if (list_empty(page_list))
1637                         break;
1638
1639                 page = list_entry(page_list->prev, struct page, lru);
1640                 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1641
1642                 /* count adjacent pages that we will read into */
1643                 contig_pages = 0;
1644                 expected_index = 
1645                         list_entry(page_list->prev, struct page, lru)->index;
1646                 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1647                         if (tmp_page->index == expected_index) {
1648                                 contig_pages++;
1649                                 expected_index++;
1650                         } else
1651                                 break; 
1652                 }
1653                 if (contig_pages + i >  num_pages)
1654                         contig_pages = num_pages - i;
1655
1656                 /* for reads over a certain size could initiate async
1657                    read ahead */
1658
1659                 read_size = contig_pages * PAGE_CACHE_SIZE;
1660                 /* Read size needs to be in multiples of one page */
1661                 read_size = min_t(const unsigned int, read_size,
1662                                   cifs_sb->rsize & PAGE_CACHE_MASK);
1663
1664                 rc = -EAGAIN;
1665                 while (rc == -EAGAIN) {
1666                         if ((open_file->invalidHandle) && 
1667                             (!open_file->closePend)) {
1668                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1669                                         file, TRUE);
1670                                 if (rc != 0)
1671                                         break;
1672                         }
1673
1674                         rc = CIFSSMBRead(xid, pTcon,
1675                                         open_file->netfid,
1676                                         read_size, offset,
1677                                         &bytes_read, &smb_read_data);
1678
1679                         /* BB more RC checks ? */
1680                         if (rc== -EAGAIN) {
1681                                 if (smb_read_data) {
1682                                         cifs_buf_release(smb_read_data);
1683                                         smb_read_data = NULL;
1684                                 }
1685                         }
1686                 }
1687                 if ((rc < 0) || (smb_read_data == NULL)) {
1688                         cFYI(1, ("Read error in readpages: %d", rc));
1689                         /* clean up remaing pages off list */
1690                         while (!list_empty(page_list) && (i < num_pages)) {
1691                                 page = list_entry(page_list->prev, struct page,
1692                                                   lru);
1693                                 list_del(&page->lru);
1694                                 page_cache_release(page);
1695                         }
1696                         break;
1697                 } else if (bytes_read > 0) {
1698                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1699                         cifs_copy_cache_pages(mapping, page_list, bytes_read,
1700                                 smb_read_data + 4 /* RFC1001 hdr */ +
1701                                 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1702
1703                         i +=  bytes_read >> PAGE_CACHE_SHIFT;
1704                         cifs_stats_bytes_read(pTcon, bytes_read);
1705                         if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1706                                 i++; /* account for partial page */
1707
1708                                 /* server copy of file can have smaller size 
1709                                    than client */
1710                                 /* BB do we need to verify this common case ? 
1711                                    this case is ok - if we are at server EOF 
1712                                    we will hit it on next read */
1713
1714                         /* while (!list_empty(page_list) && (i < num_pages)) {
1715                                         page = list_entry(page_list->prev, 
1716                                                           struct page, list);
1717                                         list_del(&page->list);
1718                                         page_cache_release(page);
1719                                 }
1720                                 break; */
1721                         }
1722                 } else {
1723                         cFYI(1, ("No bytes read (%d) at offset %lld . "
1724                                  "Cleaning remaining pages from readahead list",
1725                                  bytes_read, offset));
1726                         /* BB turn off caching and do new lookup on 
1727                            file size at server? */
1728                         while (!list_empty(page_list) && (i < num_pages)) {
1729                                 page = list_entry(page_list->prev, struct page,
1730                                                   lru);
1731                                 list_del(&page->lru);
1732
1733                                 /* BB removeme - replace with zero of page? */
1734                                 page_cache_release(page);
1735                         }
1736                         break;
1737                 }
1738                 if (smb_read_data) {
1739                         cifs_buf_release(smb_read_data);
1740                         smb_read_data = NULL;
1741                 }
1742                 bytes_read = 0;
1743         }
1744
1745         pagevec_lru_add(&lru_pvec);
1746
1747 /* need to free smb_read_data buf before exit */
1748         if (smb_read_data) {
1749                 cifs_buf_release(smb_read_data);
1750                 smb_read_data = NULL;
1751         } 
1752
1753         FreeXid(xid);
1754         return rc;
1755 }
1756
1757 static int cifs_readpage_worker(struct file *file, struct page *page,
1758         loff_t *poffset)
1759 {
1760         char *read_data;
1761         int rc;
1762
1763         page_cache_get(page);
1764         read_data = kmap(page);
1765         /* for reads over a certain size could initiate async read ahead */
1766                                                                                                                            
1767         rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1768                                                                                                                            
1769         if (rc < 0)
1770                 goto io_error;
1771         else
1772                 cFYI(1, ("Bytes read %d ",rc));
1773                                                                                                                            
1774         file->f_dentry->d_inode->i_atime =
1775                 current_fs_time(file->f_dentry->d_inode->i_sb);
1776                                                                                                                            
1777         if (PAGE_CACHE_SIZE > rc)
1778                 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
1779
1780         flush_dcache_page(page);
1781         SetPageUptodate(page);
1782         rc = 0;
1783                                                                                                                            
1784 io_error:
1785         kunmap(page);
1786         page_cache_release(page);
1787         return rc;
1788 }
1789
1790 static int cifs_readpage(struct file *file, struct page *page)
1791 {
1792         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1793         int rc = -EACCES;
1794         int xid;
1795
1796         xid = GetXid();
1797
1798         if (file->private_data == NULL) {
1799                 FreeXid(xid);
1800                 return -EBADF;
1801         }
1802
1803         cFYI(1, ("readpage %p at offset %d 0x%x\n", 
1804                  page, (int)offset, (int)offset));
1805
1806         rc = cifs_readpage_worker(file, page, &offset);
1807
1808         unlock_page(page);
1809
1810         FreeXid(xid);
1811         return rc;
1812 }
1813
1814 /* We do not want to update the file size from server for inodes
1815    open for write - to avoid races with writepage extending
1816    the file - in the future we could consider allowing
1817    refreshing the inode only on increases in the file size 
1818    but this is tricky to do without racing with writebehind
1819    page caching in the current Linux kernel design */
1820 int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1821 {
1822         struct cifsFileInfo *open_file = NULL;
1823
1824         if (cifsInode)
1825                 open_file =  find_writable_file(cifsInode);
1826  
1827         if(open_file) {
1828                 /* there is not actually a write pending so let
1829                 this handle go free and allow it to
1830                 be closable if needed */
1831                 atomic_dec(&open_file->wrtPending);
1832                 return 0;
1833         } else
1834                 return 1;
1835 }
1836
1837 static int cifs_prepare_write(struct file *file, struct page *page,
1838         unsigned from, unsigned to)
1839 {
1840         int rc = 0;
1841         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1842         cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1843         if (!PageUptodate(page)) {
1844         /*      if (to - from != PAGE_CACHE_SIZE) {
1845                         void *kaddr = kmap_atomic(page, KM_USER0);
1846                         memset(kaddr, 0, from);
1847                         memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1848                         flush_dcache_page(page);
1849                         kunmap_atomic(kaddr, KM_USER0);
1850                 } */
1851                 /* If we are writing a full page it will be up to date,
1852                    no need to read from the server */
1853                 if ((to == PAGE_CACHE_SIZE) && (from == 0))
1854                         SetPageUptodate(page);
1855
1856                 /* might as well read a page, it is fast enough */
1857                 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
1858                         rc = cifs_readpage_worker(file, page, &offset);
1859                 } else {
1860                 /* should we try using another file handle if there is one -
1861                    how would we lock it to prevent close of that handle
1862                    racing with this read?
1863                    In any case this will be written out by commit_write */
1864                 }
1865         }
1866
1867         /* BB should we pass any errors back? 
1868            e.g. if we do not have read access to the file */
1869         return 0;
1870 }
1871
1872 struct address_space_operations cifs_addr_ops = {
1873         .readpage = cifs_readpage,
1874         .readpages = cifs_readpages,
1875         .writepage = cifs_writepage,
1876 #ifdef CONFIG_CIFS_EXPERIMENTAL
1877         .writepages = cifs_writepages,
1878 #endif
1879         .prepare_write = cifs_prepare_write,
1880         .commit_write = cifs_commit_write,
1881         .set_page_dirty = __set_page_dirty_nobuffers,
1882         /* .sync_page = cifs_sync_page, */
1883         /* .direct_IO = */
1884 };