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