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