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