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