4 * vfs operations that deal with files
6 * Copyright (C) International Business Machines Corp., 2002,2003
7 * Author(s): Steve French (sfrench@us.ibm.com)
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.
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.
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
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>
33 #include "cifsproto.h"
34 #include "cifs_unicode.h"
35 #include "cifs_debug.h"
36 #include "cifs_fs_sb.h"
39 cifs_open(struct inode *inode, struct file *file)
43 struct cifs_sb_info *cifs_sb;
44 struct cifsTconInfo *pTcon;
45 struct cifsFileInfo *pCifsFile;
46 struct cifsInodeInfo *pCifsInode;
47 struct list_head * tmp;
48 char *full_path = NULL;
49 int desiredAccess = 0x20197;
52 FILE_ALL_INFO * buf = NULL;
56 cifs_sb = CIFS_SB(inode->i_sb);
57 pTcon = cifs_sb->tcon;
59 if (file->f_flags & O_CREAT) {
60 /* search inode for this file and fill in file->private_data = */
61 pCifsInode = CIFS_I(file->f_dentry->d_inode);
62 read_lock(&GlobalSMBSeslock);
63 list_for_each(tmp, &pCifsInode->openFileList) {
64 pCifsFile = list_entry(tmp,struct cifsFileInfo, flist);
65 if((pCifsFile->pfile == NULL)&& (pCifsFile->pid = current->pid)){
66 /* mode set in cifs_create */
67 pCifsFile->pfile = file; /* needed for writepage */
68 file->private_data = pCifsFile;
72 read_unlock(&GlobalSMBSeslock);
73 if(file->private_data != NULL) {
78 if(file->f_flags & O_EXCL)
79 cERROR(1,("could not find file instance for new file %p ",file));
83 full_path = build_path_from_dentry(file->f_dentry);
85 cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
86 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
87 desiredAccess = GENERIC_READ;
88 else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
89 desiredAccess = GENERIC_WRITE;
90 else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
91 /* GENERIC_ALL is too much permission to request */
92 /* can cause unnecessary access denied on create */
93 /* desiredAccess = GENERIC_ALL; */
94 desiredAccess = GENERIC_READ | GENERIC_WRITE;
97 /*********************************************************************
98 * open flag mapping table:
100 * POSIX Flag CIFS Disposition
101 * ---------- ----------------
102 * O_CREAT FILE_OPEN_IF
103 * O_CREAT | O_EXCL FILE_CREATE
104 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
105 * O_TRUNC FILE_OVERWRITE
106 * none of the above FILE_OPEN
108 * Note that there is not a direct match between disposition
109 * FILE_SUPERSEDE (ie create whether or not file exists although
110 * O_CREAT | O_TRUNC is similar but truncates the existing
111 * file rather than creating a new file as FILE_SUPERSEDE does
112 * (which uses the attributes / metadata passed in on open call)
114 *? O_SYNC is a reasonable match to CIFS writethrough flag
115 *? and the read write flags match reasonably. O_LARGEFILE
116 *? is irrelevant because largefile support is always used
117 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
118 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
119 *********************************************************************/
121 if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
122 disposition = FILE_CREATE;
123 else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
124 disposition = FILE_OVERWRITE_IF;
125 else if((file->f_flags & O_CREAT) == O_CREAT)
126 disposition = FILE_OPEN_IF;
128 disposition = FILE_OPEN;
135 /* BB pass O_SYNC flag through on file attributes .. BB */
137 /* Also refresh inode by passing in file_info buf returned by SMBOpen
138 and calling get_inode_info with returned buf (at least
139 helps non-Unix server case */
140 buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
147 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
148 CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
150 cFYI(1, ("cifs_open returned 0x%x ", rc));
151 cFYI(1, ("oplock: %d ", oplock));
153 if(file->private_data)
154 kfree(file->private_data);
156 kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
157 if (file->private_data) {
158 memset(file->private_data, 0, sizeof(struct cifsFileInfo));
159 pCifsFile = (struct cifsFileInfo *) file->private_data;
160 pCifsFile->netfid = netfid;
161 pCifsFile->pid = current->pid;
162 init_MUTEX(&pCifsFile->fh_sem);
163 pCifsFile->pfile = file; /* needed for writepage */
164 pCifsFile->pInode = inode;
165 pCifsFile->invalidHandle = FALSE;
166 pCifsFile->closePend = FALSE;
167 write_lock(&file->f_owner.lock);
168 write_lock(&GlobalSMBSeslock);
169 list_add(&pCifsFile->tlist,&pTcon->openFileList);
170 pCifsInode = CIFS_I(file->f_dentry->d_inode);
172 list_add(&pCifsFile->flist,&pCifsInode->openFileList);
173 write_unlock(&GlobalSMBSeslock);
174 write_unlock(&file->f_owner.lock);
175 if(pCifsInode->clientCanCacheRead) {
176 /* we have the inode open somewhere else
177 no need to discard cache data */
180 /* BB need same check in cifs_create too? */
182 /* if not oplocked, invalidate inode pages if mtime
183 or file size changed */
184 struct timespec temp;
185 temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
186 if(timespec_equal(&file->f_dentry->d_inode->i_mtime,&temp) &&
187 (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
188 cFYI(1,("inode unchanged on server"));
190 if(file->f_dentry->d_inode->i_mapping) {
191 /* BB no need to lock inode until after invalidate*/
192 /* since namei code should already have it locked?*/
193 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
194 filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
196 cFYI(1,("invalidating remote inode since open detected it changed"));
197 invalidate_remote_inode(file->f_dentry->d_inode);
201 if (pTcon->ses->capabilities & CAP_UNIX)
202 rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
203 full_path, inode->i_sb);
205 rc = cifs_get_inode_info(&file->f_dentry->d_inode,
206 full_path, buf, inode->i_sb);
208 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
209 pCifsInode->clientCanCacheAll = TRUE;
210 pCifsInode->clientCanCacheRead = TRUE;
211 cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
212 } else if((oplock & 0xF) == OPLOCK_READ)
213 pCifsInode->clientCanCacheRead = TRUE;
215 write_unlock(&GlobalSMBSeslock);
216 write_unlock(&file->f_owner.lock);
218 if(oplock & CIFS_CREATE_ACTION) {
219 /* time to set mode which we can not set earlier due
220 to problems creating new read-only files */
221 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
222 CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
227 else {/* BB implement via Windows security descriptors */
228 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
229 /* in the meantime could set r/o dos attribute when perms are eg:
244 /* Try to reaquire byte range locks that were released when session */
245 /* to server was lost */
246 static int cifs_relock_file(struct cifsFileInfo * cifsFile)
250 /* BB list all locks open on this file and relock */
255 static int cifs_reopen_file(struct inode *inode, struct file *file)
259 struct cifs_sb_info *cifs_sb;
260 struct cifsTconInfo *pTcon;
261 struct cifsFileInfo *pCifsFile;
262 struct cifsInodeInfo *pCifsInode;
263 char *full_path = NULL;
264 int desiredAccess = 0x20197;
265 int disposition = FILE_OPEN;
267 FILE_ALL_INFO * buf = NULL;
271 if (file->private_data) {
272 pCifsFile = (struct cifsFileInfo *) file->private_data;
277 down(&pCifsFile->fh_sem);
278 if(pCifsFile->invalidHandle == FALSE) {
279 up(&pCifsFile->fh_sem);
285 cifs_sb = CIFS_SB(inode->i_sb);
286 pTcon = cifs_sb->tcon;
288 full_path = build_path_from_dentry(file->f_dentry);
290 cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
291 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
292 desiredAccess = GENERIC_READ;
293 else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
294 desiredAccess = GENERIC_WRITE;
295 else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
296 /* GENERIC_ALL is too much permission to request */
297 /* can cause unnecessary access denied on create */
298 /* desiredAccess = GENERIC_ALL; */
299 desiredAccess = GENERIC_READ | GENERIC_WRITE;
307 /* BB pass O_SYNC flag through on file attributes .. BB */
309 /* Also refresh inode by passing in file_info buf returned by SMBOpen
310 and calling get_inode_info with returned buf (at least
311 helps non-Unix server case */
312 buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
314 up(&pCifsFile->fh_sem);
320 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
321 CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
323 up(&pCifsFile->fh_sem);
324 cFYI(1, ("cifs_open returned 0x%x ", rc));
325 cFYI(1, ("oplock: %d ", oplock));
327 pCifsFile->netfid = netfid;
328 pCifsFile->invalidHandle = FALSE;
329 up(&pCifsFile->fh_sem);
330 pCifsInode = CIFS_I(inode);
332 if (pTcon->ses->capabilities & CAP_UNIX)
333 rc = cifs_get_inode_info_unix(&inode,
334 full_path, inode->i_sb);
336 rc = cifs_get_inode_info(&inode,
337 full_path, buf, inode->i_sb);
339 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
340 pCifsInode->clientCanCacheAll = TRUE;
341 pCifsInode->clientCanCacheRead = TRUE;
342 cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
343 } else if((oplock & 0xF) == OPLOCK_READ) {
344 pCifsInode->clientCanCacheRead = TRUE;
345 pCifsInode->clientCanCacheAll = FALSE;
347 pCifsInode->clientCanCacheRead = FALSE;
348 pCifsInode->clientCanCacheAll = FALSE;
350 cifs_relock_file(pCifsFile);
363 cifs_close(struct inode *inode, struct file *file)
367 struct cifs_sb_info *cifs_sb;
368 struct cifsTconInfo *pTcon;
369 struct cifsFileInfo *pSMBFile =
370 (struct cifsFileInfo *) file->private_data;
374 cifs_sb = CIFS_SB(inode->i_sb);
375 pTcon = cifs_sb->tcon;
377 pSMBFile->closePend = TRUE;
378 write_lock(&file->f_owner.lock);
380 /* no sense reconnecting to close a file that is
382 if (pTcon->tidStatus != CifsNeedReconnect) {
383 write_unlock(&file->f_owner.lock);
384 rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
385 write_lock(&file->f_owner.lock);
388 list_del(&pSMBFile->flist);
389 list_del(&pSMBFile->tlist);
390 write_unlock(&file->f_owner.lock);
391 if(pSMBFile->search_resume_name)
392 kfree(pSMBFile->search_resume_name);
393 kfree(file->private_data);
394 file->private_data = NULL;
398 if(list_empty(&(CIFS_I(inode)->openFileList))) {
399 cFYI(1,("closing last open instance for inode %p",inode));
400 /* if the file is not open we do not know if we can cache
401 info on this inode, much less write behind and read ahead */
402 CIFS_I(inode)->clientCanCacheRead = FALSE;
403 CIFS_I(inode)->clientCanCacheAll = FALSE;
405 if((rc ==0) && CIFS_I(inode)->write_behind_rc)
406 rc = CIFS_I(inode)->write_behind_rc;
412 cifs_closedir(struct inode *inode, struct file *file)
416 struct cifsFileInfo *pSMBFileStruct =
417 (struct cifsFileInfo *) file->private_data;
419 cFYI(1, ("Closedir inode = 0x%p with ", inode));
423 if (pSMBFileStruct) {
424 cFYI(1, ("Freeing private data in close dir"));
425 kfree(file->private_data);
426 file->private_data = NULL;
433 cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
436 __u32 lockType = LOCKING_ANDX_LARGE_FILES;
440 int wait_flag = FALSE;
441 struct cifs_sb_info *cifs_sb;
442 struct cifsTconInfo *pTcon;
443 length = 1 + pfLock->fl_end - pfLock->fl_start;
450 ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
451 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
454 if (pfLock->fl_flags & FL_POSIX)
456 if (pfLock->fl_flags & FL_FLOCK)
458 if (pfLock->fl_flags & FL_SLEEP) {
459 cFYI(1, ("Blocking lock "));
462 if (pfLock->fl_flags & FL_ACCESS)
463 cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
464 if (pfLock->fl_flags & FL_LEASE)
465 cFYI(1, ("Lease on file - not implemented yet"));
466 if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
467 cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
469 if (pfLock->fl_type == F_WRLCK) {
470 cFYI(1, ("F_WRLCK "));
472 } else if (pfLock->fl_type == F_UNLCK) {
473 cFYI(1, ("F_UNLCK "));
475 } else if (pfLock->fl_type == F_RDLCK) {
476 cFYI(1, ("F_RDLCK "));
477 lockType |= LOCKING_ANDX_SHARED_LOCK;
479 } else if (pfLock->fl_type == F_EXLCK) {
480 cFYI(1, ("F_EXLCK "));
482 } else if (pfLock->fl_type == F_SHLCK) {
483 cFYI(1, ("F_SHLCK "));
484 lockType |= LOCKING_ANDX_SHARED_LOCK;
487 cFYI(1, ("Unknown type of lock "));
489 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
490 pTcon = cifs_sb->tcon;
492 if (file->private_data == NULL) {
498 rc = CIFSSMBLock(xid, pTcon,
499 ((struct cifsFileInfo *) file->
500 private_data)->netfid,
502 pfLock->fl_start, 0, 1, lockType,
505 rc = CIFSSMBLock(xid, pTcon,
506 ((struct cifsFileInfo *) file->
507 private_data)->netfid,
509 pfLock->fl_start, 1 /* numUnlock */ ,
510 0 /* numLock */ , lockType,
512 pfLock->fl_type = F_UNLCK;
515 ("Error unlocking previously locked range %d during test of lock ",
520 /* if rc == ERR_SHARING_VIOLATION ? */
521 rc = 0; /* do not change lock type to unlock since range in use */
528 rc = CIFSSMBLock(xid, pTcon,
529 ((struct cifsFileInfo *) file->private_data)->
531 pfLock->fl_start, numUnlock, numLock, lockType,
538 cifs_write(struct file * file, const char *write_data,
539 size_t write_size, loff_t * poffset)
542 unsigned int bytes_written = 0;
543 unsigned int total_written;
544 struct cifs_sb_info *cifs_sb;
545 struct cifsTconInfo *pTcon;
547 struct cifsFileInfo * open_file;
551 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
552 pTcon = cifs_sb->tcon;
555 (" write %d bytes to offset %lld of %s", write_size,
556 *poffset, file->f_dentry->d_name.name)); */
558 if (file->private_data == NULL) {
562 open_file = (struct cifsFileInfo *) file->private_data;
564 if(file->f_dentry->d_inode == NULL) {
569 if (*poffset > file->f_dentry->d_inode->i_size)
570 long_op = 2; /* writes past end of file can take a long time */
574 for (total_written = 0; write_size > total_written;
575 total_written += bytes_written) {
577 while(rc == -EAGAIN) {
578 if(file->private_data == NULL) {
579 /* file has been closed on us */
581 return total_written;
583 if ((open_file->invalidHandle) && (!open_file->closePend)) {
584 if((file->f_dentry == NULL) || (file->f_dentry->d_inode == NULL)) {
586 return total_written;
588 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
593 rc = CIFSSMBWrite(xid, pTcon,
595 write_size - total_written, *poffset,
597 write_data + total_written, long_op);
599 if (rc || (bytes_written == 0)) {
607 *poffset += bytes_written;
608 long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
611 /* since the write may have blocked check these pointers again */
613 if(file->f_dentry->d_inode) {
614 file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
616 if (bytes_written > 0) {
617 if (*poffset > file->f_dentry->d_inode->i_size)
618 i_size_write(file->f_dentry->d_inode, *poffset);
620 mark_inode_dirty_sync(file->f_dentry->d_inode);
624 return total_written;
628 cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
630 struct address_space *mapping = page->mapping;
631 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
634 int bytes_written = 0;
635 struct cifs_sb_info *cifs_sb;
636 struct cifsTconInfo *pTcon;
637 struct inode *inode = page->mapping->host;
638 struct cifsInodeInfo *cifsInode;
639 struct cifsFileInfo *open_file = NULL;
640 struct list_head *tmp;
641 struct list_head *tmp1;
643 cifs_sb = CIFS_SB(inode->i_sb);
644 pTcon = cifs_sb->tcon;
646 /* figure out which file struct to use
647 if (file->private_data == NULL) {
653 } else if(!mapping->host) {
657 offset += (loff_t)from;
658 write_data = kmap(page);
661 if((to > PAGE_CACHE_SIZE) || (from > to)) {
666 /* racing with truncate? */
667 if(offset > mapping->host->i_size) {
669 return 0; /* don't care */
672 /* check to make sure that we are not extending the file */
673 if(mapping->host->i_size - offset < (loff_t)to)
674 to = (unsigned)(mapping->host->i_size - offset);
677 cifsInode = CIFS_I(mapping->host);
678 read_lock(&GlobalSMBSeslock);
679 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
680 open_file = list_entry(tmp,struct cifsFileInfo, flist);
681 /* We check if file is open for writing first */
682 if((open_file->pfile) &&
683 ((open_file->pfile->f_flags & O_RDWR) ||
684 (open_file->pfile->f_flags & O_WRONLY))) {
685 read_unlock(&GlobalSMBSeslock);
686 bytes_written = cifs_write(open_file->pfile, write_data,
688 read_lock(&GlobalSMBSeslock);
689 /* Does mm or vfs already set times? */
690 inode->i_atime = inode->i_mtime = CURRENT_TIME;
691 if ((bytes_written > 0) && (offset)) {
693 } else if(bytes_written < 0) {
696 break; /* now that we found a valid file handle
697 and tried to write to it we are done, no
698 sense continuing to loop looking for another */
700 if(tmp->next == NULL) {
701 cFYI(1,("File instance %p removed",tmp));
705 read_unlock(&GlobalSMBSeslock);
706 if(open_file == NULL) {
707 cFYI(1,("No writeable filehandles for inode"));
717 cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
723 /* call 16K write then Setpageuptodate */
730 cifs_writepage(struct page* page, struct writeback_control *wbc)
736 /* BB add check for wbc flags */
737 page_cache_get(page);
739 rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
740 SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
742 page_cache_release(page);
748 cifs_commit_write(struct file *file, struct page *page, unsigned offset,
753 struct inode *inode = page->mapping->host;
754 loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
755 /* struct cifsFileInfo *open_file;
756 struct cifs_sb_info *cifs_sb; */
759 cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
760 if (position > inode->i_size){
761 i_size_write(inode, position);
762 /*if (file->private_data == NULL) {
765 open_file = (struct cifsFileInfo *)file->private_data;
766 cifs_sb = CIFS_SB(inode->i_sb);
768 while(rc == -EAGAIN) {
769 if((open_file->invalidHandle) &&
770 (!open_file->closePend)) {
771 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
775 if(!open_file->closePend) {
776 rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
777 position, open_file->netfid,
778 open_file->pid,FALSE);
784 cFYI(1,(" SetEOF (commit write) rc = %d",rc));
787 set_page_dirty(page);
794 cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
798 struct inode * inode = file->f_dentry->d_inode;
802 cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
803 dentry->d_name.name, datasync));
805 rc = filemap_fdatawrite(inode->i_mapping);
807 CIFS_I(inode)->write_behind_rc = 0;
813 cifs_sync_page(struct page *page)
815 struct address_space *mapping;
817 unsigned long index = page->index;
818 unsigned int rpages = 0;
821 cFYI(1,("sync page %p",page));
822 mapping = page->mapping;
825 inode = mapping->host;
829 /* fill in rpages then
830 result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
832 /* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
840 * As file closes, flush all cached write data for this inode checking
841 * for write behind errors.
844 int cifs_flush(struct file *file)
846 struct inode * inode = file->f_dentry->d_inode;
849 /* Rather than do the steps manually: */
850 /* lock the inode for writing */
851 /* loop through pages looking for write behind data (dirty pages) */
852 /* coalesce into contiguous 16K (or smaller) chunks to write to server */
853 /* send to server (prefer in parallel) */
854 /* deal with writebehind errors */
855 /* unlock inode for writing */
856 /* filemapfdatawrite appears easier for the time being */
858 rc = filemap_fdatawrite(inode->i_mapping);
859 if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
860 CIFS_I(inode)->write_behind_rc = 0;
862 cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
869 cifs_read(struct file * file, char *read_data, size_t read_size,
873 unsigned int bytes_read = 0;
874 unsigned int total_read;
875 unsigned int current_read_size;
876 struct cifs_sb_info *cifs_sb;
877 struct cifsTconInfo *pTcon;
879 char * current_offset;
880 struct cifsFileInfo * open_file;
883 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
884 pTcon = cifs_sb->tcon;
886 if (file->private_data == NULL) {
890 open_file = (struct cifsFileInfo *)file->private_data;
892 for (total_read = 0,current_offset=read_data; read_size > total_read;
893 total_read += bytes_read,current_offset+=bytes_read) {
894 current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
896 while(rc == -EAGAIN) {
897 if ((open_file->invalidHandle) && (!open_file->closePend)) {
898 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
903 rc = CIFSSMBRead(xid, pTcon,
905 current_read_size, *poffset,
906 &bytes_read, ¤t_offset);
908 if (rc || (bytes_read == 0)) {
916 *poffset += bytes_read;
924 int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
926 struct dentry * dentry = file->f_dentry;
930 rc = cifs_revalidate(dentry);
932 cFYI(1,("Validation prior to mmap failed, error=%d", rc));
936 rc = generic_file_mmap(file, vma);
941 static void cifs_copy_cache_pages(struct address_space *mapping,
942 struct list_head *pages, int bytes_read,
943 char *data,struct pagevec * plru_pvec)
948 while (bytes_read > 0) {
949 if(list_empty(pages))
952 page = list_entry(pages->prev, struct page, lru);
953 list_del(&page->lru);
955 if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
956 page_cache_release(page);
957 cFYI(1,("Add page cache failed"));
961 target = kmap_atomic(page,KM_USER0);
963 if(PAGE_CACHE_SIZE > bytes_read) {
964 memcpy(target,data,bytes_read);
965 /* zero the tail end of this partial page */
966 memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
969 memcpy(target,data,PAGE_CACHE_SIZE);
970 bytes_read -= PAGE_CACHE_SIZE;
972 kunmap_atomic(target,KM_USER0);
974 flush_dcache_page(page);
975 SetPageUptodate(page);
977 if (!pagevec_add(plru_pvec, page))
978 __pagevec_lru_add(plru_pvec);
979 data += PAGE_CACHE_SIZE;
986 cifs_readpages(struct file *file, struct address_space *mapping,
987 struct list_head *page_list, unsigned num_pages)
993 struct cifs_sb_info *cifs_sb;
994 struct cifsTconInfo *pTcon;
996 unsigned int read_size,i;
997 char * smb_read_data = 0;
998 struct smb_com_read_rsp * pSMBr;
999 struct pagevec lru_pvec;
1000 struct cifsFileInfo * open_file;
1003 if (file->private_data == NULL) {
1007 open_file = (struct cifsFileInfo *)file->private_data;
1008 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1009 pTcon = cifs_sb->tcon;
1011 pagevec_init(&lru_pvec, 0);
1013 for(i = 0;i<num_pages;) {
1014 unsigned contig_pages;
1015 struct page * tmp_page;
1016 unsigned long expected_index;
1018 if(list_empty(page_list)) {
1021 page = list_entry(page_list->prev, struct page, lru);
1022 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1024 /* count adjacent pages that we will read into */
1026 expected_index = list_entry(page_list->prev,struct page,lru)->index;
1027 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1028 if(tmp_page->index == expected_index) {
1035 if(contig_pages + i > num_pages) {
1036 contig_pages = num_pages - i;
1039 /* for reads over a certain size could initiate async read ahead */
1041 read_size = contig_pages * PAGE_CACHE_SIZE;
1042 /* Read size needs to be in multiples of one page */
1043 read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
1046 while(rc == -EAGAIN) {
1047 if ((open_file->invalidHandle) && (!open_file->closePend)) {
1048 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
1053 rc = CIFSSMBRead(xid, pTcon,
1056 &bytes_read, &smb_read_data);
1057 /* BB need to check return code here */
1060 cifs_buf_release(smb_read_data);
1065 if ((rc < 0) || (smb_read_data == NULL)) {
1066 cFYI(1,("Read error in readpages: %d",rc));
1067 /* clean up remaing pages off list */
1068 while (!list_empty(page_list) && (i < num_pages)) {
1069 page = list_entry(page_list->prev, struct page, lru);
1070 list_del(&page->lru);
1071 page_cache_release(page);
1074 } else if (bytes_read > 0) {
1075 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1076 cifs_copy_cache_pages(mapping, page_list, bytes_read,
1077 smb_read_data + 4 /* RFC1001 hdr */ +
1078 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1080 i += bytes_read >> PAGE_CACHE_SHIFT;
1082 if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1083 cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));
1085 i++; /* account for partial page */
1087 /* server copy of file can have smaller size than client */
1088 /* BB do we need to verify this common case ? this case is ok -
1089 if we are at server EOF we will hit it on next read */
1091 /* while(!list_empty(page_list) && (i < num_pages)) {
1092 page = list_entry(page_list->prev,struct page, list);
1093 list_del(&page->list);
1094 page_cache_release(page);
1099 cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset));
1100 /* BB turn off caching and do new lookup on file size at server? */
1101 while (!list_empty(page_list) && (i < num_pages)) {
1102 page = list_entry(page_list->prev, struct page, lru);
1103 list_del(&page->lru);
1104 page_cache_release(page); /* BB removeme - replace with zero of page? */
1109 cifs_buf_release(smb_read_data);
1115 pagevec_lru_add(&lru_pvec);
1117 /* need to free smb_read_data buf before exit */
1119 cifs_buf_release(smb_read_data);
1128 cifs_readpage(struct file *file, struct page *page)
1130 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1137 if (file->private_data == NULL) {
1142 cFYI(0,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
1144 page_cache_get(page);
1145 read_data = kmap(page);
1146 /* for reads over a certain size could initiate async read ahead */
1148 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, &offset);
1153 cFYI(1,("Bytes read %d ",rc));
1156 file->f_dentry->d_inode->i_atime = CURRENT_TIME;
1158 if(PAGE_CACHE_SIZE > rc) {
1159 memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
1161 flush_dcache_page(page);
1162 SetPageUptodate(page);
1169 page_cache_release(page);
1175 fill_in_inode(struct inode *tmp_inode,
1176 FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
1178 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
1179 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
1181 pfindData->ExtFileAttributes =
1182 le32_to_cpu(pfindData->ExtFileAttributes);
1183 pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
1184 pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
1185 cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
1186 cifsInfo->time = jiffies;
1188 /* Linux can not store file creation time unfortunately so ignore it */
1189 tmp_inode->i_atime =
1190 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
1191 tmp_inode->i_mtime =
1192 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
1193 tmp_inode->i_ctime =
1194 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
1195 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
1196 /* 2767 perms - indicate mandatory locking */
1197 /* BB fill in uid and gid here? with help from winbind?
1198 or retrieve from NTFS stream extended attribute */
1199 if(atomic_read(&cifsInfo->inUse) == 0) {
1200 tmp_inode->i_uid = cifs_sb->mnt_uid;
1201 tmp_inode->i_gid = cifs_sb->mnt_gid;
1202 /* set default mode. will override for dirs below */
1203 tmp_inode->i_mode = cifs_sb->mnt_file_mode;
1207 ("CIFS FFIRST: Attributes came in as 0x%x",
1208 pfindData->ExtFileAttributes));
1209 if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
1210 *pobject_type = DT_LNK;
1211 /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
1212 tmp_inode->i_mode |= S_IFLNK;
1213 } else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
1214 *pobject_type = DT_DIR;
1215 /* override default perms since we do not lock dirs */
1216 if(atomic_read(&cifsInfo->inUse) == 0) {
1217 tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
1219 tmp_inode->i_mode |= S_IFDIR;
1221 *pobject_type = DT_REG;
1222 tmp_inode->i_mode |= S_IFREG;
1223 if(pfindData->ExtFileAttributes & ATTR_READONLY)
1224 tmp_inode->i_mode &= ~(S_IWUGO);
1226 }/* could add code here - to validate if device or weird share type? */
1228 /* can not fill in nlink here as in qpathinfo version and Unx search */
1229 if(atomic_read(&cifsInfo->inUse) == 0) {
1230 atomic_set(&cifsInfo->inUse,1);
1233 i_size_write(tmp_inode,pfindData->EndOfFile);
1234 tmp_inode->i_blocks =
1235 (tmp_inode->i_blksize - 1 + pfindData->AllocationSize) >> tmp_inode->i_blkbits;
1236 if (pfindData->AllocationSize < pfindData->EndOfFile)
1237 cFYI(1, ("Possible sparse file: allocation size less than end of file "));
1239 ("File Size %ld and blocks %ld and blocksize %ld",
1240 (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
1241 tmp_inode->i_blksize));
1242 if (S_ISREG(tmp_inode->i_mode)) {
1243 cFYI(1, (" File inode "));
1244 tmp_inode->i_op = &cifs_file_inode_ops;
1245 tmp_inode->i_fop = &cifs_file_ops;
1246 tmp_inode->i_data.a_ops = &cifs_addr_ops;
1247 } else if (S_ISDIR(tmp_inode->i_mode)) {
1248 cFYI(1, (" Directory inode"));
1249 tmp_inode->i_op = &cifs_dir_inode_ops;
1250 tmp_inode->i_fop = &cifs_dir_ops;
1251 } else if (S_ISLNK(tmp_inode->i_mode)) {
1252 cFYI(1, (" Symbolic Link inode "));
1253 tmp_inode->i_op = &cifs_symlink_inode_ops;
1255 cFYI(1, (" Init special inode "));
1256 init_special_inode(tmp_inode, tmp_inode->i_mode,
1262 unix_fill_in_inode(struct inode *tmp_inode,
1263 FILE_UNIX_INFO * pfindData, int *pobject_type)
1265 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
1266 cifsInfo->time = jiffies;
1267 atomic_inc(&cifsInfo->inUse);
1269 tmp_inode->i_atime =
1270 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
1271 tmp_inode->i_mtime =
1272 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
1273 tmp_inode->i_ctime =
1274 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
1276 tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
1277 pfindData->Type = le32_to_cpu(pfindData->Type);
1278 if (pfindData->Type == UNIX_FILE) {
1279 *pobject_type = DT_REG;
1280 tmp_inode->i_mode |= S_IFREG;
1281 } else if (pfindData->Type == UNIX_SYMLINK) {
1282 *pobject_type = DT_LNK;
1283 tmp_inode->i_mode |= S_IFLNK;
1284 } else if (pfindData->Type == UNIX_DIR) {
1285 *pobject_type = DT_DIR;
1286 tmp_inode->i_mode |= S_IFDIR;
1287 } else if (pfindData->Type == UNIX_CHARDEV) {
1288 *pobject_type = DT_CHR;
1289 tmp_inode->i_mode |= S_IFCHR;
1290 } else if (pfindData->Type == UNIX_BLOCKDEV) {
1291 *pobject_type = DT_BLK;
1292 tmp_inode->i_mode |= S_IFBLK;
1293 } else if (pfindData->Type == UNIX_FIFO) {
1294 *pobject_type = DT_FIFO;
1295 tmp_inode->i_mode |= S_IFIFO;
1296 } else if (pfindData->Type == UNIX_SOCKET) {
1297 *pobject_type = DT_SOCK;
1298 tmp_inode->i_mode |= S_IFSOCK;
1301 tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
1302 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
1303 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
1305 pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
1306 pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
1307 i_size_write(tmp_inode,pfindData->EndOfFile);
1308 tmp_inode->i_blocks =
1309 (tmp_inode->i_blksize - 1 + pfindData->NumOfBytes) >> tmp_inode->i_blkbits;
1311 if (S_ISREG(tmp_inode->i_mode)) {
1312 cFYI(1, ("File inode"));
1313 tmp_inode->i_op = &cifs_file_inode_ops;
1314 tmp_inode->i_fop = &cifs_file_ops;
1315 tmp_inode->i_data.a_ops = &cifs_addr_ops;
1316 } else if (S_ISDIR(tmp_inode->i_mode)) {
1317 cFYI(1, ("Directory inode"));
1318 tmp_inode->i_op = &cifs_dir_inode_ops;
1319 tmp_inode->i_fop = &cifs_dir_ops;
1320 } else if (S_ISLNK(tmp_inode->i_mode)) {
1321 cFYI(1, ("Symbolic Link inode"));
1322 tmp_inode->i_op = &cifs_symlink_inode_ops;
1323 /* tmp_inode->i_fop = *//* do not need to set to anything */
1325 cFYI(1, ("Special inode"));
1326 init_special_inode(tmp_inode, tmp_inode->i_mode,
1332 construct_dentry(struct qstr *qstring, struct file *file,
1333 struct inode **ptmp_inode, struct dentry **pnew_dentry)
1335 struct dentry *tmp_dentry;
1336 struct cifs_sb_info *cifs_sb;
1337 struct cifsTconInfo *pTcon;
1339 cFYI(1, ("For %s ", qstring->name));
1340 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1341 pTcon = cifs_sb->tcon;
1343 qstring->hash = full_name_hash(qstring->name, qstring->len);
1344 tmp_dentry = d_lookup(file->f_dentry, qstring);
1346 cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
1347 *ptmp_inode = tmp_dentry->d_inode;
1348 /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
1349 if(*ptmp_inode == NULL) {
1350 *ptmp_inode = new_inode(file->f_dentry->d_sb);
1351 d_instantiate(tmp_dentry, *ptmp_inode);
1354 tmp_dentry = d_alloc(file->f_dentry, qstring);
1355 if(tmp_dentry == NULL) {
1356 cERROR(1,("Failed allocating dentry"));
1360 *ptmp_inode = new_inode(file->f_dentry->d_sb);
1361 tmp_dentry->d_op = &cifs_dentry_ops;
1362 cFYI(0, (" instantiate dentry 0x%p with inode 0x%p ",
1363 tmp_dentry, *ptmp_inode));
1364 d_instantiate(tmp_dentry, *ptmp_inode);
1365 d_rehash(tmp_dentry);
1368 tmp_dentry->d_time = jiffies;
1369 *pnew_dentry = tmp_dentry;
1372 static void reset_resume_key(struct file * dir_file,
1373 unsigned char * filename,
1374 unsigned int len,int Unicode,struct nls_table * nls_tab) {
1375 struct cifsFileInfo *cifsFile;
1377 cifsFile = (struct cifsFileInfo *)dir_file->private_data;
1378 if(cifsFile == NULL)
1380 if(cifsFile->search_resume_name) {
1381 kfree(cifsFile->search_resume_name);
1386 cifsFile->resume_name_length = len;
1388 cifsFile->search_resume_name =
1389 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1391 if(cifsFile->search_resume_name == NULL) {
1392 cERROR(1,("failed new resume key allocate, length %d",
1393 cifsFile->resume_name_length));
1397 cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
1398 filename, len, nls_tab);
1400 memcpy(cifsFile->search_resume_name, filename,
1401 cifsFile->resume_name_length);
1402 cFYI(1,("Reset resume key to: %s with len %d",filename,len));
1409 cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
1410 struct file *file, filldir_t filldir, void *direntry)
1412 struct inode *tmp_inode;
1413 struct dentry *tmp_dentry;
1416 pqstring->name = pfindData->FileName;
1417 pqstring->len = pfindData->FileNameLength;
1419 construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
1421 fill_in_inode(tmp_inode, pfindData, &object_type);
1422 rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
1423 tmp_inode->i_ino, object_type);
1425 /* due to readdir error we need to recalculate resume
1426 key so next readdir will restart on right entry */
1427 cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
1434 cifs_filldir_unix(struct qstr *pqstring,
1435 FILE_UNIX_INFO * pUnixFindData, struct file *file,
1436 filldir_t filldir, void *direntry)
1438 struct inode *tmp_inode;
1439 struct dentry *tmp_dentry;
1440 int object_type, rc;
1442 pqstring->name = pUnixFindData->FileName;
1443 pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
1445 construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
1447 unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
1448 rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
1449 file->f_pos, tmp_inode->i_ino, object_type);
1451 /* due to readdir error we need to recalculate resume
1452 key so next readdir will restart on right entry */
1453 cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
1460 cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
1464 int Unicode = FALSE;
1465 int UnixSearch = FALSE;
1466 unsigned int bufsize, i;
1468 struct cifs_sb_info *cifs_sb;
1469 struct cifsTconInfo *pTcon;
1470 struct cifsFileInfo *cifsFile = NULL;
1471 char *full_path = NULL;
1473 struct qstr qstring;
1474 T2_FFIRST_RSP_PARMS findParms;
1475 T2_FNEXT_RSP_PARMS findNextParms;
1476 FILE_DIRECTORY_INFO *pfindData;
1477 FILE_DIRECTORY_INFO *lastFindData;
1478 FILE_UNIX_INFO *pfindDataUnix;
1482 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1483 pTcon = cifs_sb->tcon;
1484 bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
1485 if(bufsize > CIFS_MAX_MSGSIZE) {
1489 data = kmalloc(bufsize, GFP_KERNEL);
1490 pfindData = (FILE_DIRECTORY_INFO *) data;
1492 full_path = build_wildcard_path_from_dentry(file->f_dentry);
1494 cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
1496 switch ((int) file->f_pos) {
1498 if (filldir(direntry, ".", 1, file->f_pos,
1499 file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
1500 cERROR(1, ("Filldir for current dir failed "));
1506 if (filldir(direntry, "..", 2, file->f_pos,
1507 file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
1508 cERROR(1, ("Filldir for parent dir failed "));
1514 if (file->private_data != NULL) {
1516 (struct cifsFileInfo *) file->private_data;
1517 if (cifsFile->endOfSearch) {
1518 if(cifsFile->emptyDir) {
1519 cFYI(1, ("End of search, empty dir"));
1524 cifsFile->invalidHandle = TRUE;
1525 CIFSFindClose(xid, pTcon, cifsFile->netfid);
1527 if(cifsFile->search_resume_name) {
1528 kfree(cifsFile->search_resume_name);
1529 cifsFile->search_resume_name = NULL;
1532 rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
1533 &findParms, cifs_sb->local_nls,
1534 &Unicode, &UnixSearch);
1535 cFYI(1, ("Count: %d End: %d ", findParms.SearchCount,
1536 findParms.EndofSearch));
1539 searchHandle = findParms.SearchHandle;
1540 if(file->private_data == NULL)
1541 file->private_data =
1542 kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
1543 if (file->private_data) {
1544 memset(file->private_data, 0,
1545 sizeof (struct cifsFileInfo));
1547 (struct cifsFileInfo *) file->private_data;
1548 cifsFile->netfid = searchHandle;
1549 cifsFile->invalidHandle = FALSE;
1550 init_MUTEX(&cifsFile->fh_sem);
1556 renew_parental_timestamps(file->f_dentry);
1558 (FILE_DIRECTORY_INFO *) ((char *) pfindData +
1559 findParms.LastNameOffset);
1560 if((char *)lastFindData > (char *)pfindData + bufsize) {
1561 cFYI(1,("last search entry past end of packet"));
1565 /* Offset of resume key same for levels 257 and 514 */
1566 cifsFile->resume_key = lastFindData->FileIndex;
1567 if(UnixSearch == FALSE) {
1568 cifsFile->resume_name_length =
1569 le32_to_cpu(lastFindData->FileNameLength);
1570 if(cifsFile->resume_name_length > bufsize - 64) {
1571 cFYI(1,("Illegal resume file name length %d",
1572 cifsFile->resume_name_length));
1576 cifsFile->search_resume_name =
1577 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1578 cFYI(1,("Last file: %s with name %d bytes long",
1579 lastFindData->FileName,
1580 cifsFile->resume_name_length));
1581 memcpy(cifsFile->search_resume_name,
1582 lastFindData->FileName,
1583 cifsFile->resume_name_length);
1585 pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
1586 if (Unicode == TRUE) {
1587 for(i=0;(pfindDataUnix->FileName[i]
1588 | pfindDataUnix->FileName[i+1]);
1593 cifsFile->resume_name_length = i + 2;
1595 cifsFile->resume_name_length =
1596 strnlen(pfindDataUnix->FileName,
1599 if(cifsFile->resume_name_length > bufsize - 64) {
1600 cFYI(1,("Illegal resume file name length %d",
1601 cifsFile->resume_name_length));
1605 cifsFile->search_resume_name =
1606 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1607 cFYI(1,("Last file: %s with name %d bytes long",
1608 pfindDataUnix->FileName,
1609 cifsFile->resume_name_length));
1610 memcpy(cifsFile->search_resume_name,
1611 pfindDataUnix->FileName,
1612 cifsFile->resume_name_length);
1614 for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
1615 if (UnixSearch == FALSE) {
1616 pfindData->FileNameLength =
1617 le32_to_cpu(pfindData->FileNameLength);
1618 if (Unicode == TRUE)
1619 pfindData->FileNameLength =
1621 (pfindData->FileName,
1623 pfindData->FileName,
1625 FileNameLength) / 2,
1626 cifs_sb->local_nls);
1627 qstring.len = pfindData->FileNameLength;
1628 if (((qstring.len != 1)
1629 || (pfindData->FileName[0] != '.'))
1630 && ((qstring.len != 2)
1634 FileName[1] != '.'))) {
1635 if(cifs_filldir(&qstring,
1639 /* do not end search if
1640 kernel not ready to take
1641 remaining entries yet */
1642 reset_resume_key(file, pfindData->FileName,qstring.len,
1643 Unicode, cifs_sb->local_nls);
1644 findParms.EndofSearch = 0;
1649 } else { /* UnixSearch */
1651 (FILE_UNIX_INFO *) pfindData;
1652 if (Unicode == TRUE)
1655 (pfindDataUnix->FileName,
1657 pfindDataUnix->FileName,
1659 cifs_sb->local_nls);
1662 strnlen(pfindDataUnix->
1665 if (((qstring.len != 1)
1667 FileName[0] != '.'))
1668 && ((qstring.len != 2)
1672 FileName[1] != '.'))) {
1673 if(cifs_filldir_unix(&qstring,
1678 /* do not end search if
1679 kernel not ready to take
1680 remaining entries yet */
1681 findParms.EndofSearch = 0;
1682 reset_resume_key(file, pfindDataUnix->FileName,
1683 qstring.len,Unicode,cifs_sb->local_nls);
1689 /* works also for Unix ff struct since first field of both */
1691 (FILE_DIRECTORY_INFO *) ((char *) pfindData
1692 + le32_to_cpu(pfindData->NextEntryOffset));
1693 /* BB also should check to make sure that pointer is not beyond the end of the SMB */
1694 /* if(pfindData > lastFindData) rc = -EIO; break; */
1695 } /* end for loop */
1696 if ((findParms.EndofSearch != 0) && cifsFile) {
1697 cifsFile->endOfSearch = TRUE;
1698 if(findParms.SearchCount == 2)
1699 cifsFile->emptyDir = TRUE;
1703 cifsFile->endOfSearch = TRUE;
1704 /* unless parent directory gone do not return error */
1709 if (file->private_data == NULL) {
1712 ("Readdir on closed srch, pos = %lld",
1715 cifsFile = (struct cifsFileInfo *) file->private_data;
1716 if (cifsFile->endOfSearch) {
1718 cFYI(1, ("End of search "));
1721 searchHandle = cifsFile->netfid;
1722 rc = CIFSFindNext(xid, pTcon, pfindData,
1723 &findNextParms, searchHandle,
1724 cifsFile->search_resume_name,
1725 cifsFile->resume_name_length,
1726 cifsFile->resume_key,
1727 &Unicode, &UnixSearch);
1728 cFYI(1,("Count: %d End: %d ",
1729 findNextParms.SearchCount,
1730 findNextParms.EndofSearch));
1731 if ((rc == 0) && (findNextParms.SearchCount != 0)) {
1732 /* BB save off resume key, key name and name length */
1734 (FILE_DIRECTORY_INFO *) ((char *) pfindData
1735 + findNextParms.LastNameOffset);
1736 if((char *)lastFindData > (char *)pfindData + bufsize) {
1737 cFYI(1,("last search entry past end of packet"));
1741 /* Offset of resume key same for levels 257 and 514 */
1742 cifsFile->resume_key = lastFindData->FileIndex;
1744 if(UnixSearch == FALSE) {
1745 cifsFile->resume_name_length =
1746 le32_to_cpu(lastFindData->FileNameLength);
1747 if(cifsFile->resume_name_length > bufsize - 64) {
1748 cFYI(1,("Illegal resume file name length %d",
1749 cifsFile->resume_name_length));
1753 /* Free the memory allocated by previous findfirst
1754 or findnext call - we can not reuse the memory since
1755 the resume name may not be same string length */
1756 if(cifsFile->search_resume_name)
1757 kfree(cifsFile->search_resume_name);
1758 cifsFile->search_resume_name =
1759 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1760 cFYI(1,("Last file: %s with name %d bytes long",
1761 lastFindData->FileName,
1762 cifsFile->resume_name_length));
1763 memcpy(cifsFile->search_resume_name,
1764 lastFindData->FileName,
1765 cifsFile->resume_name_length);
1767 pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
1768 if (Unicode == TRUE) {
1769 for(i=0;(pfindDataUnix->FileName[i]
1770 | pfindDataUnix->FileName[i+1]);
1775 cifsFile->resume_name_length = i + 2;
1777 cifsFile->resume_name_length =
1778 strnlen(pfindDataUnix->
1782 if(cifsFile->resume_name_length > bufsize - 64) {
1783 cFYI(1,("Illegal resume file name length %d",
1784 cifsFile->resume_name_length));
1788 /* Free the memory allocated by previous findfirst
1789 or findnext call - we can not reuse the memory since
1790 the resume name may not be same string length */
1791 if(cifsFile->search_resume_name)
1792 kfree(cifsFile->search_resume_name);
1793 cifsFile->search_resume_name =
1794 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1795 cFYI(1,("fnext last file: %s with name %d bytes long",
1796 lastFindData->FileName,
1797 cifsFile->resume_name_length));
1798 memcpy(cifsFile->search_resume_name,
1799 lastFindData->FileName,
1800 cifsFile->resume_name_length);
1803 for (i = 0; i < findNextParms.SearchCount; i++) {
1804 pfindData->FileNameLength =
1805 le32_to_cpu(pfindData->
1807 if (UnixSearch == FALSE) {
1808 if (Unicode == TRUE)
1809 pfindData->FileNameLength =
1811 (pfindData->FileName,
1813 pfindData->FileName,
1814 (pfindData->FileNameLength)/ 2,
1815 cifs_sb->local_nls);
1817 pfindData->FileNameLength;
1818 if (((qstring.len != 1)
1819 || (pfindData->FileName[0] != '.'))
1820 && ((qstring.len != 2)
1821 || (pfindData->FileName[0] != '.')
1822 || (pfindData->FileName[1] !=
1829 /* do not end search if
1830 kernel not ready to take
1831 remaining entries yet */
1832 findNextParms.EndofSearch = 0;
1833 reset_resume_key(file, pfindData->FileName,qstring.len,
1834 Unicode,cifs_sb->local_nls);
1839 } else { /* UnixSearch */
1843 if (Unicode == TRUE)
1846 (pfindDataUnix->FileName,
1848 pfindDataUnix->FileName,
1850 cifs_sb->local_nls);
1857 if (((qstring.len != 1)
1859 FileName[0] != '.'))
1860 && ((qstring.len != 2)
1866 if(cifs_filldir_unix
1871 /* do not end search if
1872 kernel not ready to take
1873 remaining entries yet */
1874 findNextParms.EndofSearch = 0;
1875 reset_resume_key(file, pfindDataUnix->FileName,qstring.len,
1876 Unicode,cifs_sb->local_nls);
1882 pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData +
1883 le32_to_cpu(pfindData->NextEntryOffset));
1884 /* works also for Unix find struct since first field of both */
1885 /* BB also should check to ensure pointer not beyond end of SMB */
1886 } /* end for loop */
1887 if (findNextParms.EndofSearch != 0) {
1888 cifsFile->endOfSearch = TRUE;
1891 cifsFile->endOfSearch = TRUE;
1892 rc = 0; /* unless parent directory disappeared - do not
1893 return error here (eg Access Denied or no more files) */
1905 int cifs_prepare_write(struct file *file, struct page *page,
1906 unsigned from, unsigned to)
1908 cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
1909 if (!PageUptodate(page)) {
1910 if (to - from != PAGE_CACHE_SIZE) {
1911 void *kaddr = kmap_atomic(page, KM_USER0);
1912 memset(kaddr, 0, from);
1913 memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1914 flush_dcache_page(page);
1915 kunmap_atomic(kaddr, KM_USER0);
1917 SetPageUptodate(page);
1923 struct address_space_operations cifs_addr_ops = {
1924 .readpage = cifs_readpage,
1925 .readpages = cifs_readpages,
1926 .writepage = cifs_writepage,
1927 .prepare_write = simple_prepare_write, /* BB fixme BB */
1928 /* .prepare_write = cifs_prepare_write, */ /* BB removeme BB */
1929 .commit_write = cifs_commit_write,
1930 /* .sync_page = cifs_sync_page, */