1 /*
2 * fs/cifs/file.c
3 *
4 * vfs operations that deal with files
5 *
6 * Copyright (C) International Business Machines Corp., 2002,2003
7 * Author(s): Steve French (sfrench@us.ibm.com)
8 *
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23 #include <linux/fs.h>
24 #include <linux/stat.h>
25 #include <linux/fcntl.h>
26 #include <linux/pagemap.h>
27 #include <linux/pagevec.h>
28 #include <linux/smp_lock.h>
29 #include <asm/div64.h>
30 #include "cifsfs.h"
31 #include "cifspdu.h"
32 #include "cifsglob.h"
33 #include "cifsproto.h"
34 #include "cifs_unicode.h"
35 #include "cifs_debug.h"
36 #include "cifs_fs_sb.h"
37
38 extern int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir); /* BB removeme BB */
39
40 int
41 cifs_open(struct inode *inode, struct file *file)
42 {
43 int rc = -EACCES;
44 int xid, oplock;
45 struct cifs_sb_info *cifs_sb;
46 struct cifsTconInfo *pTcon;
47 struct cifsFileInfo *pCifsFile;
48 struct cifsInodeInfo *pCifsInode;
49 struct list_head * tmp;
50 char *full_path = NULL;
51 int desiredAccess = 0x20197;
52 int disposition;
53 __u16 netfid;
54 FILE_ALL_INFO * buf = NULL;
55
56 xid = GetXid();
57
58 cifs_sb = CIFS_SB(inode->i_sb);
59 pTcon = cifs_sb->tcon;
60
61 if (file->f_flags & O_CREAT) {
62 /* search inode for this file and fill in file->private_data = */
63 pCifsInode = CIFS_I(file->f_dentry->d_inode);
64 read_lock(&GlobalSMBSeslock);
65 list_for_each(tmp, &pCifsInode->openFileList) {
66 pCifsFile = list_entry(tmp,struct cifsFileInfo, flist);
67 if((pCifsFile->pfile == NULL)&& (pCifsFile->pid == current->tgid)){
68 /* mode set in cifs_create */
69 pCifsFile->pfile = file; /* needed for writepage */
70 file->private_data = pCifsFile;
71 break;
72 }
73 }
74 read_unlock(&GlobalSMBSeslock);
75 if(file->private_data != NULL) {
76 rc = 0;
77 FreeXid(xid);
78 return rc;
79 } else {
80 if(file->f_flags & O_EXCL)
81 cERROR(1,("could not find file instance for new file %p ",file));
82 }
83 }
84
85 down(&inode->i_sb->s_vfs_rename_sem);
86 full_path = build_path_from_dentry(file->f_dentry);
87 up(&inode->i_sb->s_vfs_rename_sem);
88 if(full_path == NULL) {
89 FreeXid(xid);
90 return -ENOMEM;
91 }
92
93 cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
94 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
95 desiredAccess = GENERIC_READ;
96 else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
97 desiredAccess = GENERIC_WRITE;
98 else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
99 /* GENERIC_ALL is too much permission to request */
100 /* can cause unnecessary access denied on create */
101 /* desiredAccess = GENERIC_ALL; */
102 desiredAccess = GENERIC_READ | GENERIC_WRITE;
103 }
104
105 /*********************************************************************
106 * open flag mapping table:
107 *
108 * POSIX Flag CIFS Disposition
109 * ---------- ----------------
110 * O_CREAT FILE_OPEN_IF
111 * O_CREAT | O_EXCL FILE_CREATE
112 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
113 * O_TRUNC FILE_OVERWRITE
114 * none of the above FILE_OPEN
115 *
116 * Note that there is not a direct match between disposition
117 * FILE_SUPERSEDE (ie create whether or not file exists although
118 * O_CREAT | O_TRUNC is similar but truncates the existing
119 * file rather than creating a new file as FILE_SUPERSEDE does
120 * (which uses the attributes / metadata passed in on open call)
121 *?
122 *? O_SYNC is a reasonable match to CIFS writethrough flag
123 *? and the read write flags match reasonably. O_LARGEFILE
124 *? is irrelevant because largefile support is always used
125 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
126 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
127 *********************************************************************/
128
129 if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
130 disposition = FILE_CREATE;
131 else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
132 disposition = FILE_OVERWRITE_IF;
133 else if((file->f_flags & O_CREAT) == O_CREAT)
134 disposition = FILE_OPEN_IF;
135 else
136 disposition = FILE_OPEN;
137
138 if (oplockEnabled)
139 oplock = REQ_OPLOCK;
140 else
141 oplock = FALSE;
142
143 /* BB pass O_SYNC flag through on file attributes .. BB */
144
145 /* Also refresh inode by passing in file_info buf returned by SMBOpen
146 and calling get_inode_info with returned buf (at least
147 helps non-Unix server case */
148
149 /* BB we can not do this if this is the second open of a file
150 and the first handle has writebehind data, we might be
151 able to simply do a filemap_fdatawrite/filemap_fdatawait first */
152 buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
153 if(buf== NULL) {
154 if (full_path)
155 kfree(full_path);
156 FreeXid(xid);
157 return -ENOMEM;
158 }
159 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
160 CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
161 if (rc) {
162 cFYI(1, ("cifs_open returned 0x%x ", rc));
163 cFYI(1, ("oplock: %d ", oplock));
164 } else {
165 file->private_data =
166 kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
167 if (file->private_data) {
168 memset(file->private_data, 0, sizeof(struct cifsFileInfo));
169 pCifsFile = (struct cifsFileInfo *) file->private_data;
170 pCifsFile->netfid = netfid;
171 pCifsFile->pid = current->tgid;
172 init_MUTEX(&pCifsFile->fh_sem);
173 pCifsFile->pfile = file; /* needed for writepage */
174 pCifsFile->pInode = inode;
175 pCifsFile->invalidHandle = FALSE;
176 pCifsFile->closePend = FALSE;
177 write_lock(&file->f_owner.lock);
178 write_lock(&GlobalSMBSeslock);
179 list_add(&pCifsFile->tlist,&pTcon->openFileList);
180 pCifsInode = CIFS_I(file->f_dentry->d_inode);
181 if(pCifsInode) {
182 /* want handles we can use to read with first */
183 /* in the list so we do not have to walk the */
184 /* list to search for one in prepare_write */
185 if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
186 list_add_tail(&pCifsFile->flist,&pCifsInode->openFileList);
187 } else {
188 list_add(&pCifsFile->flist,&pCifsInode->openFileList);
189 }
190 write_unlock(&GlobalSMBSeslock);
191 write_unlock(&file->f_owner.lock);
192 if(pCifsInode->clientCanCacheRead) {
193 /* we have the inode open somewhere else
194 no need to discard cache data */
195 } else {
196 if(buf) {
197 /* BB need same check in cifs_create too? */
198
199 /* if not oplocked, invalidate inode pages if mtime
200 or file size changed */
201 struct timespec temp;
202 temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
203 if(timespec_equal(&file->f_dentry->d_inode->i_mtime,&temp) &&
204 (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
205 cFYI(1,("inode unchanged on server"));
206 } else {
207 if(file->f_dentry->d_inode->i_mapping) {
208 /* BB no need to lock inode until after invalidate*/
209 /* since namei code should already have it locked?*/
210 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
211 filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
212 }
213 cFYI(1,("invalidating remote inode since open detected it changed"));
214 invalidate_remote_inode(file->f_dentry->d_inode);
215 }
216 }
217 }
218 if (pTcon->ses->capabilities & CAP_UNIX)
219 rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
220 full_path, inode->i_sb,xid);
221 else
222 rc = cifs_get_inode_info(&file->f_dentry->d_inode,
223 full_path, buf, inode->i_sb,xid);
224
225 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
226 pCifsInode->clientCanCacheAll = TRUE;
227 pCifsInode->clientCanCacheRead = TRUE;
228 cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
229 } else if((oplock & 0xF) == OPLOCK_READ)
230 pCifsInode->clientCanCacheRead = TRUE;
231 } else {
232 write_unlock(&GlobalSMBSeslock);
233 write_unlock(&file->f_owner.lock);
234 }
235 if(oplock & CIFS_CREATE_ACTION) {
236 /* time to set mode which we can not set earlier due
237 to problems creating new read-only files */
238 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
239 CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
240 (__u64)-1,
241 (__u64)-1,
242 0 /* dev */,
243 cifs_sb->local_nls);
244 else {/* BB implement via Windows security descriptors */
245 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
246 /* in the meantime could set r/o dos attribute when perms are eg:
247 mode & 0222 == 0 */
248 }
249 }
250 }
251 }
252
253 if (buf)
254 kfree(buf);
255 if (full_path)
256 kfree(full_path);
257 FreeXid(xid);
258 return rc;
259 }
260
261 /* Try to reaquire byte range locks that were released when session */
262 /* to server was lost */
263 static int cifs_relock_file(struct cifsFileInfo * cifsFile)
264 {
265 int rc = 0;
266
267 /* BB list all locks open on this file and relock */
268
269 return rc;
270 }
271
272 static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush)
273 {
274 int rc = -EACCES;
275 int xid, oplock;
276 struct cifs_sb_info *cifs_sb;
277 struct cifsTconInfo *pTcon;
278 struct cifsFileInfo *pCifsFile;
279 struct cifsInodeInfo *pCifsInode;
280 char *full_path = NULL;
281 int desiredAccess = 0x20197;
282 int disposition = FILE_OPEN;
283 __u16 netfid;
284
285 if(inode == NULL)
286 return -EBADF;
287 if (file->private_data) {
288 pCifsFile = (struct cifsFileInfo *) file->private_data;
289 } else
290 return -EBADF;
291
292 xid = GetXid();
293 down(&pCifsFile->fh_sem);
294 if(pCifsFile->invalidHandle == FALSE) {
295 up(&pCifsFile->fh_sem);
296 FreeXid(xid);
297 return 0;
298 }
299
300 if(file->f_dentry == NULL) {
301 up(&pCifsFile->fh_sem);
302 cFYI(1,("failed file reopen, no valid name if dentry freed"));
303 FreeXid(xid);
304 return -EBADF;
305 }
306 cifs_sb = CIFS_SB(inode->i_sb);
307 pTcon = cifs_sb->tcon;
308 /* can not grab rename sem here because various ops, including
309 those that already have the rename sem can end up causing writepage
310 to get called and if the server was down that means we end up here,
311 and we can never tell if the caller already has the rename_sem */
312 full_path = build_path_from_dentry(file->f_dentry);
313 if(full_path == NULL) {
314 up(&pCifsFile->fh_sem);
315 FreeXid(xid);
316 return -ENOMEM;
317 }
318
319 cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
320 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
321 desiredAccess = GENERIC_READ;
322 else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
323 desiredAccess = GENERIC_WRITE;
324 else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
325 /* GENERIC_ALL is too much permission to request */
326 /* can cause unnecessary access denied on create */
327 /* desiredAccess = GENERIC_ALL; */
328 desiredAccess = GENERIC_READ | GENERIC_WRITE;
329 }
330
331 if (oplockEnabled)
332 oplock = REQ_OPLOCK;
333 else
334 oplock = FALSE;
335
336
337 /* Can not refresh inode by passing in file_info buf to be returned
338 by SMBOpen and then calling get_inode_info with returned buf
339 since file might have write behind data that needs to be flushed
340 and server version of file size can be stale. If we
341 knew for sure that inode was not dirty locally we could do this */
342
343 /* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
344 if(buf==0) {
345 up(&pCifsFile->fh_sem);
346 if (full_path)
347 kfree(full_path);
348 FreeXid(xid);
349 return -ENOMEM;
350 }*/
351 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
352 CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
353 if (rc) {
354 up(&pCifsFile->fh_sem);
355 cFYI(1, ("cifs_open returned 0x%x ", rc));
356 cFYI(1, ("oplock: %d ", oplock));
357 } else {
358 pCifsFile->netfid = netfid;
359 pCifsFile->invalidHandle = FALSE;
360 up(&pCifsFile->fh_sem);
361 pCifsInode = CIFS_I(inode);
362 if(pCifsInode) {
363 if(can_flush) {
364 filemap_fdatawrite(inode->i_mapping);
365 filemap_fdatawait(inode->i_mapping);
366 /* temporarily disable caching while we
367 go to server to get inode info */
368 pCifsInode->clientCanCacheAll = FALSE;
369 pCifsInode->clientCanCacheRead = FALSE;
370 if (pTcon->ses->capabilities & CAP_UNIX)
371 rc = cifs_get_inode_info_unix(&inode,
372 full_path, inode->i_sb,xid);
373 else
374 rc = cifs_get_inode_info(&inode,
375 full_path, NULL, inode->i_sb,xid);
376 } /* else we are writing out data to server already
377 and could deadlock if we tried to flush data, and
378 since we do not know if we have data that would
379 invalidate the current end of file on the server
380 we can not go to the server to get the new
381 inod info */
382 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
383 pCifsInode->clientCanCacheAll = TRUE;
384 pCifsInode->clientCanCacheRead = TRUE;
385 cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
386 } else if((oplock & 0xF) == OPLOCK_READ) {
387 pCifsInode->clientCanCacheRead = TRUE;
388 pCifsInode->clientCanCacheAll = FALSE;
389 } else {
390 pCifsInode->clientCanCacheRead = FALSE;
391 pCifsInode->clientCanCacheAll = FALSE;
392 }
393 cifs_relock_file(pCifsFile);
394 }
395 }
396
397 if (full_path)
398 kfree(full_path);
399 FreeXid(xid);
400 return rc;
401 }
402
403 int
404 cifs_close(struct inode *inode, struct file *file)
405 {
406 int rc = 0;
407 int xid;
408 struct cifs_sb_info *cifs_sb;
409 struct cifsTconInfo *pTcon;
410 struct cifsFileInfo *pSMBFile =
411 (struct cifsFileInfo *) file->private_data;
412
413 xid = GetXid();
414
415 cifs_sb = CIFS_SB(inode->i_sb);
416 pTcon = cifs_sb->tcon;
417 if (pSMBFile) {
418 pSMBFile->closePend = TRUE;
419 write_lock(&file->f_owner.lock);
420 if(pTcon) {
421 /* no sense reconnecting to close a file that is
422 already closed */
423 if (pTcon->tidStatus != CifsNeedReconnect) {
424 write_unlock(&file->f_owner.lock);
425 rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
426 write_lock(&file->f_owner.lock);
427 }
428 }
429 list_del(&pSMBFile->flist);
430 list_del(&pSMBFile->tlist);
431 write_unlock(&file->f_owner.lock);
432 if(pSMBFile->search_resume_name)
433 kfree(pSMBFile->search_resume_name);
434 kfree(file->private_data);
435 file->private_data = NULL;
436 } else
437 rc = -EBADF;
438
439 if(list_empty(&(CIFS_I(inode)->openFileList))) {
440 cFYI(1,("closing last open instance for inode %p",inode));
441 /* if the file is not open we do not know if we can cache
442 info on this inode, much less write behind and read ahead */
443 CIFS_I(inode)->clientCanCacheRead = FALSE;
444 CIFS_I(inode)->clientCanCacheAll = FALSE;
445 }
446 if((rc ==0) && CIFS_I(inode)->write_behind_rc)
447 rc = CIFS_I(inode)->write_behind_rc;
448 FreeXid(xid);
449 return rc;
450 }
451
452 int
453 cifs_closedir(struct inode *inode, struct file *file)
454 {
455 int rc = 0;
456 int xid;
457 struct cifsFileInfo *pCFileStruct =
458 (struct cifsFileInfo *) file->private_data;
459 char * ptmp;
460
461 cFYI(1, ("Closedir inode = 0x%p with ", inode));
462
463 xid = GetXid();
464
465 if (pCFileStruct) {
466 struct cifsTconInfo *pTcon;
467 struct cifs_sb_info * cifs_sb = CIFS_SB(file->f_dentry->d_sb);
468
469 pTcon = cifs_sb->tcon;
470
471 cFYI(1, ("Freeing private data in close dir"));
472 if(pCFileStruct->srch_inf.endOfSearch == FALSE) {
473 pCFileStruct->invalidHandle = TRUE;
474 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
475 cFYI(1,("Closing uncompleted readdir with rc %d",rc));
476 /* not much we can do if it fails anywway, ignore rc */
477 rc = 0;
478 }
479 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
480 if(ptmp) {
481 cFYI(1,("freeing smb buf in srch struct in closedir")); /* BB removeme BB */
482 pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
483 cifs_buf_release(ptmp);
484 }
485 ptmp = pCFileStruct->search_resume_name;
486 if(ptmp) {
487 cFYI(1,("freeing resume name in closedir")); /* BB removeme BB */
488 pCFileStruct->search_resume_name = NULL;
489 kfree(ptmp);
490 }
491 kfree(file->private_data);
492 file->private_data = NULL;
493 }
494 /* BB can we lock the filestruct while this is going on? */
495 FreeXid(xid);
496 return rc;
497 }
498
499 int
500 cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
501 {
502 int rc, xid;
503 __u32 lockType = LOCKING_ANDX_LARGE_FILES;
504 __u32 numLock = 0;
505 __u32 numUnlock = 0;
506 __u64 length;
507 int wait_flag = FALSE;
508 struct cifs_sb_info *cifs_sb;
509 struct cifsTconInfo *pTcon;
510 length = 1 + pfLock->fl_end - pfLock->fl_start;
511
512 rc = -EACCES;
513
514 xid = GetXid();
515
516 cFYI(1,
517 ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
518 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
519 pfLock->fl_end));
520
521 if (pfLock->fl_flags & FL_POSIX)
522 cFYI(1, ("Posix "));
523 if (pfLock->fl_flags & FL_FLOCK)
524 cFYI(1, ("Flock "));
525 if (pfLock->fl_flags & FL_SLEEP) {
526 cFYI(1, ("Blocking lock "));
527 wait_flag = TRUE;
528 }
529 if (pfLock->fl_flags & FL_ACCESS)
530 cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
531 if (pfLock->fl_flags & FL_LEASE)
532 cFYI(1, ("Lease on file - not implemented yet"));
533 if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
534 cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
535
536 if (pfLock->fl_type == F_WRLCK) {
537 cFYI(1, ("F_WRLCK "));
538 numLock = 1;
539 } else if (pfLock->fl_type == F_UNLCK) {
540 cFYI(1, ("F_UNLCK "));
541 numUnlock = 1;
542 } else if (pfLock->fl_type == F_RDLCK) {
543 cFYI(1, ("F_RDLCK "));
544 lockType |= LOCKING_ANDX_SHARED_LOCK;
545 numLock = 1;
546 } else if (pfLock->fl_type == F_EXLCK) {
547 cFYI(1, ("F_EXLCK "));
548 numLock = 1;
549 } else if (pfLock->fl_type == F_SHLCK) {
550 cFYI(1, ("F_SHLCK "));
551 lockType |= LOCKING_ANDX_SHARED_LOCK;
552 numLock = 1;
553 } else
554 cFYI(1, ("Unknown type of lock "));
555
556 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
557 pTcon = cifs_sb->tcon;
558
559 if (file->private_data == NULL) {
560 FreeXid(xid);
561 return -EBADF;
562 }
563
564 if (IS_GETLK(cmd)) {
565 rc = CIFSSMBLock(xid, pTcon,
566 ((struct cifsFileInfo *) file->
567 private_data)->netfid,
568 length,
569 pfLock->fl_start, 0, 1, lockType,
570 0 /* wait flag */ );
571 if (rc == 0) {
572 rc = CIFSSMBLock(xid, pTcon,
573 ((struct cifsFileInfo *) file->
574 private_data)->netfid,
575 length,
576 pfLock->fl_start, 1 /* numUnlock */ ,
577 0 /* numLock */ , lockType,
578 0 /* wait flag */ );
579 pfLock->fl_type = F_UNLCK;
580 if (rc != 0)
581 cERROR(1,
582 ("Error unlocking previously locked range %d during test of lock ",
583 rc));
584 rc = 0;
585
586 } else {
587 /* if rc == ERR_SHARING_VIOLATION ? */
588 rc = 0; /* do not change lock type to unlock since range in use */
589 }
590
591 FreeXid(xid);
592 return rc;
593 }
594
595 rc = CIFSSMBLock(xid, pTcon,
596 ((struct cifsFileInfo *) file->private_data)->
597 netfid, length,
598 pfLock->fl_start, numUnlock, numLock, lockType,
599 wait_flag);
600 if (rc == 0 && (pfLock->fl_flags & FL_POSIX))
601 posix_lock_file_wait(file, pfLock);
602 FreeXid(xid);
603 return rc;
604 }
605
606 ssize_t
607 cifs_user_write(struct file * file, const char __user * write_data,
608 size_t write_size, loff_t * poffset)
609 {
610 int rc = 0;
611 unsigned int bytes_written = 0;
612 unsigned int total_written;
613 struct cifs_sb_info *cifs_sb;
614 struct cifsTconInfo *pTcon;
615 int xid, long_op;
616 struct cifsFileInfo * open_file;
617
618 if(file->f_dentry == NULL)
619 return -EBADF;
620
621 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
622 if(cifs_sb == NULL) {
623 return -EBADF;
624 }
625 pTcon = cifs_sb->tcon;
626
627 /*cFYI(1,
628 (" write %d bytes to offset %lld of %s", write_size,
629 *poffset, file->f_dentry->d_name.name)); */
630
631 if (file->private_data == NULL) {
632 return -EBADF;
633 } else {
634 open_file = (struct cifsFileInfo *) file->private_data;
635 }
636
637 xid = GetXid();
638 if(file->f_dentry->d_inode == NULL) {
639 FreeXid(xid);
640 return -EBADF;
641 }
642
643 if (*poffset > file->f_dentry->d_inode->i_size)
644 long_op = 2; /* writes past end of file can take a long time */
645 else
646 long_op = 1;
647
648 for (total_written = 0; write_size > total_written;
649 total_written += bytes_written) {
650 rc = -EAGAIN;
651 while(rc == -EAGAIN) {
652 if(file->private_data == NULL) {
653 /* file has been closed on us */
654 FreeXid(xid);
655 /* if we have gotten here we have written some data
656 and blocked, and the file has been freed on us
657 while we blocked so return what we managed to write */
658 return total_written;
659 }
660 if(open_file->closePend) {
661 FreeXid(xid);
662 if(total_written)
663 return total_written;
664 else
665 return -EBADF;
666 }
667 if (open_file->invalidHandle) {
668 if((file->f_dentry == NULL) ||
669 (file->f_dentry->d_inode == NULL)) {
670 FreeXid(xid);
671 return total_written;
672 }
673 /* we could deadlock if we called
674 filemap_fdatawait from here so tell
675 reopen_file not to flush data to server now */
676 rc = cifs_reopen_file(file->f_dentry->d_inode,
677 file,FALSE);
678 if(rc != 0)
679 break;
680 }
681
682 rc = CIFSSMBWrite(xid, pTcon,
683 open_file->netfid,
684 write_size - total_written, *poffset,
685 &bytes_written,
686 NULL, write_data + total_written, long_op);
687 }
688 if (rc || (bytes_written == 0)) {
689 if (total_written)
690 break;
691 else {
692 FreeXid(xid);
693 return rc;
694 }
695 } else
696 *poffset += bytes_written;
697 long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
698 }
699
700 #ifdef CONFIG_CIFS_STATS
701 if(total_written > 0) {
702 atomic_inc(&pTcon->num_writes);
703 spin_lock(&pTcon->stat_lock);
704 pTcon->bytes_written += total_written;
705 spin_unlock(&pTcon->stat_lock);
706 }
707 #endif
708
709 /* since the write may have blocked check these pointers again */
710 if(file->f_dentry) {
711 if(file->f_dentry->d_inode) {
712 struct inode *inode = file->f_dentry->d_inode;
713 inode->i_ctime = inode->i_mtime =
714 current_fs_time(inode->i_sb);
715 if (total_written > 0) {
716 if (*poffset > file->f_dentry->d_inode->i_size)
717 i_size_write(file->f_dentry->d_inode, *poffset);
718 }
719 mark_inode_dirty_sync(file->f_dentry->d_inode);
720 }
721 }
722 FreeXid(xid);
723 return total_written;
724 }
725
726 static ssize_t
727 cifs_write(struct file * file, const char *write_data,
728 size_t write_size, loff_t * poffset)
729 {
730 int rc = 0;
731 unsigned int bytes_written = 0;
732 unsigned int total_written;
733 struct cifs_sb_info *cifs_sb;
734 struct cifsTconInfo *pTcon;
735 int xid, long_op;
736 struct cifsFileInfo * open_file;
737
738 if(file->f_dentry == NULL)
739 return -EBADF;
740
741 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
742 if(cifs_sb == NULL) {
743 return -EBADF;
744 }
745 pTcon = cifs_sb->tcon;
746
747 /*cFYI(1,
748 (" write %d bytes to offset %lld of %s", write_size,
749 *poffset, file->f_dentry->d_name.name)); */
750
751 if (file->private_data == NULL) {
752 return -EBADF;
753 } else {
754 open_file = (struct cifsFileInfo *) file->private_data;
755 }
756
757 xid = GetXid();
758 if(file->f_dentry->d_inode == NULL) {
759 FreeXid(xid);
760 return -EBADF;
761 }
762
763 if (*poffset > file->f_dentry->d_inode->i_size)
764 long_op = 2; /* writes past end of file can take a long time */
765 else
766 long_op = 1;
767
768 for (total_written = 0; write_size > total_written;
769 total_written += bytes_written) {
770 rc = -EAGAIN;
771 while(rc == -EAGAIN) {
772 if(file->private_data == NULL) {
773 /* file has been closed on us */
774 FreeXid(xid);
775 /* if we have gotten here we have written some data
776 and blocked, and the file has been freed on us
777 while we blocked so return what we managed to write */
778 return total_written;
779 }
780 if(open_file->closePend) {
781 FreeXid(xid);
782 if(total_written)
783 return total_written;
784 else
785 return -EBADF;
786 }
787 if (open_file->invalidHandle) {
788 if((file->f_dentry == NULL) ||
789 (file->f_dentry->d_inode == NULL)) {
790 FreeXid(xid);
791 return total_written;
792 }
793 /* we could deadlock if we called
794 filemap_fdatawait from here so tell
795 reopen_file not to flush data to server now */
796 rc = cifs_reopen_file(file->f_dentry->d_inode,
797 file,FALSE);
798 if(rc != 0)
799 break;
800 }
801
802 rc = CIFSSMBWrite(xid, pTcon,
803 open_file->netfid,
804 write_size - total_written, *poffset,
805 &bytes_written,
806 write_data + total_written, NULL, long_op);
807 }
808 if (rc || (bytes_written == 0)) {
809 if (total_written)
810 break;
811 else {
812 FreeXid(xid);
813 return rc;
814 }
815 } else
816 *poffset += bytes_written;
817 long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
818 }
819
820 #ifdef CONFIG_CIFS_STATS
821 if(total_written > 0) {
822 atomic_inc(&pTcon->num_writes);
823 spin_lock(&pTcon->stat_lock);
824 pTcon->bytes_written += total_written;
825 spin_unlock(&pTcon->stat_lock);
826 }
827 #endif
828
829 /* since the write may have blocked check these pointers again */
830 if(file->f_dentry) {
831 if(file->f_dentry->d_inode) {
832 file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
833 CURRENT_TIME;
834 if (total_written > 0) {
835 if (*poffset > file->f_dentry->d_inode->i_size)
836 i_size_write(file->f_dentry->d_inode, *poffset);
837 }
838 mark_inode_dirty_sync(file->f_dentry->d_inode);
839 }
840 }
841 FreeXid(xid);
842 return total_written;
843 }
844
845 static int
846 cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
847 {
848 struct address_space *mapping = page->mapping;
849 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
850 char * write_data;
851 int rc = -EFAULT;
852 int bytes_written = 0;
853 struct cifs_sb_info *cifs_sb;
854 struct cifsTconInfo *pTcon;
855 struct inode *inode;
856 struct cifsInodeInfo *cifsInode;
857 struct cifsFileInfo *open_file = NULL;
858 struct list_head *tmp;
859 struct list_head *tmp1;
860
861 if (!mapping) {
862 return -EFAULT;
863 } else if(!mapping->host) {
864 return -EFAULT;
865 }
866
867 inode = page->mapping->host;
868 cifs_sb = CIFS_SB(inode->i_sb);
869 pTcon = cifs_sb->tcon;
870
871 offset += (loff_t)from;
872 write_data = kmap(page);
873 write_data += from;
874
875 if((to > PAGE_CACHE_SIZE) || (from > to)) {
876 kunmap(page);
877 return -EIO;
878 }
879
880 /* racing with truncate? */
881 if(offset > mapping->host->i_size) {
882 kunmap(page);
883 return 0; /* don't care */
884 }
885
886 /* check to make sure that we are not extending the file */
887 if(mapping->host->i_size - offset < (loff_t)to)
888 to = (unsigned)(mapping->host->i_size - offset);
889
890
891 cifsInode = CIFS_I(mapping->host);
892 read_lock(&GlobalSMBSeslock);
893 /* BB we should start at the end */
894 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
895 open_file = list_entry(tmp,struct cifsFileInfo, flist);
896 if(open_file->closePend)
897 continue;
898 /* We check if file is open for writing first */
899 if((open_file->pfile) &&
900 ((open_file->pfile->f_flags & O_RDWR) ||
901 (open_file->pfile->f_flags & O_WRONLY))) {
902 read_unlock(&GlobalSMBSeslock);
903 bytes_written = cifs_write(open_file->pfile, write_data,
904 to-from, &offset);
905 read_lock(&GlobalSMBSeslock);
906 /* Does mm or vfs already set times? */
907 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
908 if ((bytes_written > 0) && (offset)) {
909 rc = 0;
910 } else if(bytes_written < 0) {
911 if(rc == -EBADF) {
912 /* have seen a case in which
913 kernel seemed to have closed/freed a file
914 even with writes active so we might as well
915 see if there are other file structs to try
916 for the same inode before giving up */
917 continue;
918 } else
919 rc = bytes_written;
920 }
921 break; /* now that we found a valid file handle
922 and tried to write to it we are done, no
923 sense continuing to loop looking for another */
924 }
925 if(tmp->next == NULL) {
926 cFYI(1,("File instance %p removed",tmp));
927 break;
928 }
929 }
930 read_unlock(&GlobalSMBSeslock);
931 if(open_file == NULL) {
932 cFYI(1,("No writeable filehandles for inode"));
933 rc = -EIO;
934 }
935
936 kunmap(page);
937 return rc;
938 }
939
940 #if 0
941 static int
942 cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
943 {
944 int rc = -EFAULT;
945 int xid;
946
947 xid = GetXid();
948 /* call 16K write then Setpageuptodate */
949 FreeXid(xid);
950 return rc;
951 }
952 #endif
953
954 static int
955 cifs_writepage(struct page* page, struct writeback_control *wbc)
956 {
957 int rc = -EFAULT;
958 int xid;
959
960 xid = GetXid();
961 /* BB add check for wbc flags */
962 page_cache_get(page);
963 if (!PageUptodate(page)) {
964 cFYI(1,("ppw - page not up to date"));
965 }
966
967 rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
968 SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
969 unlock_page(page);
970 page_cache_release(page);
971 FreeXid(xid);
972 return rc;
973 }
974
975 static int
976 cifs_commit_write(struct file *file, struct page *page, unsigned offset,
977 unsigned to)
978 {
979 int xid;
980 int rc = 0;
981 struct inode *inode = page->mapping->host;
982 loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
983 char * page_data;
984
985 xid = GetXid();
986 cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
987 if (position > inode->i_size){
988 i_size_write(inode, position);
989 /*if (file->private_data == NULL) {
990 rc = -EBADF;
991 } else {
992 open_file = (struct cifsFileInfo *)file->private_data;
993 cifs_sb = CIFS_SB(inode->i_sb);
994 rc = -EAGAIN;
995 while(rc == -EAGAIN) {
996 if((open_file->invalidHandle) &&
997 (!open_file->closePend)) {
998 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
999 if(rc != 0)
1000 break;
1001 }
1002 if(!open_file->closePend) {
1003 rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
1004 position, open_file->netfid,
1005 open_file->pid,FALSE);
1006 } else {
1007 rc = -EBADF;
1008 break;
1009 }
1010 }
1011 cFYI(1,(" SetEOF (commit write) rc = %d",rc));
1012 }*/
1013 }
1014 if (!PageUptodate(page)) {
1015 position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
1016 /* can not rely on (or let) writepage write this data */
1017 if(to < offset) {
1018 cFYI(1,("Illegal offsets, can not copy from %d to %d",
1019 offset,to));
1020 FreeXid(xid);
1021 return rc;
1022 }
1023 /* this is probably better than directly calling
1024 partialpage_write since in this function
1025 the file handle is known which we might as well
1026 leverage */
1027 /* BB check if anything else missing out of ppw */
1028 /* such as updating last write time */
1029 page_data = kmap(page);
1030 rc = cifs_write(file, page_data+offset,to-offset,
1031 &position);
1032 if(rc > 0)
1033 rc = 0;
1034 /* else if rc < 0 should we set writebehind rc? */
1035 kunmap(page);
1036 } else {
1037 set_page_dirty(page);
1038 }
1039
1040 FreeXid(xid);
1041 return rc;
1042 }
1043
1044 int
1045 cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1046 {
1047 int xid;
1048 int rc = 0;
1049 struct inode * inode = file->f_dentry->d_inode;
1050
1051 xid = GetXid();
1052
1053 cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
1054 dentry->d_name.name, datasync));
1055
1056 rc = filemap_fdatawrite(inode->i_mapping);
1057 if(rc == 0)
1058 CIFS_I(inode)->write_behind_rc = 0;
1059 FreeXid(xid);
1060 return rc;
1061 }
1062
1063 /* static int
1064 cifs_sync_page(struct page *page)
1065 {
1066 struct address_space *mapping;
1067 struct inode *inode;
1068 unsigned long index = page->index;
1069 unsigned int rpages = 0;
1070 int rc = 0;
1071
1072 cFYI(1,("sync page %p",page));
1073 mapping = page->mapping;
1074 if (!mapping)
1075 return 0;
1076 inode = mapping->host;
1077 if (!inode)
1078 return 0;*/
1079
1080 /* fill in rpages then
1081 result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
1082
1083 /* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
1084
1085 if (rc < 0)
1086 return rc;
1087 return 0;
1088 } */
1089
1090 /*
1091 * As file closes, flush all cached write data for this inode checking
1092 * for write behind errors.
1093 *
1094 */
1095 int cifs_flush(struct file *file)
1096 {
1097 struct inode * inode = file->f_dentry->d_inode;
1098 int rc = 0;
1099
1100 /* Rather than do the steps manually: */
1101 /* lock the inode for writing */
1102 /* loop through pages looking for write behind data (dirty pages) */
1103 /* coalesce into contiguous 16K (or smaller) chunks to write to server */
1104 /* send to server (prefer in parallel) */
1105 /* deal with writebehind errors */
1106 /* unlock inode for writing */
1107 /* filemapfdatawrite appears easier for the time being */
1108
1109 rc = filemap_fdatawrite(inode->i_mapping);
1110 if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
1111 CIFS_I(inode)->write_behind_rc = 0;
1112
1113 cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
1114
1115 return rc;
1116 }
1117
1118
1119 ssize_t
1120 cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
1121 loff_t * poffset)
1122 {
1123 int rc = -EACCES;
1124 unsigned int bytes_read = 0;
1125 unsigned int total_read = 0;
1126 unsigned int current_read_size;
1127 struct cifs_sb_info *cifs_sb;
1128 struct cifsTconInfo *pTcon;
1129 int xid;
1130 struct cifsFileInfo * open_file;
1131 char * smb_read_data;
1132 char __user * current_offset;
1133 struct smb_com_read_rsp * pSMBr;
1134
1135 xid = GetXid();
1136 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1137 pTcon = cifs_sb->tcon;
1138
1139 if (file->private_data == NULL) {
1140 FreeXid(xid);
1141 return -EBADF;
1142 }
1143 open_file = (struct cifsFileInfo *)file->private_data;
1144
1145 if((file->f_flags & O_ACCMODE) == O_WRONLY) {
1146 cFYI(1,("attempting read on write only file instance"));
1147 }
1148
1149 for (total_read = 0,current_offset=read_data; read_size > total_read;
1150 total_read += bytes_read,current_offset+=bytes_read) {
1151 current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
1152 rc = -EAGAIN;
1153 smb_read_data = NULL;
1154 while(rc == -EAGAIN) {
1155 if ((open_file->invalidHandle) && (!open_file->closePend)) {
1156 rc = cifs_reopen_file(file->f_dentry->d_inode,
1157 file,TRUE);
1158 if(rc != 0)
1159 break;
1160 }
1161
1162 rc = CIFSSMBRead(xid, pTcon,
1163 open_file->netfid,
1164 current_read_size, *poffset,
1165 &bytes_read, &smb_read_data);
1166
1167 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1168 copy_to_user(current_offset,smb_read_data + 4/* RFC1001 hdr*/
1169 + le16_to_cpu(pSMBr->DataOffset), bytes_read);
1170 if(smb_read_data) {
1171 cifs_buf_release(smb_read_data);
1172 smb_read_data = NULL;
1173 }
1174 }
1175 if (rc || (bytes_read == 0)) {
1176 if (total_read) {
1177 break;
1178 } else {
1179 FreeXid(xid);
1180 return rc;
1181 }
1182 } else {
1183 #ifdef CONFIG_CIFS_STATS
1184 atomic_inc(&pTcon->num_reads);
1185 spin_lock(&pTcon->stat_lock);
1186 pTcon->bytes_read += total_read;
1187 spin_unlock(&pTcon->stat_lock);
1188 #endif
1189 *poffset += bytes_read;
1190 }
1191 }
1192 FreeXid(xid);
1193 return total_read;
1194 }
1195
1196 static ssize_t
1197 cifs_read(struct file * file, char *read_data, size_t read_size,
1198 loff_t * poffset)
1199 {
1200 int rc = -EACCES;
1201 unsigned int bytes_read = 0;
1202 unsigned int total_read;
1203 unsigned int current_read_size;
1204 struct cifs_sb_info *cifs_sb;
1205 struct cifsTconInfo *pTcon;
1206 int xid;
1207 char * current_offset;
1208 struct cifsFileInfo * open_file;
1209
1210 xid = GetXid();
1211 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1212 pTcon = cifs_sb->tcon;
1213
1214 if (file->private_data == NULL) {
1215 FreeXid(xid);
1216 return -EBADF;
1217 }
1218 open_file = (struct cifsFileInfo *)file->private_data;
1219
1220 if((file->f_flags & O_ACCMODE) == O_WRONLY) {
1221 cFYI(1,("attempting read on write only file instance"));
1222 }
1223
1224 for (total_read = 0,current_offset=read_data; read_size > total_read;
1225 total_read += bytes_read,current_offset+=bytes_read) {
1226 current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
1227 rc = -EAGAIN;
1228 while(rc == -EAGAIN) {
1229 if ((open_file->invalidHandle) && (!open_file->closePend)) {
1230 rc = cifs_reopen_file(file->f_dentry->d_inode,
1231 file,TRUE);
1232 if(rc != 0)
1233 break;
1234 }
1235
1236 rc = CIFSSMBRead(xid, pTcon,
1237 open_file->netfid,
1238 current_read_size, *poffset,
1239 &bytes_read, ¤t_offset);
1240 }
1241 if (rc || (bytes_read == 0)) {
1242 if (total_read) {
1243 break;
1244 } else {
1245 FreeXid(xid);
1246 return rc;
1247 }
1248 } else {
1249 #ifdef CONFIG_CIFS_STATS
1250 atomic_inc(&pTcon->num_reads);
1251 spin_lock(&pTcon->stat_lock);
1252 pTcon->bytes_read += total_read;
1253 spin_unlock(&pTcon->stat_lock);
1254 #endif
1255 *poffset += bytes_read;
1256 }
1257 }
1258 FreeXid(xid);
1259 return total_read;
1260 }
1261
1262 int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
1263 {
1264 struct dentry * dentry = file->f_dentry;
1265 int rc, xid;
1266
1267 #ifdef CIFS_EXPERIMENTAL /* BB fixme reenable when cifs_read_wrapper fixed */
1268 if(dentry->d_sb) {
1269 struct cifs_sb_info *cifs_sb;
1270 cifs_sb = CIFS_SB(sb);
1271 if(cifs_sb != NULL) {
1272 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
1273 return -ENODEV
1274 }
1275 }
1276 #endif /* CIFS_EXPERIMENTAL */
1277
1278 xid = GetXid();
1279 rc = cifs_revalidate(dentry);
1280 if (rc) {
1281 cFYI(1,("Validation prior to mmap failed, error=%d", rc));
1282 FreeXid(xid);
1283 return rc;
1284 }
1285 rc = generic_file_mmap(file, vma);
1286 FreeXid(xid);
1287 return rc;
1288 }
1289
1290 static void cifs_copy_cache_pages(struct address_space *mapping,
1291 struct list_head *pages, int bytes_read,
1292 char *data,struct pagevec * plru_pvec)
1293 {
1294 struct page *page;
1295 char * target;
1296
1297 while (bytes_read > 0) {
1298 if(list_empty(pages))
1299 break;
1300
1301 page = list_entry(pages->prev, struct page, lru);
1302 list_del(&page->lru);
1303
1304 if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
1305 page_cache_release(page);
1306 cFYI(1,("Add page cache failed"));
1307 continue;
1308 }
1309
1310 target = kmap_atomic(page,KM_USER0);
1311
1312 if(PAGE_CACHE_SIZE > bytes_read) {
1313 memcpy(target,data,bytes_read);
1314 /* zero the tail end of this partial page */
1315 memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
1316 bytes_read = 0;
1317 } else {
1318 memcpy(target,data,PAGE_CACHE_SIZE);
1319 bytes_read -= PAGE_CACHE_SIZE;
1320 }
1321 kunmap_atomic(target,KM_USER0);
1322
1323 flush_dcache_page(page);
1324 SetPageUptodate(page);
1325 unlock_page(page);
1326 if (!pagevec_add(plru_pvec, page))
1327 __pagevec_lru_add(plru_pvec);
1328 data += PAGE_CACHE_SIZE;
1329 }
1330 return;
1331 }
1332
1333
1334 static int
1335 cifs_readpages(struct file *file, struct address_space *mapping,
1336 struct list_head *page_list, unsigned num_pages)
1337 {
1338 int rc = -EACCES;
1339 int xid;
1340 loff_t offset;
1341 struct page * page;
1342 struct cifs_sb_info *cifs_sb;
1343 struct cifsTconInfo *pTcon;
1344 int bytes_read = 0;
1345 unsigned int read_size,i;
1346 char * smb_read_data = NULL;
1347 struct smb_com_read_rsp * pSMBr;
1348 struct pagevec lru_pvec;
1349 struct cifsFileInfo * open_file;
1350
1351 xid = GetXid();
1352 if (file->private_data == NULL) {
1353 FreeXid(xid);
1354 return -EBADF;
1355 }
1356 open_file = (struct cifsFileInfo *)file->private_data;
1357 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1358 pTcon = cifs_sb->tcon;
1359
1360 pagevec_init(&lru_pvec, 0);
1361
1362 for(i = 0;i<num_pages;) {
1363 unsigned contig_pages;
1364 struct page * tmp_page;
1365 unsigned long expected_index;
1366
1367 if(list_empty(page_list)) {
1368 break;
1369 }
1370 page = list_entry(page_list->prev, struct page, lru);
1371 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1372
1373 /* count adjacent pages that we will read into */
1374 contig_pages = 0;
1375 expected_index = list_entry(page_list->prev,struct page,lru)->index;
1376 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1377 if(tmp_page->index == expected_index) {
1378 contig_pages++;
1379 expected_index++;
1380 } else {
1381 break;
1382 }
1383 }
1384 if(contig_pages + i > num_pages) {
1385 contig_pages = num_pages - i;
1386 }
1387
1388 /* for reads over a certain size could initiate async read ahead */
1389
1390 read_size = contig_pages * PAGE_CACHE_SIZE;
1391 /* Read size needs to be in multiples of one page */
1392 read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
1393
1394 rc = -EAGAIN;
1395 while(rc == -EAGAIN) {
1396 if ((open_file->invalidHandle) && (!open_file->closePend)) {
1397 rc = cifs_reopen_file(file->f_dentry->d_inode,
1398 file, TRUE);
1399 if(rc != 0)
1400 break;
1401 }
1402
1403 rc = CIFSSMBRead(xid, pTcon,
1404 open_file->netfid,
1405 read_size, offset,
1406 &bytes_read, &smb_read_data);
1407 /* BB need to check return code here */
1408 if(rc== -EAGAIN) {
1409 if(smb_read_data) {
1410 cifs_buf_release(smb_read_data);
1411 smb_read_data = NULL;
1412 }
1413 }
1414 }
1415 if ((rc < 0) || (smb_read_data == NULL)) {
1416 cFYI(1,("Read error in readpages: %d",rc));
1417 /* clean up remaing pages off list */
1418 while (!list_empty(page_list) && (i < num_pages)) {
1419 page = list_entry(page_list->prev, struct page, lru);
1420 list_del(&page->lru);
1421 page_cache_release(page);
1422 }
1423 break;
1424 } else if (bytes_read > 0) {
1425 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1426 cifs_copy_cache_pages(mapping, page_list, bytes_read,
1427 smb_read_data + 4 /* RFC1001 hdr */ +
1428 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1429
1430 i += bytes_read >> PAGE_CACHE_SHIFT;
1431 #ifdef CONFIG_CIFS_STATS
1432 atomic_inc(&pTcon->num_reads);
1433 spin_lock(&pTcon->stat_lock);
1434 pTcon->bytes_read += bytes_read;
1435 spin_unlock(&pTcon->stat_lock);
1436 #endif
1437 if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1438 i++; /* account for partial page */
1439
1440 /* server copy of file can have smaller size than client */
1441 /* BB do we need to verify this common case ? this case is ok -
1442 if we are at server EOF we will hit it on next read */
1443
1444 /* while(!list_empty(page_list) && (i < num_pages)) {
1445 page = list_entry(page_list->prev,struct page, list);
1446 list_del(&page->list);
1447 page_cache_release(page);
1448 }
1449 break; */
1450 }
1451 } else {
1452 cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset));
1453 /* BB turn off caching and do new lookup on file size at server? */
1454 while (!list_empty(page_list) && (i < num_pages)) {
1455 page = list_entry(page_list->prev, struct page, lru);
1456 list_del(&page->lru);
1457 page_cache_release(page); /* BB removeme - replace with zero of page? */
1458 }
1459 break;
1460 }
1461 if(smb_read_data) {
1462 cifs_buf_release(smb_read_data);
1463 smb_read_data = NULL;
1464 }
1465 bytes_read = 0;
1466 }
1467
1468 pagevec_lru_add(&lru_pvec);
1469
1470 /* need to free smb_read_data buf before exit */
1471 if(smb_read_data) {
1472 cifs_buf_release(smb_read_data);
1473 smb_read_data = NULL;
1474 }
1475
1476 FreeXid(xid);
1477 return rc;
1478 }
1479
1480 static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset)
1481 {
1482 char * read_data;
1483 int rc;
1484
1485 page_cache_get(page);
1486 read_data = kmap(page);
1487 /* for reads over a certain size could initiate async read ahead */
1488
1489 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1490
1491 if (rc < 0)
1492 goto io_error;
1493 else {
1494 cFYI(1,("Bytes read %d ",rc));
1495 }
1496
1497 file->f_dentry->d_inode->i_atime =
1498 current_fs_time(file->f_dentry->d_inode->i_sb);
1499
1500 if(PAGE_CACHE_SIZE > rc) {
1501 memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
1502 }
1503 flush_dcache_page(page);
1504 SetPageUptodate(page);
1505 rc = 0;
1506
1507 io_error:
1508 kunmap(page);
1509 page_cache_release(page);
1510 return rc;
1511 }
1512
1513 static int
1514 cifs_readpage(struct file *file, struct page *page)
1515 {
1516 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1517 int rc = -EACCES;
1518 int xid;
1519
1520 xid = GetXid();
1521
1522 if (file->private_data == NULL) {
1523 FreeXid(xid);
1524 return -EBADF;
1525 }
1526
1527 cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
1528
1529 rc = cifs_readpage_worker(file,page,&offset);
1530
1531 unlock_page(page);
1532
1533 FreeXid(xid);
1534 return rc;
1535 }
1536
1537 /* We do not want to update the file size from server for inodes
1538 open for write - to avoid races with writepage extending
1539 the file - in the future we could consider allowing
1540 refreshing the inode only on increases in the file size
1541 but this is tricky to do without racing with writebehind
1542 page caching in the current Linux kernel design */
1543
1544 int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
1545 {
1546 struct list_head *tmp;
1547 struct list_head *tmp1;
1548 struct cifsFileInfo *open_file = NULL;
1549 int rc = TRUE;
1550
1551 if(cifsInode == NULL)
1552 return rc;
1553
1554 read_lock(&GlobalSMBSeslock);
1555 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
1556 open_file = list_entry(tmp,struct cifsFileInfo, flist);
1557 if(open_file == NULL)
1558 break;
1559 if(open_file->closePend)
1560 continue;
1561 /* We check if file is open for writing,
1562 BB we could supplement this with a check to see if file size
1563 changes have been flushed to server - ie inode metadata dirty */
1564 if((open_file->pfile) &&
1565 ((open_file->pfile->f_flags & O_RDWR) ||
1566 (open_file->pfile->f_flags & O_WRONLY))) {
1567 rc = FALSE;
1568 break;
1569 }
1570 if(tmp->next == NULL) {
1571 cFYI(1,("File instance %p removed",tmp));
1572 break;
1573 }
1574 }
1575 read_unlock(&GlobalSMBSeslock);
1576 return rc;
1577 }
1578
1579
1580 void
1581 fill_in_inode(struct inode *tmp_inode,
1582 FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
1583 {
1584 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
1585 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
1586 __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
1587 __u64 allocation_size = le64_to_cpu(pfindData->AllocationSize);
1588 __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
1589
1590 cifsInfo->cifsAttrs = attr;
1591 cifsInfo->time = jiffies;
1592
1593 /* Linux can not store file creation time unfortunately so ignore it */
1594 tmp_inode->i_atime =
1595 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
1596 tmp_inode->i_mtime =
1597 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
1598 tmp_inode->i_ctime =
1599 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
1600 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
1601 /* 2767 perms - indicate mandatory locking */
1602 /* BB fill in uid and gid here? with help from winbind?
1603 or retrieve from NTFS stream extended attribute */
1604 if(atomic_read(&cifsInfo->inUse) == 0) {
1605 tmp_inode->i_uid = cifs_sb->mnt_uid;
1606 tmp_inode->i_gid = cifs_sb->mnt_gid;
1607 /* set default mode. will override for dirs below */
1608 tmp_inode->i_mode = cifs_sb->mnt_file_mode;
1609 }
1610
1611 cFYI(0,
1612 ("CIFS FFIRST: Attributes came in as 0x%x",
1613 attr));
1614 if (attr & ATTR_DIRECTORY) {
1615 *pobject_type = DT_DIR;
1616 /* override default perms since we do not lock dirs */
1617 if(atomic_read(&cifsInfo->inUse) == 0) {
1618 tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
1619 }
1620 tmp_inode->i_mode |= S_IFDIR;
1621 /* we no longer mark these because we could not follow them */
1622 /* } else if (attr & ATTR_REPARSE) {
1623 *pobject_type = DT_LNK;
1624 tmp_inode->i_mode |= S_IFLNK;*/
1625 } else {
1626 *pobject_type = DT_REG;
1627 tmp_inode->i_mode |= S_IFREG;
1628 if(attr & ATTR_READONLY)
1629 tmp_inode->i_mode &= ~(S_IWUGO);
1630 }/* could add code here - to validate if device or weird share type? */
1631
1632 /* can not fill in nlink here as in qpathinfo version and Unx search */
1633 if(atomic_read(&cifsInfo->inUse) == 0) {
1634 atomic_set(&cifsInfo->inUse,1);
1635 }
1636
1637 if(is_size_safe_to_change(cifsInfo)) {
1638 /* can not safely change the file size here if the
1639 client is writing to it due to potential races */
1640 i_size_write(tmp_inode,end_of_file);
1641
1642 /* 512 bytes (2**9) is the fake blocksize that must be used */
1643 /* for this calculation, even though the reported blocksize is larger */
1644 tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
1645 }
1646
1647 if (allocation_size < end_of_file)
1648 cFYI(1, ("Possible sparse file: allocation size less than end of file "));
1649 cFYI(1,
1650 ("File Size %ld and blocks %ld and blocksize %ld",
1651 (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
1652 tmp_inode->i_blksize));
1653 if (S_ISREG(tmp_inode->i_mode)) {
1654 cFYI(1, (" File inode "));
1655 tmp_inode->i_op = &cifs_file_inode_ops;
1656 tmp_inode->i_fop = &cifs_file_ops;
1657 tmp_inode->i_data.a_ops = &cifs_addr_ops;
1658 } else if (S_ISDIR(tmp_inode->i_mode)) {
1659 cFYI(1, (" Directory inode"));
1660 tmp_inode->i_op = &cifs_dir_inode_ops;
1661 tmp_inode->i_fop = &cifs_dir_ops;
1662 } else if (S_ISLNK(tmp_inode->i_mode)) {
1663 cFYI(1, (" Symbolic Link inode "));
1664 tmp_inode->i_op = &cifs_symlink_inode_ops;
1665 } else {
1666 cFYI(1, (" Init special inode "));
1667 init_special_inode(tmp_inode, tmp_inode->i_mode,
1668 tmp_inode->i_rdev);
1669 }
1670 }
1671
1672 void
1673 unix_fill_in_inode(struct inode *tmp_inode,
1674 FILE_UNIX_INFO * pfindData, int *pobject_type)
1675 {
1676 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
1677 __u32 type = le32_to_cpu(pfindData->Type);
1678 __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);
1679 __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
1680 cifsInfo->time = jiffies;
1681 atomic_inc(&cifsInfo->inUse);
1682
1683 tmp_inode->i_atime =
1684 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
1685 tmp_inode->i_mtime =
1686 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
1687 tmp_inode->i_ctime =
1688 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
1689
1690 tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
1691 if (type == UNIX_FILE) {
1692 *pobject_type = DT_REG;
1693 tmp_inode->i_mode |= S_IFREG;
1694 } else if (type == UNIX_SYMLINK) {
1695 *pobject_type = DT_LNK;
1696 tmp_inode->i_mode |= S_IFLNK;
1697 } else if (type == UNIX_DIR) {
1698 *pobject_type = DT_DIR;
1699 tmp_inode->i_mode |= S_IFDIR;
1700 } else if (type == UNIX_CHARDEV) {
1701 *pobject_type = DT_CHR;
1702 tmp_inode->i_mode |= S_IFCHR;
1703 tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
1704 le64_to_cpu(pfindData->DevMinor) & MINORMASK);
1705 } else if (type == UNIX_BLOCKDEV) {
1706 *pobject_type = DT_BLK;
1707 tmp_inode->i_mode |= S_IFBLK;
1708 tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
1709 le64_to_cpu(pfindData->DevMinor) & MINORMASK);
1710 } else if (type == UNIX_FIFO) {
1711 *pobject_type = DT_FIFO;
1712 tmp_inode->i_mode |= S_IFIFO;
1713 } else if (type == UNIX_SOCKET) {
1714 *pobject_type = DT_SOCK;
1715 tmp_inode->i_mode |= S_IFSOCK;
1716 }
1717
1718 tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
1719 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
1720 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
1721
1722
1723 if(is_size_safe_to_change(cifsInfo)) {
1724 /* can not safely change the file size here if the
1725 client is writing to it due to potential races */
1726 i_size_write(tmp_inode,end_of_file);
1727
1728 /* 512 bytes (2**9) is the fake blocksize that must be used */
1729 /* for this calculation, not the real blocksize */
1730 tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
1731 }
1732
1733 if (S_ISREG(tmp_inode->i_mode)) {
1734 cFYI(1, ("File inode"));
1735 tmp_inode->i_op = &cifs_file_inode_ops;
1736 tmp_inode->i_fop = &cifs_file_ops;
1737 tmp_inode->i_data.a_ops = &cifs_addr_ops;
1738 } else if (S_ISDIR(tmp_inode->i_mode)) {
1739 cFYI(1, ("Directory inode"));
1740 tmp_inode->i_op = &cifs_dir_inode_ops;
1741 tmp_inode->i_fop = &cifs_dir_ops;
1742 } else if (S_ISLNK(tmp_inode->i_mode)) {
1743 cFYI(1, ("Symbolic Link inode"));
1744 tmp_inode->i_op = &cifs_symlink_inode_ops;
1745 /* tmp_inode->i_fop = *//* do not need to set to anything */
1746 } else {
1747 cFYI(1, ("Special inode"));
1748 init_special_inode(tmp_inode, tmp_inode->i_mode,
1749 tmp_inode->i_rdev);
1750 }
1751 }
1752
1753 /* Returns one if new inode created (which therefore needs to be hashed) */
1754 /* Might check in the future if inode number changed so we can rehash inode */
1755 int
1756 construct_dentry(struct qstr *qstring, struct file *file,
1757 struct inode **ptmp_inode, struct dentry **pnew_dentry)
1758 {
1759 struct dentry *tmp_dentry;
1760 struct cifs_sb_info *cifs_sb;
1761 struct cifsTconInfo *pTcon;
1762 int rc = 0;
1763
1764 cFYI(1, ("For %s ", qstring->name));
1765 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1766 pTcon = cifs_sb->tcon;
1767
1768 qstring->hash = full_name_hash(qstring->name, qstring->len);
1769 tmp_dentry = d_lookup(file->f_dentry, qstring);
1770 if (tmp_dentry) {
1771 cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
1772 *ptmp_inode = tmp_dentry->d_inode;
1773 /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
1774 if(*ptmp_inode == NULL) {
1775 *ptmp_inode = new_inode(file->f_dentry->d_sb);
1776 if(*ptmp_inode == NULL)
1777 return rc;
1778 rc = 1;
1779 d_instantiate(tmp_dentry, *ptmp_inode);
1780 }
1781 } else {
1782 tmp_dentry = d_alloc(file->f_dentry, qstring);
1783 if(tmp_dentry == NULL) {
1784 cERROR(1,("Failed allocating dentry"));
1785 *ptmp_inode = NULL;
1786 return rc;
1787 }
1788
1789 *ptmp_inode = new_inode(file->f_dentry->d_sb);
1790 tmp_dentry->d_op = &cifs_dentry_ops;
1791 if(*ptmp_inode == NULL)
1792 return rc;
1793 rc = 1;
1794 d_instantiate(tmp_dentry, *ptmp_inode);
1795 d_rehash(tmp_dentry);
1796 }
1797
1798 tmp_dentry->d_time = jiffies;
1799 *pnew_dentry = tmp_dentry;
1800 return rc;
1801 }
1802
1803 static void reset_resume_key(struct file * dir_file,
1804 unsigned char * filename,
1805 unsigned int len,int Unicode,struct nls_table * nls_tab) {
1806 struct cifsFileInfo *cifsFile;
1807
1808 cifsFile = (struct cifsFileInfo *)dir_file->private_data;
1809 if(cifsFile == NULL)
1810 return;
1811 if(cifsFile->search_resume_name) {
1812 kfree(cifsFile->search_resume_name);
1813 }
1814
1815 if(Unicode)
1816 len *= 2;
1817 cifsFile->resume_name_length = len;
1818
1819 cifsFile->search_resume_name =
1820 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1821
1822 if(cifsFile->search_resume_name == NULL) {
1823 cERROR(1,("failed new resume key allocate, length %d",
1824 cifsFile->resume_name_length));
1825 return;
1826 }
1827 if(Unicode)
1828 cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
1829 filename, len, nls_tab);
1830 else
1831 memcpy(cifsFile->search_resume_name, filename,
1832 cifsFile->resume_name_length);
1833 cFYI(1,("Reset resume key to: %s with len %d",filename,len));
1834 return;
1835 }
1836
1837
1838
1839 static int
1840 cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
1841 struct file *file, filldir_t filldir, void *direntry)
1842 {
1843 struct inode *tmp_inode;
1844 struct dentry *tmp_dentry;
1845 int object_type,rc;
1846
1847 pqstring->name = pfindData->FileName;
1848 /* pqstring->len is already set by caller */
1849
1850 rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
1851 if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
1852 return -ENOMEM;
1853 }
1854 fill_in_inode(tmp_inode, pfindData, &object_type);
1855 if(rc) {
1856 /* We have no reliable way to get inode numbers
1857 from servers w/o Unix extensions yet so we can not set
1858 i_ino from pfindData yet */
1859
1860 /* new inode created, let us hash it */
1861 insert_inode_hash(tmp_inode);
1862 } /* else if inode number changed do we rehash it? */
1863 rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
1864 tmp_inode->i_ino, object_type);
1865 if(rc) {
1866 /* due to readdir error we need to recalculate resume
1867 key so next readdir will restart on right entry */
1868 cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
1869 }
1870 dput(tmp_dentry);
1871 return rc;
1872 }
1873
1874 static int
1875 cifs_filldir_unix(struct qstr *pqstring,
1876 FILE_UNIX_INFO * pUnixFindData, struct file *file,
1877 filldir_t filldir, void *direntry)
1878 {
1879 struct inode *tmp_inode;
1880 struct dentry *tmp_dentry;
1881 int object_type, rc;
1882
1883 pqstring->name = pUnixFindData->FileName;
1884 pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
1885
1886 rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
1887 if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
1888 return -ENOMEM;
1889 }
1890 if(rc) {
1891 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
1892
1893 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
1894 tmp_inode->i_ino =
1895 (unsigned long)pUnixFindData->UniqueId;
1896 }
1897 insert_inode_hash(tmp_inode);
1898 } /* else if i_ino has changed should we rehash it? */
1899 unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
1900 rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
1901 file->f_pos, tmp_inode->i_ino, object_type);
1902 if(rc) {
1903 /* due to readdir error we need to recalculate resume
1904 key so next readdir will restart on right entry */
1905 cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
1906 }
1907 dput(tmp_dentry);
1908 return rc;
1909 }
1910
1911 int
1912 cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
1913 {
1914 int rc = 0;
1915 int xid;
1916 int Unicode = FALSE;
1917 int UnixSearch = FALSE;
1918 unsigned int bufsize, i;
1919 __u16 searchHandle;
1920 struct cifs_sb_info *cifs_sb;
1921 struct cifsTconInfo *pTcon;
1922 struct cifsFileInfo *cifsFile = NULL;
1923 char *full_path = NULL;
1924 char *data;
1925 struct qstr qstring;
1926 T2_FFIRST_RSP_PARMS findParms;
1927 T2_FNEXT_RSP_PARMS findNextParms;
1928 FILE_DIRECTORY_INFO *pfindData;
1929 FILE_DIRECTORY_INFO *lastFindData;
1930 FILE_UNIX_INFO *pfindDataUnix;
1931
1932
1933 /* BB removeme begin */
1934 if(!experimEnabled)
1935 return cifs_readdir2(file,direntry,filldir);
1936 /* BB removeme end */
1937
1938
1939 xid = GetXid();
1940
1941 if(file->f_dentry == NULL) {
1942 rc = -EIO;
1943 FreeXid(xid);
1944 return rc;
1945 }
1946 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1947 pTcon = cifs_sb->tcon;
1948 bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
1949 if(bufsize > CIFSMaxBufSize) {
1950 rc = -EIO;
1951 FreeXid(xid);
1952 return rc;
1953 }
1954 data = kmalloc(bufsize, GFP_KERNEL);
1955 pfindData = (FILE_DIRECTORY_INFO *) data;
1956 if(data == NULL) {
1957 rc = -ENOMEM;
1958 FreeXid(xid);
1959 return rc;
1960 }
1961 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
1962 full_path = build_wildcard_path_from_dentry(file->f_dentry);
1963 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
1964
1965 if(full_path == NULL) {
1966 kfree(data);
1967 FreeXid(xid);
1968 return -ENOMEM;
1969 }
1970 cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
1971
1972 switch ((int) file->f_pos) {
1973 case 0:
1974 if (filldir(direntry, ".", 1, file->f_pos,
1975 file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
1976 cERROR(1, ("Filldir for current dir failed "));
1977 break;
1978 }
1979 file->f_pos++;
1980 /* fallthrough */
1981 case 1:
1982 if (filldir(direntry, "..", 2, file->f_pos,
1983 file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
1984 cERROR(1, ("Filldir for parent dir failed "));
1985 break;
1986 }
1987 file->f_pos++;
1988 /* fallthrough */
1989 case 2:
1990 if (file->private_data != NULL) {
1991 cifsFile =
1992 (struct cifsFileInfo *) file->private_data;
1993 if (cifsFile->srch_inf.endOfSearch) {
1994 if(cifsFile->srch_inf.emptyDir) {
1995 cFYI(1, ("End of search, empty dir"));
1996 rc = 0;
1997 break;
1998 }
1999 } else {
2000 cifsFile->invalidHandle = TRUE;
2001 CIFSFindClose(xid, pTcon, cifsFile->netfid);
2002 }
2003 if(cifsFile->search_resume_name) {
2004 kfree(cifsFile->search_resume_name);
2005 cifsFile->search_resume_name = NULL;
2006 }
2007 }
2008 rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
2009 &findParms, cifs_sb->local_nls,
2010 &Unicode, &UnixSearch);
2011 cFYI(1, ("Count: %d End: %d ",
2012 le16_to_cpu(findParms.SearchCount),
2013 le16_to_cpu(findParms.EndofSearch)));
2014
2015 if (rc == 0) {
2016 __u16 count = le16_to_cpu(findParms.SearchCount);
2017 searchHandle = findParms.SearchHandle;
2018 if(file->private_data == NULL)
2019 file->private_data =
2020 kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
2021 if (file->private_data) {
2022 memset(file->private_data, 0,
2023 sizeof (struct cifsFileInfo));
2024 cifsFile =
2025 (struct cifsFileInfo *) file->private_data;
2026 cifsFile->netfid = searchHandle;
2027 cifsFile->invalidHandle = FALSE;
2028 init_MUTEX(&cifsFile->fh_sem);
2029 } else {
2030 rc = -ENOMEM;
2031 break;
2032 }
2033
2034 renew_parental_timestamps(file->f_dentry);
2035 lastFindData =
2036 (FILE_DIRECTORY_INFO *) ((char *) pfindData +
2037 le16_to_cpu(findParms.LastNameOffset));
2038 if((char *)lastFindData > (char *)pfindData + bufsize) {
2039 cFYI(1,("last search entry past end of packet"));
2040 rc = -EIO;
2041 break;
2042 }
2043 /* Offset of resume key same for levels 257 and 514 */
2044 cifsFile->srch_inf.resume_key = lastFindData->FileIndex;
2045 if(UnixSearch == FALSE) {
2046 cifsFile->resume_name_length =
2047 le32_to_cpu(lastFindData->FileNameLength);
2048 if(cifsFile->resume_name_length > bufsize - 64) {
2049 cFYI(1,("Illegal resume file name length %d",
2050 cifsFile->resume_name_length));
2051 rc = -ENOMEM;
2052 break;
2053 }
2054 cifsFile->search_resume_name =
2055 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
2056 cFYI(1,("Last file: %s with name %d bytes long",
2057 lastFindData->FileName,
2058 cifsFile->resume_name_length));
2059 if(cifsFile->search_resume_name == NULL) {
2060 rc = -ENOMEM;
2061 break;
2062 }
2063 memcpy(cifsFile->search_resume_name,
2064 lastFindData->FileName,
2065 cifsFile->resume_name_length);
2066 } else {
2067 pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
2068 if (Unicode == TRUE) {
2069 for(i=0;(pfindDataUnix->FileName[i]
2070 | pfindDataUnix->FileName[i+1]);
2071 i+=2) {
2072 if(i > bufsize-64)
2073 break;
2074 }
2075 cifsFile->resume_name_length = i + 2;
2076 } else {
2077 cifsFile->resume_name_length =
2078 strnlen(pfindDataUnix->FileName,
2079 bufsize-63);
2080 }
2081 if(cifsFile->resume_name_length > bufsize - 64) {
2082 cFYI(1,("Illegal resume file name length %d",
2083 cifsFile->resume_name_length));
2084 rc = -ENOMEM;
2085 break;
2086 }
2087 cifsFile->search_resume_name =
2088 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
2089 cFYI(1,("Last file: %s with name %d bytes long",
2090 pfindDataUnix->FileName,
2091 cifsFile->resume_name_length));
2092 if(cifsFile->search_resume_name == NULL) {
2093 rc = -ENOMEM;
2094 break;
2095 }
2096 memcpy(cifsFile->search_resume_name,
2097 pfindDataUnix->FileName,
2098 cifsFile->resume_name_length);
2099 }
2100 for (i = 2; i < count + 2; i++) {
2101 if (UnixSearch == FALSE) {
2102 __u32 len = le32_to_cpu(pfindData->FileNameLength);
2103 if (Unicode == TRUE)
2104 len =
2105 cifs_strfromUCS_le
2106 (pfindData->FileName,
2107 (wchar_t *)
2108 pfindData->FileName,
2109 len / 2,
2110 cifs_sb->local_nls);
2111 qstring.len = len;
2112 if (((len != 1)
2113 || (pfindData->FileName[0] != '.'))
2114 && ((len != 2)
2115 || (pfindData->
2116 FileName[0] != '.')
2117 || (pfindData->
2118 FileName[1] != '.'))) {
2119 if(cifs_filldir(&qstring,
2120 pfindData,
2121 file, filldir,
2122 direntry)) {
2123 /* do not end search if
2124 kernel not ready to take
2125 remaining entries yet */
2126 reset_resume_key(file, pfindData->FileName,qstring.len,
2127 Unicode, cifs_sb->local_nls);
2128 findParms.EndofSearch = 0;
2129 break;
2130 }
2131 file->f_pos++;
2132 }
2133 } else { /* UnixSearch */
2134 pfindDataUnix =
2135 (FILE_UNIX_INFO *) pfindData;
2136 if (Unicode == TRUE)
2137 qstring.len =
2138 cifs_strfromUCS_le
2139 (pfindDataUnix->FileName,
2140 (wchar_t *)
2141 pfindDataUnix->FileName,
2142 MAX_PATHCONF,
2143 cifs_sb->local_nls);
2144 else
2145 qstring.len =
2146 strnlen(pfindDataUnix->
2147 FileName,
2148 MAX_PATHCONF);
2149 if (((qstring.len != 1)
2150 || (pfindDataUnix->
2151 FileName[0] != '.'))
2152 && ((qstring.len != 2)
2153 || (pfindDataUnix->
2154 FileName[0] != '.')
2155 || (pfindDataUnix->
2156 FileName[1] != '.'))) {
2157 if(cifs_filldir_unix(&qstring,
2158 pfindDataUnix,
2159 file,
2160 filldir,
2161 direntry)) {
2162 /* do not end search if
2163 kernel not ready to take
2164 remaining entries yet */
2165 findParms.EndofSearch = 0;
2166 reset_resume_key(file, pfindDataUnix->FileName,
2167 qstring.len,Unicode,cifs_sb->local_nls);
2168 break;
2169 }
2170 file->f_pos++;
2171 }
2172 }
2173 /* works also for Unix ff struct since first field of both */
2174 pfindData =
2175 (FILE_DIRECTORY_INFO *) ((char *) pfindData
2176 + le32_to_cpu(pfindData->NextEntryOffset));
2177 /* BB also should check to make sure that pointer is not beyond the end of the SMB */
2178 /* if(pfindData > lastFindData) rc = -EIO; break; */
2179 } /* end for loop */
2180 if ((findParms.EndofSearch != 0) && cifsFile) {
2181 cifsFile->srch_inf.endOfSearch = TRUE;
2182 if(findParms.SearchCount == cpu_to_le16(2))
2183 cifsFile->srch_inf.emptyDir = TRUE;
2184 }
2185 } else {
2186 if (cifsFile)
2187 cifsFile->srch_inf.endOfSearch = TRUE;
2188 /* unless parent directory gone do not return error */
2189 rc = 0;
2190 }
2191 break;
2192 default:
2193 if (file->private_data == NULL) {
2194 rc = -EBADF;
2195 cFYI(1,
2196 ("Readdir on closed srch, pos = %lld",
2197 file->f_pos));
2198 } else {
2199 cifsFile = (struct cifsFileInfo *) file->private_data;
2200 if (cifsFile->srch_inf.endOfSearch) {
2201 rc = 0;
2202 cFYI(1, ("End of search "));
2203 break;
2204 }
2205 searchHandle = cifsFile->netfid;
2206 rc = CIFSFindNext(xid, pTcon, pfindData,
2207 &findNextParms, searchHandle,
2208 cifsFile->search_resume_name,
2209 cifsFile->resume_name_length,
2210 cifsFile->srch_inf.resume_key,
2211 &Unicode, &UnixSearch);
2212 cFYI(1,("Count: %d End: %d ",
2213 le16_to_cpu(findNextParms.SearchCount),
2214 le16_to_cpu(findNextParms.EndofSearch)));
2215 if ((rc == 0) && (findNextParms.SearchCount != 0)) {
2216 /* BB save off resume key, key name and name length */
2217 __u16 count = le16_to_cpu(findNextParms.SearchCount);
2218 lastFindData =
2219 (FILE_DIRECTORY_INFO *) ((char *) pfindData
2220 + le16_to_cpu(findNextParms.LastNameOffset));
2221 if((char *)lastFindData > (char *)pfindData + bufsize) {
2222 cFYI(1,("last search entry past end of packet"));
2223 rc = -EIO;
2224 break;
2225 }
2226 /* Offset of resume key same for levels 257 and 514 */
2227 cifsFile->srch_inf.resume_key = lastFindData->FileIndex;
2228
2229 if(UnixSearch == FALSE) {
2230 cifsFile->resume_name_length =
2231 le32_to_cpu(lastFindData->FileNameLength);
2232 if(cifsFile->resume_name_length > bufsize - 64) {
2233 cFYI(1,("Illegal resume file name length %d",
2234 cifsFile->resume_name_length));
2235 rc = -ENOMEM;
2236 break;
2237 }
2238 /* Free the memory allocated by previous findfirst
2239 or findnext call - we can not reuse the memory since
2240 the resume name may not be same string length */
2241 if(cifsFile->search_resume_name)
2242 kfree(cifsFile->search_resume_name);
2243 cifsFile->search_resume_name =
2244 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
2245 cFYI(1,("Last file: %s with name %d bytes long",
2246 lastFindData->FileName,
2247 cifsFile->resume_name_length));
2248 if(cifsFile->search_resume_name == NULL) {
2249 rc = -ENOMEM;
2250 break;
2251 }
2252
2253 memcpy(cifsFile->search_resume_name,
2254 lastFindData->FileName,
2255 cifsFile->resume_name_length);
2256 } else {
2257 pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
2258 if (Unicode == TRUE) {
2259 for(i=0;(pfindDataUnix->FileName[i]
2260 | pfindDataUnix->FileName[i+1]);
2261 i+=2) {
2262 if(i > bufsize-64)
2263 break;
2264 }
2265 cifsFile->resume_name_length = i + 2;
2266 } else {
2267 cifsFile->resume_name_length =
2268 strnlen(pfindDataUnix->
2269 FileName,
2270 MAX_PATHCONF);
2271 }
2272 if(cifsFile->resume_name_length > bufsize - 64) {
2273 cFYI(1,("Illegal resume file name length %d",
2274 cifsFile->resume_name_length));
2275 rc = -ENOMEM;
2276 break;
2277 }
2278 /* Free the memory allocated by previous findfirst
2279 or findnext call - we can not reuse the memory since
2280 the resume name may not be same string length */
2281 if(cifsFile->search_resume_name)
2282 kfree(cifsFile->search_resume_name);
2283 cifsFile->search_resume_name =
2284 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
2285 cFYI(1,("fnext last file: %s with name %d bytes long",
2286 pfindDataUnix->FileName,
2287 cifsFile->resume_name_length));
2288 if(cifsFile->search_resume_name == NULL) {
2289 rc = -ENOMEM;
2290 break;
2291 }
2292 memcpy(cifsFile->search_resume_name,
2293 pfindDataUnix->FileName,
2294 cifsFile->resume_name_length);
2295 }
2296
2297 for (i = 0; i < count; i++) {
2298 __u32 len = le32_to_cpu(pfindData->
2299 FileNameLength);
2300 if (UnixSearch == FALSE) {
2301 if (Unicode == TRUE)
2302 len =
2303 cifs_strfromUCS_le
2304 (pfindData->FileName,
2305 (wchar_t *)
2306 pfindData->FileName,
2307 len / 2,
2308 cifs_sb->local_nls);
2309 qstring.len = len;
2310 if (((len != 1)
2311 || (pfindData->FileName[0] != '.'))
2312 && ((len != 2)
2313 || (pfindData->FileName[0] != '.')
2314 || (pfindData->FileName[1] !=
2315 '.'))) {
2316 if(cifs_filldir
2317 (&qstring,
2318 pfindData,
2319 file, filldir,
2320 direntry)) {
2321 /* do not end search if
2322 kernel not ready to take
2323 remaining entries yet */
2324 findNextParms.EndofSearch = 0;
2325 reset_resume_key(file, pfindData->FileName,qstring.len,
2326 Unicode,cifs_sb->local_nls);
2327 break;
2328 }
2329 file->f_pos++;
2330 }
2331 } else { /* UnixSearch */
2332 pfindDataUnix =
2333 (FILE_UNIX_INFO *)
2334 pfindData;
2335 if (Unicode == TRUE)
2336 qstring.len =
2337 cifs_strfromUCS_le
2338 (pfindDataUnix->FileName,
2339 (wchar_t *)
2340 pfindDataUnix->FileName,
2341 MAX_PATHCONF,
2342 cifs_sb->local_nls);
2343 else
2344 qstring.len =
2345 strnlen
2346 (pfindDataUnix->
2347 FileName,
2348 MAX_PATHCONF);
2349 if (((qstring.len != 1)
2350 || (pfindDataUnix->
2351 FileName[0] != '.'))
2352 && ((qstring.len != 2)
2353 || (pfindDataUnix->
2354 FileName[0] != '.')
2355 || (pfindDataUnix->
2356 FileName[1] !=
2357 '.'))) {
2358 if(cifs_filldir_unix
2359 (&qstring,
2360 pfindDataUnix,
2361 file, filldir,
2362 direntry)) {
2363 /* do not end search if
2364 kernel not ready to take
2365 remaining entries yet */
2366 findNextParms.EndofSearch = 0;
2367 reset_resume_key(file, pfindDataUnix->FileName,qstring.len,
2368 Unicode,cifs_sb->local_nls);
2369 break;
2370 }
2371 file->f_pos++;
2372 }
2373 }
2374 pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData +
2375 le32_to_cpu(pfindData->NextEntryOffset));
2376 /* works also for Unix find struct since first field of both */
2377 /* BB also should check to ensure pointer not beyond end of SMB */
2378 } /* end for loop */
2379 if (findNextParms.EndofSearch != 0) {
2380 cifsFile->srch_inf.endOfSearch = TRUE;
2381 }
2382 } else {
2383 cifsFile->srch_inf.endOfSearch = TRUE;
2384 rc = 0; /* unless parent directory disappeared - do not
2385 return error here (eg Access Denied or no more files) */
2386 }
2387 }
2388 } /* end switch */
2389 if (data)
2390 kfree(data);
2391 if (full_path)
2392 kfree(full_path);
2393 FreeXid(xid);
2394
2395 return rc;
2396 }
2397 int cifs_prepare_write(struct file *file, struct page *page,
2398 unsigned from, unsigned to)
2399 {
2400 int rc = 0;
2401 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2402 cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
2403 if (!PageUptodate(page)) {
2404 /* if (to - from != PAGE_CACHE_SIZE) {
2405 void *kaddr = kmap_atomic(page, KM_USER0);
2406 memset(kaddr, 0, from);
2407 memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
2408 flush_dcache_page(page);
2409 kunmap_atomic(kaddr, KM_USER0);
2410 } */
2411 /* If we are writing a full page it will be up to date,
2412 no need to read from the server */
2413 if((to==PAGE_CACHE_SIZE) && (from == 0))
2414 SetPageUptodate(page);
2415
2416 /* might as well read a page, it is fast enough */
2417 if((file->f_flags & O_ACCMODE) != O_WRONLY) {
2418 rc = cifs_readpage_worker(file,page,&offset);
2419 } else {
2420 /* should we try using another
2421 file handle if there is one - how would we lock it
2422 to prevent close of that handle racing with this read? */
2423 /* In any case this will be written out by commit_write */
2424 }
2425 }
2426
2427 /* BB should we pass any errors back? e.g. if we do not have read access to the file */
2428 return 0;
2429 }
2430
2431
2432 struct address_space_operations cifs_addr_ops = {
2433 .readpage = cifs_readpage,
2434 .readpages = cifs_readpages,
2435 .writepage = cifs_writepage,
2436 .prepare_write = cifs_prepare_write,
2437 .commit_write = cifs_commit_write,
2438 .set_page_dirty = __set_page_dirty_nobuffers,
2439 /* .sync_page = cifs_sync_page, */
2440 /*.direct_IO = */
2441 };
2442
|
This page was automatically generated by the
LXR engine.
|