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