]> bbs.cooldavid.org Git - net-next-2.6.git/blob - fs/cifs/file.c
[CIFS] CIFS writepage improvements - eliminate double copy
[net-next-2.6.git] / 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 == FALSE)) {
517                         pCFileStruct->invalidHandle = TRUE;
518                         rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
519                         cFYI(1, ("Closing uncompleted readdir with rc %d",
520                                  rc));
521                         /* not much we can do if it fails anyway, ignore rc */
522                         rc = 0;
523                 }
524                 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
525                 if (ptmp) {
526    /* BB removeme BB */ cFYI(1, ("freeing smb buf in srch struct in closedir"));
527                         pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
528                         cifs_buf_release(ptmp);
529                 }
530                 ptmp = pCFileStruct->search_resume_name;
531                 if (ptmp) {
532    /* BB removeme BB */ cFYI(1, ("freeing resume name in closedir"));
533                         pCFileStruct->search_resume_name = NULL;
534                         kfree(ptmp);
535                 }
536                 kfree(file->private_data);
537                 file->private_data = NULL;
538         }
539         /* BB can we lock the filestruct while this is going on? */
540         FreeXid(xid);
541         return rc;
542 }
543
544 int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
545 {
546         int rc, xid;
547         __u32 lockType = LOCKING_ANDX_LARGE_FILES;
548         __u32 numLock = 0;
549         __u32 numUnlock = 0;
550         __u64 length;
551         int wait_flag = FALSE;
552         struct cifs_sb_info *cifs_sb;
553         struct cifsTconInfo *pTcon;
554
555         length = 1 + pfLock->fl_end - pfLock->fl_start;
556         rc = -EACCES;
557         xid = GetXid();
558
559         cFYI(1, ("Lock parm: 0x%x flockflags: "
560                  "0x%x flocktype: 0x%x start: %lld end: %lld",
561                 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
562                 pfLock->fl_end));
563
564         if (pfLock->fl_flags & FL_POSIX)
565                 cFYI(1, ("Posix "));
566         if (pfLock->fl_flags & FL_FLOCK)
567                 cFYI(1, ("Flock "));
568         if (pfLock->fl_flags & FL_SLEEP) {
569                 cFYI(1, ("Blocking lock "));
570                 wait_flag = TRUE;
571         }
572         if (pfLock->fl_flags & FL_ACCESS)
573                 cFYI(1, ("Process suspended by mandatory locking - "
574                          "not implemented yet "));
575         if (pfLock->fl_flags & FL_LEASE)
576                 cFYI(1, ("Lease on file - not implemented yet"));
577         if (pfLock->fl_flags & 
578             (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
579                 cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags));
580
581         if (pfLock->fl_type == F_WRLCK) {
582                 cFYI(1, ("F_WRLCK "));
583                 numLock = 1;
584         } else if (pfLock->fl_type == F_UNLCK) {
585                 cFYI(1, ("F_UNLCK "));
586                 numUnlock = 1;
587         } else if (pfLock->fl_type == F_RDLCK) {
588                 cFYI(1, ("F_RDLCK "));
589                 lockType |= LOCKING_ANDX_SHARED_LOCK;
590                 numLock = 1;
591         } else if (pfLock->fl_type == F_EXLCK) {
592                 cFYI(1, ("F_EXLCK "));
593                 numLock = 1;
594         } else if (pfLock->fl_type == F_SHLCK) {
595                 cFYI(1, ("F_SHLCK "));
596                 lockType |= LOCKING_ANDX_SHARED_LOCK;
597                 numLock = 1;
598         } else
599                 cFYI(1, ("Unknown type of lock "));
600
601         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
602         pTcon = cifs_sb->tcon;
603
604         if (file->private_data == NULL) {
605                 FreeXid(xid);
606                 return -EBADF;
607         }
608
609         if (IS_GETLK(cmd)) {
610                 rc = CIFSSMBLock(xid, pTcon,
611                                  ((struct cifsFileInfo *)file->
612                                   private_data)->netfid,
613                                  length,
614                                  pfLock->fl_start, 0, 1, lockType,
615                                  0 /* wait flag */ );
616                 if (rc == 0) {
617                         rc = CIFSSMBLock(xid, pTcon,
618                                          ((struct cifsFileInfo *) file->
619                                           private_data)->netfid,
620                                          length,
621                                          pfLock->fl_start, 1 /* numUnlock */ ,
622                                          0 /* numLock */ , lockType,
623                                          0 /* wait flag */ );
624                         pfLock->fl_type = F_UNLCK;
625                         if (rc != 0)
626                                 cERROR(1, ("Error unlocking previously locked "
627                                            "range %d during test of lock ",
628                                            rc));
629                         rc = 0;
630
631                 } else {
632                         /* if rc == ERR_SHARING_VIOLATION ? */
633                         rc = 0; /* do not change lock type to unlock
634                                    since range in use */
635                 }
636
637                 FreeXid(xid);
638                 return rc;
639         }
640
641         rc = CIFSSMBLock(xid, pTcon,
642                          ((struct cifsFileInfo *) file->private_data)->
643                          netfid, length,
644                          pfLock->fl_start, numUnlock, numLock, lockType,
645                          wait_flag);
646         if (rc == 0 && (pfLock->fl_flags & FL_POSIX))
647                 posix_lock_file_wait(file, pfLock);
648         FreeXid(xid);
649         return rc;
650 }
651
652 ssize_t cifs_user_write(struct file *file, const char __user *write_data,
653         size_t write_size, loff_t *poffset)
654 {
655         int rc = 0;
656         unsigned int bytes_written = 0;
657         unsigned int total_written;
658         struct cifs_sb_info *cifs_sb;
659         struct cifsTconInfo *pTcon;
660         int xid, long_op;
661         struct cifsFileInfo *open_file;
662
663         if (file->f_dentry == NULL)
664                 return -EBADF;
665
666         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
667         if (cifs_sb == NULL)
668                 return -EBADF;
669
670         pTcon = cifs_sb->tcon;
671
672         /* cFYI(1,
673            (" write %d bytes to offset %lld of %s", write_size,
674            *poffset, file->f_dentry->d_name.name)); */
675
676         if (file->private_data == NULL)
677                 return -EBADF;
678         else
679                 open_file = (struct cifsFileInfo *) file->private_data;
680         
681         xid = GetXid();
682         if (file->f_dentry->d_inode == NULL) {
683                 FreeXid(xid);
684                 return -EBADF;
685         }
686
687         if (*poffset > file->f_dentry->d_inode->i_size)
688                 long_op = 2; /* writes past end of file can take a long time */
689         else
690                 long_op = 1;
691
692         for (total_written = 0; write_size > total_written;
693              total_written += bytes_written) {
694                 rc = -EAGAIN;
695                 while (rc == -EAGAIN) {
696                         if (file->private_data == NULL) {
697                                 /* file has been closed on us */
698                                 FreeXid(xid);
699                         /* if we have gotten here we have written some data
700                            and blocked, and the file has been freed on us while
701                            we blocked so return what we managed to write */
702                                 return total_written;
703                         } 
704                         if (open_file->closePend) {
705                                 FreeXid(xid);
706                                 if (total_written)
707                                         return total_written;
708                                 else
709                                         return -EBADF;
710                         }
711                         if (open_file->invalidHandle) {
712                                 if ((file->f_dentry == NULL) ||
713                                     (file->f_dentry->d_inode == NULL)) {
714                                         FreeXid(xid);
715                                         return total_written;
716                                 }
717                                 /* we could deadlock if we called
718                                    filemap_fdatawait from here so tell
719                                    reopen_file not to flush data to server
720                                    now */
721                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
722                                         file, FALSE);
723                                 if (rc != 0)
724                                         break;
725                         }
726
727                         rc = CIFSSMBWrite(xid, pTcon,
728                                 open_file->netfid,
729                                 min_t(const int, cifs_sb->wsize,
730                                       write_size - total_written),
731                                 *poffset, &bytes_written,
732                                 NULL, write_data + total_written, long_op);
733                 }
734                 if (rc || (bytes_written == 0)) {
735                         if (total_written)
736                                 break;
737                         else {
738                                 FreeXid(xid);
739                                 return rc;
740                         }
741                 } else
742                         *poffset += bytes_written;
743                 long_op = FALSE; /* subsequent writes fast -
744                                     15 seconds is plenty */
745         }
746
747 #ifdef CONFIG_CIFS_STATS
748         if (total_written > 0) {
749                 atomic_inc(&pTcon->num_writes);
750                 spin_lock(&pTcon->stat_lock);
751                 pTcon->bytes_written += total_written;
752                 spin_unlock(&pTcon->stat_lock);
753         }
754 #endif          
755
756         /* since the write may have blocked check these pointers again */
757         if (file->f_dentry) {
758                 if (file->f_dentry->d_inode) {
759                         struct inode *inode = file->f_dentry->d_inode;
760                         inode->i_ctime = inode->i_mtime =
761                                 current_fs_time(inode->i_sb);
762                         if (total_written > 0) {
763                                 if (*poffset > file->f_dentry->d_inode->i_size)
764                                         i_size_write(file->f_dentry->d_inode,
765                                         *poffset);
766                         }
767                         mark_inode_dirty_sync(file->f_dentry->d_inode);
768                 }
769         }
770         FreeXid(xid);
771         return total_written;
772 }
773
774 static ssize_t cifs_write(struct file *file, const char *write_data,
775         size_t write_size, loff_t *poffset)
776 {
777         int rc = 0;
778         unsigned int bytes_written = 0;
779         unsigned int total_written;
780         struct cifs_sb_info *cifs_sb;
781         struct cifsTconInfo *pTcon;
782         int xid, long_op;
783         struct cifsFileInfo *open_file;
784
785         if (file->f_dentry == NULL)
786                 return -EBADF;
787
788         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
789         if (cifs_sb == NULL)
790                 return -EBADF;
791
792         pTcon = cifs_sb->tcon;
793
794         cFYI(1,(" write %d bytes to offset %lld of %s", write_size,
795            *poffset, file->f_dentry->d_name.name)); /* BB removeme BB */
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 #ifdef CIFS_EXPERIMENTAL
849                         /* BB FIXME We can not sign across two buffers yet */
850                         cERROR(1,("checking signing")); /* BB removeme BB */
851                         if(pTcon->ses->server->secMode & 
852                            (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED) == 0)
853                                 rc = CIFSSMBWrite2(xid, pTcon,
854                                                 open_file->netfid,
855                                                 min_t(const int, cifs_sb->wsize,
856                                                     write_size - total_written),
857                                                 *poffset, &bytes_written,
858                                                 write_data + total_written, 
859                                                 long_op);
860                         } else
861                         /* BB FIXME fixup indentation of line below */
862 #endif                  
863                         rc = CIFSSMBWrite(xid, pTcon,
864                                  open_file->netfid,
865                                  min_t(const int, cifs_sb->wsize, 
866                                        write_size - total_written),
867                                  *poffset, &bytes_written,
868                                  write_data + total_written, NULL, long_op);
869                 }
870                 if (rc || (bytes_written == 0)) {
871                         if (total_written)
872                                 break;
873                         else {
874                                 FreeXid(xid);
875                                 return rc;
876                         }
877                 } else
878                         *poffset += bytes_written;
879                 long_op = FALSE; /* subsequent writes fast - 
880                                     15 seconds is plenty */
881         }
882
883 #ifdef CONFIG_CIFS_STATS
884         if (total_written > 0) {
885                 atomic_inc(&pTcon->num_writes);
886                 spin_lock(&pTcon->stat_lock);
887                 pTcon->bytes_written += total_written;
888                 spin_unlock(&pTcon->stat_lock);
889         }
890 #endif          
891
892         /* since the write may have blocked check these pointers again */
893         if (file->f_dentry) {
894                 if (file->f_dentry->d_inode) {
895                         file->f_dentry->d_inode->i_ctime = 
896                         file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
897                         if (total_written > 0) {
898                                 if (*poffset > file->f_dentry->d_inode->i_size)
899                                         i_size_write(file->f_dentry->d_inode, 
900                                                      *poffset);
901                         }
902                         mark_inode_dirty_sync(file->f_dentry->d_inode);
903                 }
904         }
905         FreeXid(xid);
906         return total_written;
907 }
908
909 static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
910 {
911         struct address_space *mapping = page->mapping;
912         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
913         char *write_data;
914         int rc = -EFAULT;
915         int bytes_written = 0;
916         struct cifs_sb_info *cifs_sb;
917         struct cifsTconInfo *pTcon;
918         struct inode *inode;
919         struct cifsInodeInfo *cifsInode;
920         struct cifsFileInfo *open_file = NULL;
921         struct list_head *tmp;
922         struct list_head *tmp1;
923
924         if (!mapping || !mapping->host)
925                 return -EFAULT;
926
927         inode = page->mapping->host;
928         cifs_sb = CIFS_SB(inode->i_sb);
929         pTcon = cifs_sb->tcon;
930
931         offset += (loff_t)from;
932         write_data = kmap(page);
933         write_data += from;
934
935         if ((to > PAGE_CACHE_SIZE) || (from > to)) {
936                 kunmap(page);
937                 return -EIO;
938         }
939
940         /* racing with truncate? */
941         if (offset > mapping->host->i_size) {
942                 kunmap(page);
943                 return 0; /* don't care */
944         }
945
946         /* check to make sure that we are not extending the file */
947         if (mapping->host->i_size - offset < (loff_t)to)
948                 to = (unsigned)(mapping->host->i_size - offset); 
949
950         cifsInode = CIFS_I(mapping->host);
951         read_lock(&GlobalSMBSeslock); 
952         /* BB we should start at the end */
953         list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {            
954                 open_file = list_entry(tmp, struct cifsFileInfo, flist);
955                 if (open_file->closePend)
956                         continue;
957                 /* We check if file is open for writing first */
958                 if ((open_file->pfile) && 
959                    ((open_file->pfile->f_flags & O_RDWR) || 
960                         (open_file->pfile->f_flags & O_WRONLY))) {
961                         read_unlock(&GlobalSMBSeslock);
962                         bytes_written = cifs_write(open_file->pfile,
963                                                 write_data, to-from,
964                                                 &offset);
965                         read_lock(&GlobalSMBSeslock);
966                 /* Does mm or vfs already set times? */
967                         inode->i_atime = 
968                         inode->i_mtime = current_fs_time(inode->i_sb);
969                         if ((bytes_written > 0) && (offset)) {
970                                 rc = 0;
971                         } else if (bytes_written < 0) {
972                                 if (rc == -EBADF) {
973                                 /* have seen a case in which kernel seemed to
974                                    have closed/freed a file even with writes
975                                    active so we might as well see if there are
976                                    other file structs to try for the same
977                                    inode before giving up */
978                                         continue;
979                                 } else
980                                         rc = bytes_written;
981                         }
982                         break;  /* now that we found a valid file handle and
983                                    tried to write to it we are done, no sense
984                                    continuing to loop looking for another */
985                 }
986                 if (tmp->next == NULL) {
987                         cFYI(1, ("File instance %p removed", tmp));
988                         break;
989                 }
990         }
991         read_unlock(&GlobalSMBSeslock);
992         if (open_file == NULL) {
993                 cFYI(1, ("No writeable filehandles for inode"));
994                 rc = -EIO;
995         }
996
997         kunmap(page);
998         return rc;
999 }
1000
1001 #if 0
1002 static int cifs_writepages(struct address_space *mapping,
1003         struct writeback_control *wbc)
1004 {
1005         int rc = -EFAULT;
1006         int xid;
1007
1008         xid = GetXid();
1009
1010         /* Find contiguous pages then iterate through repeating
1011            call 16K write then Setpageuptodate or if LARGE_WRITE_X
1012            support then send larger writes via kevec so as to eliminate
1013            a memcpy */
1014         FreeXid(xid);
1015         return rc;
1016 }
1017 #endif
1018
1019 static int cifs_writepage(struct page* page, struct writeback_control *wbc)
1020 {
1021         int rc = -EFAULT;
1022         int xid;
1023
1024         xid = GetXid();
1025 /* BB add check for wbc flags */
1026         page_cache_get(page);
1027         if (!PageUptodate(page)) {
1028                 cFYI(1, ("ppw - page not up to date"));
1029         }
1030         
1031         rc = cifs_partialpagewrite(page, 0, PAGE_CACHE_SIZE);
1032         SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
1033         unlock_page(page);
1034         page_cache_release(page);       
1035         FreeXid(xid);
1036         return rc;
1037 }
1038
1039 static int cifs_commit_write(struct file *file, struct page *page,
1040         unsigned offset, unsigned to)
1041 {
1042         int xid;
1043         int rc = 0;
1044         struct inode *inode = page->mapping->host;
1045         loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
1046         char *page_data;
1047
1048         xid = GetXid();
1049         cFYI(1, ("commit write for page %p up to position %lld for %d", 
1050                  page, position, to));
1051         if (position > inode->i_size) {
1052                 i_size_write(inode, position);
1053                 /* if (file->private_data == NULL) {
1054                         rc = -EBADF;
1055                 } else {
1056                         open_file = (struct cifsFileInfo *)file->private_data;
1057                         cifs_sb = CIFS_SB(inode->i_sb);
1058                         rc = -EAGAIN;
1059                         while (rc == -EAGAIN) {
1060                                 if ((open_file->invalidHandle) && 
1061                                     (!open_file->closePend)) {
1062                                         rc = cifs_reopen_file(
1063                                                 file->f_dentry->d_inode, file);
1064                                         if (rc != 0)
1065                                                 break;
1066                                 }
1067                                 if (!open_file->closePend) {
1068                                         rc = CIFSSMBSetFileSize(xid,
1069                                                 cifs_sb->tcon, position,
1070                                                 open_file->netfid,
1071                                                 open_file->pid, FALSE);
1072                                 } else {
1073                                         rc = -EBADF;
1074                                         break;
1075                                 }
1076                         }
1077                         cFYI(1, (" SetEOF (commit write) rc = %d", rc));
1078                 } */
1079         }
1080         if (!PageUptodate(page)) {
1081                 position =  ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
1082                 /* can not rely on (or let) writepage write this data */
1083                 if (to < offset) {
1084                         cFYI(1, ("Illegal offsets, can not copy from %d to %d",
1085                                 offset, to));
1086                         FreeXid(xid);
1087                         return rc;
1088                 }
1089                 /* this is probably better than directly calling
1090                    partialpage_write since in this function the file handle is
1091                    known which we might as well leverage */
1092                 /* BB check if anything else missing out of ppw
1093                    such as updating last write time */
1094                 page_data = kmap(page);
1095                 rc = cifs_write(file, page_data + offset, to-offset,
1096                                 &position);
1097                 if (rc > 0)
1098                         rc = 0;
1099                 /* else if (rc < 0) should we set writebehind rc? */
1100                 kunmap(page);
1101         } else {        
1102                 set_page_dirty(page);
1103         }
1104
1105         FreeXid(xid);
1106         return rc;
1107 }
1108
1109 int cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1110 {
1111         int xid;
1112         int rc = 0;
1113         struct inode *inode = file->f_dentry->d_inode;
1114
1115         xid = GetXid();
1116
1117         cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 
1118                 dentry->d_name.name, datasync));
1119         
1120         rc = filemap_fdatawrite(inode->i_mapping);
1121         if (rc == 0)
1122                 CIFS_I(inode)->write_behind_rc = 0;
1123         FreeXid(xid);
1124         return rc;
1125 }
1126
1127 /* static int cifs_sync_page(struct page *page)
1128 {
1129         struct address_space *mapping;
1130         struct inode *inode;
1131         unsigned long index = page->index;
1132         unsigned int rpages = 0;
1133         int rc = 0;
1134
1135         cFYI(1, ("sync page %p",page));
1136         mapping = page->mapping;
1137         if (!mapping)
1138                 return 0;
1139         inode = mapping->host;
1140         if (!inode)
1141                 return 0; */
1142
1143 /*      fill in rpages then 
1144         result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
1145
1146 /*      cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
1147
1148         if (rc < 0)
1149                 return rc;
1150         return 0;
1151 } */
1152
1153 /*
1154  * As file closes, flush all cached write data for this inode checking
1155  * for write behind errors.
1156  */
1157 int cifs_flush(struct file *file)
1158 {
1159         struct inode * inode = file->f_dentry->d_inode;
1160         int rc = 0;
1161
1162         /* Rather than do the steps manually:
1163            lock the inode for writing
1164            loop through pages looking for write behind data (dirty pages)
1165            coalesce into contiguous 16K (or smaller) chunks to write to server
1166            send to server (prefer in parallel)
1167            deal with writebehind errors
1168            unlock inode for writing
1169            filemapfdatawrite appears easier for the time being */
1170
1171         rc = filemap_fdatawrite(inode->i_mapping);
1172         if (!rc) /* reset wb rc if we were able to write out dirty pages */
1173                 CIFS_I(inode)->write_behind_rc = 0;
1174                 
1175         cFYI(1, ("Flush inode %p file %p rc %d",inode,file,rc));
1176
1177         return rc;
1178 }
1179
1180 ssize_t cifs_user_read(struct file *file, char __user *read_data,
1181         size_t read_size, loff_t *poffset)
1182 {
1183         int rc = -EACCES;
1184         unsigned int bytes_read = 0;
1185         unsigned int total_read = 0;
1186         unsigned int current_read_size;
1187         struct cifs_sb_info *cifs_sb;
1188         struct cifsTconInfo *pTcon;
1189         int xid;
1190         struct cifsFileInfo *open_file;
1191         char *smb_read_data;
1192         char __user *current_offset;
1193         struct smb_com_read_rsp *pSMBr;
1194
1195         xid = GetXid();
1196         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1197         pTcon = cifs_sb->tcon;
1198
1199         if (file->private_data == NULL) {
1200                 FreeXid(xid);
1201                 return -EBADF;
1202         }
1203         open_file = (struct cifsFileInfo *)file->private_data;
1204
1205         if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
1206                 cFYI(1, ("attempting read on write only file instance"));
1207         }
1208         for (total_read = 0, current_offset = read_data;
1209              read_size > total_read;
1210              total_read += bytes_read, current_offset += bytes_read) {
1211                 current_read_size = min_t(const int, read_size - total_read, 
1212                                           cifs_sb->rsize);
1213                 rc = -EAGAIN;
1214                 smb_read_data = NULL;
1215                 while (rc == -EAGAIN) {
1216                         if ((open_file->invalidHandle) && 
1217                             (!open_file->closePend)) {
1218                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1219                                         file, TRUE);
1220                                 if (rc != 0)
1221                                         break;
1222                         }
1223
1224                         rc = CIFSSMBRead(xid, pTcon,
1225                                  open_file->netfid,
1226                                  current_read_size, *poffset,
1227                                  &bytes_read, &smb_read_data);
1228
1229                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1230                         if (copy_to_user(current_offset, 
1231                                          smb_read_data + 4 /* RFC1001 hdr */
1232                                          + le16_to_cpu(pSMBr->DataOffset), 
1233                                          bytes_read)) {
1234                                 rc = -EFAULT;
1235                                 FreeXid(xid);
1236                                 return rc;
1237             }
1238                         if (smb_read_data) {
1239                                 cifs_buf_release(smb_read_data);
1240                                 smb_read_data = NULL;
1241                         }
1242                 }
1243                 if (rc || (bytes_read == 0)) {
1244                         if (total_read) {
1245                                 break;
1246                         } else {
1247                                 FreeXid(xid);
1248                                 return rc;
1249                         }
1250                 } else {
1251 #ifdef CONFIG_CIFS_STATS
1252                         atomic_inc(&pTcon->num_reads);
1253                         spin_lock(&pTcon->stat_lock);
1254                         pTcon->bytes_read += total_read;
1255                         spin_unlock(&pTcon->stat_lock);
1256 #endif
1257                         *poffset += bytes_read;
1258                 }
1259         }
1260         FreeXid(xid);
1261         return total_read;
1262 }
1263
1264
1265 static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
1266         loff_t *poffset)
1267 {
1268         int rc = -EACCES;
1269         unsigned int bytes_read = 0;
1270         unsigned int total_read;
1271         unsigned int current_read_size;
1272         struct cifs_sb_info *cifs_sb;
1273         struct cifsTconInfo *pTcon;
1274         int xid;
1275         char *current_offset;
1276         struct cifsFileInfo *open_file;
1277
1278         xid = GetXid();
1279         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1280         pTcon = cifs_sb->tcon;
1281
1282         if (file->private_data == NULL) {
1283                 FreeXid(xid);
1284                 return -EBADF;
1285         }
1286         open_file = (struct cifsFileInfo *)file->private_data;
1287
1288         if ((file->f_flags & O_ACCMODE) == O_WRONLY)
1289                 cFYI(1, ("attempting read on write only file instance"));
1290
1291         for (total_read = 0, current_offset = read_data; 
1292              read_size > total_read;
1293              total_read += bytes_read, current_offset += bytes_read) {
1294                 current_read_size = min_t(const int, read_size - total_read,
1295                                           cifs_sb->rsize);
1296                 rc = -EAGAIN;
1297                 while (rc == -EAGAIN) {
1298                         if ((open_file->invalidHandle) && 
1299                             (!open_file->closePend)) {
1300                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1301                                         file, TRUE);
1302                                 if (rc != 0)
1303                                         break;
1304                         }
1305
1306                         rc = CIFSSMBRead(xid, pTcon,
1307                                  open_file->netfid,
1308                                  current_read_size, *poffset,
1309                                  &bytes_read, &current_offset);
1310                 }
1311                 if (rc || (bytes_read == 0)) {
1312                         if (total_read) {
1313                                 break;
1314                         } else {
1315                                 FreeXid(xid);
1316                                 return rc;
1317                         }
1318                 } else {
1319 #ifdef CONFIG_CIFS_STATS
1320                         atomic_inc(&pTcon->num_reads);
1321                         spin_lock(&pTcon->stat_lock);
1322                         pTcon->bytes_read += total_read;
1323                         spin_unlock(&pTcon->stat_lock);
1324 #endif
1325                         *poffset += bytes_read;
1326                 }
1327         }
1328         FreeXid(xid);
1329         return total_read;
1330 }
1331
1332 int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
1333 {
1334         struct dentry *dentry = file->f_dentry;
1335         int rc, xid;
1336
1337         xid = GetXid();
1338         rc = cifs_revalidate(dentry);
1339         if (rc) {
1340                 cFYI(1, ("Validation prior to mmap failed, error=%d", rc));
1341                 FreeXid(xid);
1342                 return rc;
1343         }
1344         rc = generic_file_mmap(file, vma);
1345         FreeXid(xid);
1346         return rc;
1347 }
1348
1349
1350 static void cifs_copy_cache_pages(struct address_space *mapping, 
1351         struct list_head *pages, int bytes_read, char *data,
1352         struct pagevec *plru_pvec)
1353 {
1354         struct page *page;
1355         char *target;
1356
1357         while (bytes_read > 0) {
1358                 if (list_empty(pages))
1359                         break;
1360
1361                 page = list_entry(pages->prev, struct page, lru);
1362                 list_del(&page->lru);
1363
1364                 if (add_to_page_cache(page, mapping, page->index,
1365                                       GFP_KERNEL)) {
1366                         page_cache_release(page);
1367                         cFYI(1, ("Add page cache failed"));
1368                         continue;
1369                 }
1370
1371                 target = kmap_atomic(page,KM_USER0);
1372
1373                 if (PAGE_CACHE_SIZE > bytes_read) {
1374                         memcpy(target, data, bytes_read);
1375                         /* zero the tail end of this partial page */
1376                         memset(target + bytes_read, 0, 
1377                                PAGE_CACHE_SIZE - bytes_read);
1378                         bytes_read = 0;
1379                 } else {
1380                         memcpy(target, data, PAGE_CACHE_SIZE);
1381                         bytes_read -= PAGE_CACHE_SIZE;
1382                 }
1383                 kunmap_atomic(target, KM_USER0);
1384
1385                 flush_dcache_page(page);
1386                 SetPageUptodate(page);
1387                 unlock_page(page);
1388                 if (!pagevec_add(plru_pvec, page))
1389                         __pagevec_lru_add(plru_pvec);
1390                 data += PAGE_CACHE_SIZE;
1391         }
1392         return;
1393 }
1394
1395 static int cifs_readpages(struct file *file, struct address_space *mapping,
1396         struct list_head *page_list, unsigned num_pages)
1397 {
1398         int rc = -EACCES;
1399         int xid;
1400         loff_t offset;
1401         struct page *page;
1402         struct cifs_sb_info *cifs_sb;
1403         struct cifsTconInfo *pTcon;
1404         int bytes_read = 0;
1405         unsigned int read_size,i;
1406         char *smb_read_data = NULL;
1407         struct smb_com_read_rsp *pSMBr;
1408         struct pagevec lru_pvec;
1409         struct cifsFileInfo *open_file;
1410
1411         xid = GetXid();
1412         if (file->private_data == NULL) {
1413                 FreeXid(xid);
1414                 return -EBADF;
1415         }
1416         open_file = (struct cifsFileInfo *)file->private_data;
1417         cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1418         pTcon = cifs_sb->tcon;
1419
1420         pagevec_init(&lru_pvec, 0);
1421
1422         for (i = 0; i < num_pages; ) {
1423                 unsigned contig_pages;
1424                 struct page *tmp_page;
1425                 unsigned long expected_index;
1426
1427                 if (list_empty(page_list))
1428                         break;
1429
1430                 page = list_entry(page_list->prev, struct page, lru);
1431                 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1432
1433                 /* count adjacent pages that we will read into */
1434                 contig_pages = 0;
1435                 expected_index = 
1436                         list_entry(page_list->prev, struct page, lru)->index;
1437                 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1438                         if (tmp_page->index == expected_index) {
1439                                 contig_pages++;
1440                                 expected_index++;
1441                         } else
1442                                 break; 
1443                 }
1444                 if (contig_pages + i >  num_pages)
1445                         contig_pages = num_pages - i;
1446
1447                 /* for reads over a certain size could initiate async
1448                    read ahead */
1449
1450                 read_size = contig_pages * PAGE_CACHE_SIZE;
1451                 /* Read size needs to be in multiples of one page */
1452                 read_size = min_t(const unsigned int, read_size,
1453                                   cifs_sb->rsize & PAGE_CACHE_MASK);
1454
1455                 rc = -EAGAIN;
1456                 while (rc == -EAGAIN) {
1457                         if ((open_file->invalidHandle) && 
1458                             (!open_file->closePend)) {
1459                                 rc = cifs_reopen_file(file->f_dentry->d_inode,
1460                                         file, TRUE);
1461                                 if (rc != 0)
1462                                         break;
1463                         }
1464
1465                         rc = CIFSSMBRead(xid, pTcon,
1466                                 open_file->netfid,
1467                                 read_size, offset,
1468                                 &bytes_read, &smb_read_data);
1469                         /* BB need to check return code here */
1470                         if (rc== -EAGAIN) {
1471                                 if (smb_read_data) {
1472                                         cifs_buf_release(smb_read_data);
1473                                         smb_read_data = NULL;
1474                                 }
1475                         }
1476                 }
1477                 if ((rc < 0) || (smb_read_data == NULL)) {
1478                         cFYI(1, ("Read error in readpages: %d", rc));
1479                         /* clean up remaing pages off list */
1480                         while (!list_empty(page_list) && (i < num_pages)) {
1481                                 page = list_entry(page_list->prev, struct page,
1482                                                   lru);
1483                                 list_del(&page->lru);
1484                                 page_cache_release(page);
1485                         }
1486                         break;
1487                 } else if (bytes_read > 0) {
1488                         pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1489                         cifs_copy_cache_pages(mapping, page_list, bytes_read,
1490                                 smb_read_data + 4 /* RFC1001 hdr */ +
1491                                 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1492
1493                         i +=  bytes_read >> PAGE_CACHE_SHIFT;
1494 #ifdef CONFIG_CIFS_STATS
1495                         atomic_inc(&pTcon->num_reads);
1496                         spin_lock(&pTcon->stat_lock);
1497                         pTcon->bytes_read += bytes_read;
1498                         spin_unlock(&pTcon->stat_lock);
1499 #endif
1500                         if ((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1501                                 i++; /* account for partial page */
1502
1503                                 /* server copy of file can have smaller size 
1504                                    than client */
1505                                 /* BB do we need to verify this common case ? 
1506                                    this case is ok - if we are at server EOF 
1507                                    we will hit it on next read */
1508
1509                         /* while (!list_empty(page_list) && (i < num_pages)) {
1510                                         page = list_entry(page_list->prev, 
1511                                                           struct page, list);
1512                                         list_del(&page->list);
1513                                         page_cache_release(page);
1514                                 }
1515                                 break; */
1516                         }
1517                 } else {
1518                         cFYI(1, ("No bytes read (%d) at offset %lld . "
1519                                  "Cleaning remaining pages from readahead list",
1520                                  bytes_read, offset));
1521                         /* BB turn off caching and do new lookup on 
1522                            file size at server? */
1523                         while (!list_empty(page_list) && (i < num_pages)) {
1524                                 page = list_entry(page_list->prev, struct page,
1525                                                   lru);
1526                                 list_del(&page->lru);
1527
1528                                 /* BB removeme - replace with zero of page? */
1529                                 page_cache_release(page);
1530                         }
1531                         break;
1532                 }
1533                 if (smb_read_data) {
1534                         cifs_buf_release(smb_read_data);
1535                         smb_read_data = NULL;
1536                 }
1537                 bytes_read = 0;
1538         }
1539
1540         pagevec_lru_add(&lru_pvec);
1541
1542 /* need to free smb_read_data buf before exit */
1543         if (smb_read_data) {
1544                 cifs_buf_release(smb_read_data);
1545                 smb_read_data = NULL;
1546         } 
1547
1548         FreeXid(xid);
1549         return rc;
1550 }
1551
1552 static int cifs_readpage_worker(struct file *file, struct page *page,
1553         loff_t *poffset)
1554 {
1555         char *read_data;
1556         int rc;
1557
1558         page_cache_get(page);
1559         read_data = kmap(page);
1560         /* for reads over a certain size could initiate async read ahead */
1561                                                                                                                            
1562         rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1563                                                                                                                            
1564         if (rc < 0)
1565                 goto io_error;
1566         else
1567                 cFYI(1, ("Bytes read %d ",rc));
1568                                                                                                                            
1569         file->f_dentry->d_inode->i_atime =
1570                 current_fs_time(file->f_dentry->d_inode->i_sb);
1571                                                                                                                            
1572         if (PAGE_CACHE_SIZE > rc)
1573                 memset(read_data + rc, 0, PAGE_CACHE_SIZE - rc);
1574
1575         flush_dcache_page(page);
1576         SetPageUptodate(page);
1577         rc = 0;
1578                                                                                                                            
1579 io_error:
1580         kunmap(page);
1581         page_cache_release(page);
1582         return rc;
1583 }
1584
1585 static int cifs_readpage(struct file *file, struct page *page)
1586 {
1587         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1588         int rc = -EACCES;
1589         int xid;
1590
1591         xid = GetXid();
1592
1593         if (file->private_data == NULL) {
1594                 FreeXid(xid);
1595                 return -EBADF;
1596         }
1597
1598         cFYI(1, ("readpage %p at offset %d 0x%x\n", 
1599                  page, (int)offset, (int)offset));
1600
1601         rc = cifs_readpage_worker(file, page, &offset);
1602
1603         unlock_page(page);
1604
1605         FreeXid(xid);
1606         return rc;
1607 }
1608
1609 /* We do not want to update the file size from server for inodes
1610    open for write - to avoid races with writepage extending
1611    the file - in the future we could consider allowing
1612    refreshing the inode only on increases in the file size 
1613    but this is tricky to do without racing with writebehind
1614    page caching in the current Linux kernel design */
1615 int is_size_safe_to_change(struct cifsInodeInfo *cifsInode)
1616 {
1617         struct list_head *tmp;
1618         struct list_head *tmp1;
1619         struct cifsFileInfo *open_file = NULL;
1620         int rc = TRUE;
1621
1622         if (cifsInode == NULL)
1623                 return rc;
1624
1625         read_lock(&GlobalSMBSeslock); 
1626         list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {            
1627                 open_file = list_entry(tmp, struct cifsFileInfo, flist);
1628                 if (open_file == NULL)
1629                         break;
1630                 if (open_file->closePend)
1631                         continue;
1632         /* We check if file is open for writing,   
1633            BB we could supplement this with a check to see if file size
1634            changes have been flushed to server - ie inode metadata dirty */
1635                 if ((open_file->pfile) && 
1636                     ((open_file->pfile->f_flags & O_RDWR) || 
1637                     (open_file->pfile->f_flags & O_WRONLY))) {
1638                         rc = FALSE;
1639                         break;
1640                 }
1641                 if (tmp->next == NULL) {
1642                         cFYI(1, ("File instance %p removed", tmp));
1643                         break;
1644                 }
1645         }
1646         read_unlock(&GlobalSMBSeslock);
1647         return rc;
1648 }
1649
1650
1651 static int cifs_prepare_write(struct file *file, struct page *page,
1652         unsigned from, unsigned to)
1653 {
1654         int rc = 0;
1655         loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1656         cFYI(1, ("prepare write for page %p from %d to %d",page,from,to));
1657         if (!PageUptodate(page)) {
1658         /*      if (to - from != PAGE_CACHE_SIZE) {
1659                         void *kaddr = kmap_atomic(page, KM_USER0);
1660                         memset(kaddr, 0, from);
1661                         memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1662                         flush_dcache_page(page);
1663                         kunmap_atomic(kaddr, KM_USER0);
1664                 } */
1665                 /* If we are writing a full page it will be up to date,
1666                    no need to read from the server */
1667                 if ((to == PAGE_CACHE_SIZE) && (from == 0))
1668                         SetPageUptodate(page);
1669
1670                 /* might as well read a page, it is fast enough */
1671                 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
1672                         rc = cifs_readpage_worker(file, page, &offset);
1673                 } else {
1674                 /* should we try using another file handle if there is one -
1675                    how would we lock it to prevent close of that handle
1676                    racing with this read?
1677                    In any case this will be written out by commit_write */
1678                 }
1679         }
1680
1681         /* BB should we pass any errors back? 
1682            e.g. if we do not have read access to the file */
1683         return 0;
1684 }
1685
1686 struct address_space_operations cifs_addr_ops = {
1687         .readpage = cifs_readpage,
1688         .readpages = cifs_readpages,
1689         .writepage = cifs_writepage,
1690         .prepare_write = cifs_prepare_write,
1691         .commit_write = cifs_commit_write,
1692         .set_page_dirty = __set_page_dirty_nobuffers,
1693         /* .sync_page = cifs_sync_page, */
1694         /* .direct_IO = */
1695 };