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 down(&inode->i_sb->s_vfs_rename_sem);
84 full_path = build_path_from_dentry(file->f_dentry);
85 up(&inode->i_sb->s_vfs_rename_sem);
86 if(full_path == NULL) {
91 cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
92 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
93 desiredAccess = GENERIC_READ;
94 else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
95 desiredAccess = GENERIC_WRITE;
96 else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
97 /* GENERIC_ALL is too much permission to request */
98 /* can cause unnecessary access denied on create */
99 /* desiredAccess = GENERIC_ALL; */
100 desiredAccess = GENERIC_READ | GENERIC_WRITE;
103 /*********************************************************************
104 * open flag mapping table:
106 * POSIX Flag CIFS Disposition
107 * ---------- ----------------
108 * O_CREAT FILE_OPEN_IF
109 * O_CREAT | O_EXCL FILE_CREATE
110 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
111 * O_TRUNC FILE_OVERWRITE
112 * none of the above FILE_OPEN
114 * Note that there is not a direct match between disposition
115 * FILE_SUPERSEDE (ie create whether or not file exists although
116 * O_CREAT | O_TRUNC is similar but truncates the existing
117 * file rather than creating a new file as FILE_SUPERSEDE does
118 * (which uses the attributes / metadata passed in on open call)
120 *? O_SYNC is a reasonable match to CIFS writethrough flag
121 *? and the read write flags match reasonably. O_LARGEFILE
122 *? is irrelevant because largefile support is always used
123 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
124 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
125 *********************************************************************/
127 if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
128 disposition = FILE_CREATE;
129 else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
130 disposition = FILE_OVERWRITE_IF;
131 else if((file->f_flags & O_CREAT) == O_CREAT)
132 disposition = FILE_OPEN_IF;
134 disposition = FILE_OPEN;
141 /* BB pass O_SYNC flag through on file attributes .. BB */
143 /* Also refresh inode by passing in file_info buf returned by SMBOpen
144 and calling get_inode_info with returned buf (at least
145 helps non-Unix server case */
146 buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
153 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
154 CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
156 cFYI(1, ("cifs_open returned 0x%x ", rc));
157 cFYI(1, ("oplock: %d ", oplock));
160 kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
161 if (file->private_data) {
162 memset(file->private_data, 0, sizeof(struct cifsFileInfo));
163 pCifsFile = (struct cifsFileInfo *) file->private_data;
164 pCifsFile->netfid = netfid;
165 pCifsFile->pid = current->pid;
166 init_MUTEX(&pCifsFile->fh_sem);
167 pCifsFile->pfile = file; /* needed for writepage */
168 pCifsFile->pInode = inode;
169 pCifsFile->invalidHandle = FALSE;
170 pCifsFile->closePend = FALSE;
171 write_lock(&file->f_owner.lock);
172 write_lock(&GlobalSMBSeslock);
173 list_add(&pCifsFile->tlist,&pTcon->openFileList);
174 pCifsInode = CIFS_I(file->f_dentry->d_inode);
176 list_add(&pCifsFile->flist,&pCifsInode->openFileList);
177 write_unlock(&GlobalSMBSeslock);
178 write_unlock(&file->f_owner.lock);
179 if(pCifsInode->clientCanCacheRead) {
180 /* we have the inode open somewhere else
181 no need to discard cache data */
184 /* BB need same check in cifs_create too? */
186 /* if not oplocked, invalidate inode pages if mtime
187 or file size changed */
188 struct timespec temp;
189 temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
190 if(timespec_equal(&file->f_dentry->d_inode->i_mtime,&temp) &&
191 (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
192 cFYI(1,("inode unchanged on server"));
194 if(file->f_dentry->d_inode->i_mapping) {
195 /* BB no need to lock inode until after invalidate*/
196 /* since namei code should already have it locked?*/
197 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
198 filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
200 cFYI(1,("invalidating remote inode since open detected it changed"));
201 invalidate_remote_inode(file->f_dentry->d_inode);
205 if (pTcon->ses->capabilities & CAP_UNIX)
206 rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
207 full_path, inode->i_sb);
209 rc = cifs_get_inode_info(&file->f_dentry->d_inode,
210 full_path, buf, inode->i_sb);
212 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
213 pCifsInode->clientCanCacheAll = TRUE;
214 pCifsInode->clientCanCacheRead = TRUE;
215 cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
216 } else if((oplock & 0xF) == OPLOCK_READ)
217 pCifsInode->clientCanCacheRead = TRUE;
219 write_unlock(&GlobalSMBSeslock);
220 write_unlock(&file->f_owner.lock);
222 if(oplock & CIFS_CREATE_ACTION) {
223 /* time to set mode which we can not set earlier due
224 to problems creating new read-only files */
225 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
226 CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
231 else {/* BB implement via Windows security descriptors */
232 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
233 /* in the meantime could set r/o dos attribute when perms are eg:
248 /* Try to reaquire byte range locks that were released when session */
249 /* to server was lost */
250 static int cifs_relock_file(struct cifsFileInfo * cifsFile)
254 /* BB list all locks open on this file and relock */
259 static int cifs_reopen_file(struct inode *inode, struct file *file)
263 struct cifs_sb_info *cifs_sb;
264 struct cifsTconInfo *pTcon;
265 struct cifsFileInfo *pCifsFile;
266 struct cifsInodeInfo *pCifsInode;
267 char *full_path = NULL;
268 int desiredAccess = 0x20197;
269 int disposition = FILE_OPEN;
271 FILE_ALL_INFO * buf = NULL;
275 if (file->private_data) {
276 pCifsFile = (struct cifsFileInfo *) file->private_data;
281 down(&pCifsFile->fh_sem);
282 if(pCifsFile->invalidHandle == FALSE) {
283 up(&pCifsFile->fh_sem);
288 if(file->f_dentry == NULL) {
289 up(&pCifsFile->fh_sem);
290 cFYI(1,("failed file reopen, no valid name if dentry freed"));
294 cifs_sb = CIFS_SB(inode->i_sb);
295 pTcon = cifs_sb->tcon;
296 /* can not grab rename sem here because various ops, including
297 those that already have the rename sem can end up causing writepage
298 to get called and if the server was down that means we end up here,
299 and we can never tell if the caller already has the rename_sem */
300 full_path = build_path_from_dentry(file->f_dentry);
301 if(full_path == NULL) {
302 up(&pCifsFile->fh_sem);
307 cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
308 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
309 desiredAccess = GENERIC_READ;
310 else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
311 desiredAccess = GENERIC_WRITE;
312 else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
313 /* GENERIC_ALL is too much permission to request */
314 /* can cause unnecessary access denied on create */
315 /* desiredAccess = GENERIC_ALL; */
316 desiredAccess = GENERIC_READ | GENERIC_WRITE;
324 /* BB pass O_SYNC flag through on file attributes .. BB */
326 /* Also refresh inode by passing in file_info buf returned by SMBOpen
327 and calling get_inode_info with returned buf (at least
328 helps non-Unix server case */
329 buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
331 up(&pCifsFile->fh_sem);
337 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
338 CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
340 up(&pCifsFile->fh_sem);
341 cFYI(1, ("cifs_open returned 0x%x ", rc));
342 cFYI(1, ("oplock: %d ", oplock));
344 pCifsFile->netfid = netfid;
345 pCifsFile->invalidHandle = FALSE;
346 up(&pCifsFile->fh_sem);
347 pCifsInode = CIFS_I(inode);
349 if (pTcon->ses->capabilities & CAP_UNIX)
350 rc = cifs_get_inode_info_unix(&inode,
351 full_path, inode->i_sb);
353 rc = cifs_get_inode_info(&inode,
354 full_path, buf, inode->i_sb);
356 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
357 pCifsInode->clientCanCacheAll = TRUE;
358 pCifsInode->clientCanCacheRead = TRUE;
359 cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
360 } else if((oplock & 0xF) == OPLOCK_READ) {
361 pCifsInode->clientCanCacheRead = TRUE;
362 pCifsInode->clientCanCacheAll = FALSE;
364 pCifsInode->clientCanCacheRead = FALSE;
365 pCifsInode->clientCanCacheAll = FALSE;
367 cifs_relock_file(pCifsFile);
380 cifs_close(struct inode *inode, struct file *file)
384 struct cifs_sb_info *cifs_sb;
385 struct cifsTconInfo *pTcon;
386 struct cifsFileInfo *pSMBFile =
387 (struct cifsFileInfo *) file->private_data;
391 cifs_sb = CIFS_SB(inode->i_sb);
392 pTcon = cifs_sb->tcon;
394 pSMBFile->closePend = TRUE;
395 write_lock(&file->f_owner.lock);
397 /* no sense reconnecting to close a file that is
399 if (pTcon->tidStatus != CifsNeedReconnect) {
400 write_unlock(&file->f_owner.lock);
401 rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
402 write_lock(&file->f_owner.lock);
405 list_del(&pSMBFile->flist);
406 list_del(&pSMBFile->tlist);
407 write_unlock(&file->f_owner.lock);
408 if(pSMBFile->search_resume_name)
409 kfree(pSMBFile->search_resume_name);
410 kfree(file->private_data);
411 file->private_data = NULL;
415 if(list_empty(&(CIFS_I(inode)->openFileList))) {
416 cFYI(1,("closing last open instance for inode %p",inode));
417 /* if the file is not open we do not know if we can cache
418 info on this inode, much less write behind and read ahead */
419 CIFS_I(inode)->clientCanCacheRead = FALSE;
420 CIFS_I(inode)->clientCanCacheAll = FALSE;
422 if((rc ==0) && CIFS_I(inode)->write_behind_rc)
423 rc = CIFS_I(inode)->write_behind_rc;
429 cifs_closedir(struct inode *inode, struct file *file)
433 struct cifsFileInfo *pSMBFileStruct =
434 (struct cifsFileInfo *) file->private_data;
436 cFYI(1, ("Closedir inode = 0x%p with ", inode));
440 if (pSMBFileStruct) {
441 cFYI(1, ("Freeing private data in close dir"));
442 kfree(file->private_data);
443 file->private_data = NULL;
450 cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
453 __u32 lockType = LOCKING_ANDX_LARGE_FILES;
457 int wait_flag = FALSE;
458 struct cifs_sb_info *cifs_sb;
459 struct cifsTconInfo *pTcon;
460 length = 1 + pfLock->fl_end - pfLock->fl_start;
467 ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
468 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
471 if (pfLock->fl_flags & FL_POSIX)
473 if (pfLock->fl_flags & FL_FLOCK)
475 if (pfLock->fl_flags & FL_SLEEP) {
476 cFYI(1, ("Blocking lock "));
479 if (pfLock->fl_flags & FL_ACCESS)
480 cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
481 if (pfLock->fl_flags & FL_LEASE)
482 cFYI(1, ("Lease on file - not implemented yet"));
483 if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
484 cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
486 if (pfLock->fl_type == F_WRLCK) {
487 cFYI(1, ("F_WRLCK "));
489 } else if (pfLock->fl_type == F_UNLCK) {
490 cFYI(1, ("F_UNLCK "));
492 } else if (pfLock->fl_type == F_RDLCK) {
493 cFYI(1, ("F_RDLCK "));
494 lockType |= LOCKING_ANDX_SHARED_LOCK;
496 } else if (pfLock->fl_type == F_EXLCK) {
497 cFYI(1, ("F_EXLCK "));
499 } else if (pfLock->fl_type == F_SHLCK) {
500 cFYI(1, ("F_SHLCK "));
501 lockType |= LOCKING_ANDX_SHARED_LOCK;
504 cFYI(1, ("Unknown type of lock "));
506 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
507 pTcon = cifs_sb->tcon;
509 if (file->private_data == NULL) {
515 rc = CIFSSMBLock(xid, pTcon,
516 ((struct cifsFileInfo *) file->
517 private_data)->netfid,
519 pfLock->fl_start, 0, 1, lockType,
522 rc = CIFSSMBLock(xid, pTcon,
523 ((struct cifsFileInfo *) file->
524 private_data)->netfid,
526 pfLock->fl_start, 1 /* numUnlock */ ,
527 0 /* numLock */ , lockType,
529 pfLock->fl_type = F_UNLCK;
532 ("Error unlocking previously locked range %d during test of lock ",
537 /* if rc == ERR_SHARING_VIOLATION ? */
538 rc = 0; /* do not change lock type to unlock since range in use */
545 rc = CIFSSMBLock(xid, pTcon,
546 ((struct cifsFileInfo *) file->private_data)->
548 pfLock->fl_start, numUnlock, numLock, lockType,
555 cifs_write(struct file * file, const char *write_data,
556 size_t write_size, loff_t * poffset)
559 unsigned int bytes_written = 0;
560 unsigned int total_written;
561 struct cifs_sb_info *cifs_sb;
562 struct cifsTconInfo *pTcon;
564 struct cifsFileInfo * open_file;
566 if(file->f_dentry == NULL)
571 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
572 pTcon = cifs_sb->tcon;
575 (" write %d bytes to offset %lld of %s", write_size,
576 *poffset, file->f_dentry->d_name.name)); */
578 if (file->private_data == NULL) {
582 open_file = (struct cifsFileInfo *) file->private_data;
584 if(file->f_dentry->d_inode == NULL) {
589 if (*poffset > file->f_dentry->d_inode->i_size)
590 long_op = 2; /* writes past end of file can take a long time */
594 for (total_written = 0; write_size > total_written;
595 total_written += bytes_written) {
597 while(rc == -EAGAIN) {
598 if(file->private_data == NULL) {
599 /* file has been closed on us */
601 return total_written;
603 if ((open_file->invalidHandle) && (!open_file->closePend)) {
604 if((file->f_dentry == NULL) || (file->f_dentry->d_inode == NULL)) {
606 return total_written;
608 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
613 rc = CIFSSMBWrite(xid, pTcon,
615 write_size - total_written, *poffset,
617 write_data + total_written, long_op);
619 if (rc || (bytes_written == 0)) {
627 *poffset += bytes_written;
628 long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
631 #ifdef CONFIG_CIFS_STATS
632 if(total_written > 0) {
633 atomic_inc(&pTcon->num_writes);
634 spin_lock(&pTcon->stat_lock);
635 pTcon->bytes_written += total_written;
636 spin_unlock(&pTcon->stat_lock);
640 /* since the write may have blocked check these pointers again */
642 if(file->f_dentry->d_inode) {
643 file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
645 if (total_written > 0) {
646 if (*poffset > file->f_dentry->d_inode->i_size)
647 i_size_write(file->f_dentry->d_inode, *poffset);
649 mark_inode_dirty_sync(file->f_dentry->d_inode);
653 return total_written;
657 cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
659 struct address_space *mapping = page->mapping;
660 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
663 int bytes_written = 0;
664 struct cifs_sb_info *cifs_sb;
665 struct cifsTconInfo *pTcon;
667 struct cifsInodeInfo *cifsInode;
668 struct cifsFileInfo *open_file = NULL;
669 struct list_head *tmp;
670 struct list_head *tmp1;
674 } else if(!mapping->host) {
678 inode = page->mapping->host;
679 cifs_sb = CIFS_SB(inode->i_sb);
680 pTcon = cifs_sb->tcon;
682 offset += (loff_t)from;
683 write_data = kmap(page);
686 if((to > PAGE_CACHE_SIZE) || (from > to)) {
691 /* racing with truncate? */
692 if(offset > mapping->host->i_size) {
694 return 0; /* don't care */
697 /* check to make sure that we are not extending the file */
698 if(mapping->host->i_size - offset < (loff_t)to)
699 to = (unsigned)(mapping->host->i_size - offset);
702 cifsInode = CIFS_I(mapping->host);
703 read_lock(&GlobalSMBSeslock);
704 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
705 open_file = list_entry(tmp,struct cifsFileInfo, flist);
706 if(open_file->closePend)
708 /* We check if file is open for writing first */
709 if((open_file->pfile) &&
710 ((open_file->pfile->f_flags & O_RDWR) ||
711 (open_file->pfile->f_flags & O_WRONLY))) {
712 read_unlock(&GlobalSMBSeslock);
713 bytes_written = cifs_write(open_file->pfile, write_data,
715 read_lock(&GlobalSMBSeslock);
716 /* Does mm or vfs already set times? */
717 inode->i_atime = inode->i_mtime = CURRENT_TIME;
718 if ((bytes_written > 0) && (offset)) {
720 } else if(bytes_written < 0) {
722 /* have seen a case in which
723 kernel seemed to have closed/freed a file
724 even with writes active so we might as well
725 see if there are other file structs to try
726 for the same inode before giving up */
731 break; /* now that we found a valid file handle
732 and tried to write to it we are done, no
733 sense continuing to loop looking for another */
735 if(tmp->next == NULL) {
736 cFYI(1,("File instance %p removed",tmp));
740 read_unlock(&GlobalSMBSeslock);
741 if(open_file == NULL) {
742 cFYI(1,("No writeable filehandles for inode"));
752 cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
758 /* call 16K write then Setpageuptodate */
765 cifs_writepage(struct page* page, struct writeback_control *wbc)
771 /* BB add check for wbc flags */
772 page_cache_get(page);
774 rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
775 SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
777 page_cache_release(page);
783 cifs_commit_write(struct file *file, struct page *page, unsigned offset,
788 struct inode *inode = page->mapping->host;
789 loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
790 /* struct cifsFileInfo *open_file;
791 struct cifs_sb_info *cifs_sb; */
794 cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
795 if (position > inode->i_size){
796 i_size_write(inode, position);
797 /*if (file->private_data == NULL) {
800 open_file = (struct cifsFileInfo *)file->private_data;
801 cifs_sb = CIFS_SB(inode->i_sb);
803 while(rc == -EAGAIN) {
804 if((open_file->invalidHandle) &&
805 (!open_file->closePend)) {
806 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
810 if(!open_file->closePend) {
811 rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
812 position, open_file->netfid,
813 open_file->pid,FALSE);
819 cFYI(1,(" SetEOF (commit write) rc = %d",rc));
822 set_page_dirty(page);
829 cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
833 struct inode * inode = file->f_dentry->d_inode;
837 cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
838 dentry->d_name.name, datasync));
840 rc = filemap_fdatawrite(inode->i_mapping);
842 CIFS_I(inode)->write_behind_rc = 0;
848 cifs_sync_page(struct page *page)
850 struct address_space *mapping;
852 unsigned long index = page->index;
853 unsigned int rpages = 0;
856 cFYI(1,("sync page %p",page));
857 mapping = page->mapping;
860 inode = mapping->host;
864 /* fill in rpages then
865 result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
867 /* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
875 * As file closes, flush all cached write data for this inode checking
876 * for write behind errors.
879 int cifs_flush(struct file *file)
881 struct inode * inode = file->f_dentry->d_inode;
884 /* Rather than do the steps manually: */
885 /* lock the inode for writing */
886 /* loop through pages looking for write behind data (dirty pages) */
887 /* coalesce into contiguous 16K (or smaller) chunks to write to server */
888 /* send to server (prefer in parallel) */
889 /* deal with writebehind errors */
890 /* unlock inode for writing */
891 /* filemapfdatawrite appears easier for the time being */
893 rc = filemap_fdatawrite(inode->i_mapping);
894 if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
895 CIFS_I(inode)->write_behind_rc = 0;
897 cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
904 cifs_read(struct file * file, char *read_data, size_t read_size,
908 unsigned int bytes_read = 0;
909 unsigned int total_read;
910 unsigned int current_read_size;
911 struct cifs_sb_info *cifs_sb;
912 struct cifsTconInfo *pTcon;
914 char * current_offset;
915 struct cifsFileInfo * open_file;
918 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
919 pTcon = cifs_sb->tcon;
921 if (file->private_data == NULL) {
925 open_file = (struct cifsFileInfo *)file->private_data;
927 for (total_read = 0,current_offset=read_data; read_size > total_read;
928 total_read += bytes_read,current_offset+=bytes_read) {
929 current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
931 while(rc == -EAGAIN) {
932 if ((open_file->invalidHandle) && (!open_file->closePend)) {
933 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
938 rc = CIFSSMBRead(xid, pTcon,
940 current_read_size, *poffset,
941 &bytes_read, ¤t_offset);
943 if (rc || (bytes_read == 0)) {
951 #ifdef CONFIG_CIFS_STATS
952 atomic_inc(&pTcon->num_reads);
953 spin_lock(&pTcon->stat_lock);
954 pTcon->bytes_read += total_read;
955 spin_unlock(&pTcon->stat_lock);
957 *poffset += bytes_read;
964 int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
966 struct dentry * dentry = file->f_dentry;
970 rc = cifs_revalidate(dentry);
972 cFYI(1,("Validation prior to mmap failed, error=%d", rc));
976 rc = generic_file_mmap(file, vma);
981 static void cifs_copy_cache_pages(struct address_space *mapping,
982 struct list_head *pages, int bytes_read,
983 char *data,struct pagevec * plru_pvec)
988 while (bytes_read > 0) {
989 if(list_empty(pages))
992 page = list_entry(pages->prev, struct page, lru);
993 list_del(&page->lru);
995 if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
996 page_cache_release(page);
997 cFYI(1,("Add page cache failed"));
1001 target = kmap_atomic(page,KM_USER0);
1003 if(PAGE_CACHE_SIZE > bytes_read) {
1004 memcpy(target,data,bytes_read);
1005 /* zero the tail end of this partial page */
1006 memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
1009 memcpy(target,data,PAGE_CACHE_SIZE);
1010 bytes_read -= PAGE_CACHE_SIZE;
1012 kunmap_atomic(target,KM_USER0);
1014 flush_dcache_page(page);
1015 SetPageUptodate(page);
1017 if (!pagevec_add(plru_pvec, page))
1018 __pagevec_lru_add(plru_pvec);
1019 data += PAGE_CACHE_SIZE;
1026 cifs_readpages(struct file *file, struct address_space *mapping,
1027 struct list_head *page_list, unsigned num_pages)
1033 struct cifs_sb_info *cifs_sb;
1034 struct cifsTconInfo *pTcon;
1036 unsigned int read_size,i;
1037 char * smb_read_data = 0;
1038 struct smb_com_read_rsp * pSMBr;
1039 struct pagevec lru_pvec;
1040 struct cifsFileInfo * open_file;
1043 if (file->private_data == NULL) {
1047 open_file = (struct cifsFileInfo *)file->private_data;
1048 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1049 pTcon = cifs_sb->tcon;
1051 pagevec_init(&lru_pvec, 0);
1053 for(i = 0;i<num_pages;) {
1054 unsigned contig_pages;
1055 struct page * tmp_page;
1056 unsigned long expected_index;
1058 if(list_empty(page_list)) {
1061 page = list_entry(page_list->prev, struct page, lru);
1062 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1064 /* count adjacent pages that we will read into */
1066 expected_index = list_entry(page_list->prev,struct page,lru)->index;
1067 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1068 if(tmp_page->index == expected_index) {
1075 if(contig_pages + i > num_pages) {
1076 contig_pages = num_pages - i;
1079 /* for reads over a certain size could initiate async read ahead */
1081 read_size = contig_pages * PAGE_CACHE_SIZE;
1082 /* Read size needs to be in multiples of one page */
1083 read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
1086 while(rc == -EAGAIN) {
1087 if ((open_file->invalidHandle) && (!open_file->closePend)) {
1088 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
1093 rc = CIFSSMBRead(xid, pTcon,
1096 &bytes_read, &smb_read_data);
1097 /* BB need to check return code here */
1100 cifs_buf_release(smb_read_data);
1105 if ((rc < 0) || (smb_read_data == NULL)) {
1106 cFYI(1,("Read error in readpages: %d",rc));
1107 /* clean up remaing pages off list */
1108 while (!list_empty(page_list) && (i < num_pages)) {
1109 page = list_entry(page_list->prev, struct page, lru);
1110 list_del(&page->lru);
1111 page_cache_release(page);
1114 } else if (bytes_read > 0) {
1115 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1116 cifs_copy_cache_pages(mapping, page_list, bytes_read,
1117 smb_read_data + 4 /* RFC1001 hdr */ +
1118 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1120 i += bytes_read >> PAGE_CACHE_SHIFT;
1121 #ifdef CONFIG_CIFS_STATS
1122 atomic_inc(&pTcon->num_reads);
1123 spin_lock(&pTcon->stat_lock);
1124 pTcon->bytes_read += bytes_read;
1125 spin_unlock(&pTcon->stat_lock);
1127 if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1128 cFYI(1,("Partial page %d of %d read to cache",i++,num_pages));
1130 i++; /* account for partial page */
1132 /* server copy of file can have smaller size than client */
1133 /* BB do we need to verify this common case ? this case is ok -
1134 if we are at server EOF we will hit it on next read */
1136 /* while(!list_empty(page_list) && (i < num_pages)) {
1137 page = list_entry(page_list->prev,struct page, list);
1138 list_del(&page->list);
1139 page_cache_release(page);
1144 cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset));
1145 /* BB turn off caching and do new lookup on file size at server? */
1146 while (!list_empty(page_list) && (i < num_pages)) {
1147 page = list_entry(page_list->prev, struct page, lru);
1148 list_del(&page->lru);
1149 page_cache_release(page); /* BB removeme - replace with zero of page? */
1154 cifs_buf_release(smb_read_data);
1160 pagevec_lru_add(&lru_pvec);
1162 /* need to free smb_read_data buf before exit */
1164 cifs_buf_release(smb_read_data);
1173 cifs_readpage(struct file *file, struct page *page)
1175 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1182 if (file->private_data == NULL) {
1187 cFYI(0,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
1189 page_cache_get(page);
1190 read_data = kmap(page);
1191 /* for reads over a certain size could initiate async read ahead */
1193 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, &offset);
1198 cFYI(1,("Bytes read %d ",rc));
1201 file->f_dentry->d_inode->i_atime = CURRENT_TIME;
1203 if(PAGE_CACHE_SIZE > rc) {
1204 memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
1206 flush_dcache_page(page);
1207 SetPageUptodate(page);
1214 page_cache_release(page);
1220 fill_in_inode(struct inode *tmp_inode,
1221 FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
1223 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
1224 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
1226 pfindData->ExtFileAttributes =
1227 le32_to_cpu(pfindData->ExtFileAttributes);
1228 pfindData->AllocationSize = le64_to_cpu(pfindData->AllocationSize);
1229 pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
1230 cifsInfo->cifsAttrs = pfindData->ExtFileAttributes;
1231 cifsInfo->time = jiffies;
1233 /* Linux can not store file creation time unfortunately so ignore it */
1234 tmp_inode->i_atime =
1235 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
1236 tmp_inode->i_mtime =
1237 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
1238 tmp_inode->i_ctime =
1239 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
1240 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
1241 /* 2767 perms - indicate mandatory locking */
1242 /* BB fill in uid and gid here? with help from winbind?
1243 or retrieve from NTFS stream extended attribute */
1244 if(atomic_read(&cifsInfo->inUse) == 0) {
1245 tmp_inode->i_uid = cifs_sb->mnt_uid;
1246 tmp_inode->i_gid = cifs_sb->mnt_gid;
1247 /* set default mode. will override for dirs below */
1248 tmp_inode->i_mode = cifs_sb->mnt_file_mode;
1252 ("CIFS FFIRST: Attributes came in as 0x%x",
1253 pfindData->ExtFileAttributes));
1254 if (pfindData->ExtFileAttributes & ATTR_REPARSE) {
1255 *pobject_type = DT_LNK;
1256 /* BB can this and S_IFREG or S_IFDIR be set as in Windows? */
1257 tmp_inode->i_mode |= S_IFLNK;
1258 } else if (pfindData->ExtFileAttributes & ATTR_DIRECTORY) {
1259 *pobject_type = DT_DIR;
1260 /* override default perms since we do not lock dirs */
1261 if(atomic_read(&cifsInfo->inUse) == 0) {
1262 tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
1264 tmp_inode->i_mode |= S_IFDIR;
1266 *pobject_type = DT_REG;
1267 tmp_inode->i_mode |= S_IFREG;
1268 if(pfindData->ExtFileAttributes & ATTR_READONLY)
1269 tmp_inode->i_mode &= ~(S_IWUGO);
1271 }/* could add code here - to validate if device or weird share type? */
1273 /* can not fill in nlink here as in qpathinfo version and Unx search */
1274 if(atomic_read(&cifsInfo->inUse) == 0) {
1275 atomic_set(&cifsInfo->inUse,1);
1278 i_size_write(tmp_inode,pfindData->EndOfFile);
1279 tmp_inode->i_blocks =
1280 (tmp_inode->i_blksize - 1 + pfindData->AllocationSize) >> tmp_inode->i_blkbits;
1281 if (pfindData->AllocationSize < pfindData->EndOfFile)
1282 cFYI(1, ("Possible sparse file: allocation size less than end of file "));
1284 ("File Size %ld and blocks %ld and blocksize %ld",
1285 (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
1286 tmp_inode->i_blksize));
1287 if (S_ISREG(tmp_inode->i_mode)) {
1288 cFYI(1, (" File inode "));
1289 tmp_inode->i_op = &cifs_file_inode_ops;
1290 tmp_inode->i_fop = &cifs_file_ops;
1291 tmp_inode->i_data.a_ops = &cifs_addr_ops;
1292 } else if (S_ISDIR(tmp_inode->i_mode)) {
1293 cFYI(1, (" Directory inode"));
1294 tmp_inode->i_op = &cifs_dir_inode_ops;
1295 tmp_inode->i_fop = &cifs_dir_ops;
1296 } else if (S_ISLNK(tmp_inode->i_mode)) {
1297 cFYI(1, (" Symbolic Link inode "));
1298 tmp_inode->i_op = &cifs_symlink_inode_ops;
1300 cFYI(1, (" Init special inode "));
1301 init_special_inode(tmp_inode, tmp_inode->i_mode,
1307 unix_fill_in_inode(struct inode *tmp_inode,
1308 FILE_UNIX_INFO * pfindData, int *pobject_type)
1310 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
1311 cifsInfo->time = jiffies;
1312 atomic_inc(&cifsInfo->inUse);
1314 tmp_inode->i_atime =
1315 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
1316 tmp_inode->i_mtime =
1317 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
1318 tmp_inode->i_ctime =
1319 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
1321 tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
1322 pfindData->Type = le32_to_cpu(pfindData->Type);
1323 if (pfindData->Type == UNIX_FILE) {
1324 *pobject_type = DT_REG;
1325 tmp_inode->i_mode |= S_IFREG;
1326 } else if (pfindData->Type == UNIX_SYMLINK) {
1327 *pobject_type = DT_LNK;
1328 tmp_inode->i_mode |= S_IFLNK;
1329 } else if (pfindData->Type == UNIX_DIR) {
1330 *pobject_type = DT_DIR;
1331 tmp_inode->i_mode |= S_IFDIR;
1332 } else if (pfindData->Type == UNIX_CHARDEV) {
1333 *pobject_type = DT_CHR;
1334 tmp_inode->i_mode |= S_IFCHR;
1335 } else if (pfindData->Type == UNIX_BLOCKDEV) {
1336 *pobject_type = DT_BLK;
1337 tmp_inode->i_mode |= S_IFBLK;
1338 } else if (pfindData->Type == UNIX_FIFO) {
1339 *pobject_type = DT_FIFO;
1340 tmp_inode->i_mode |= S_IFIFO;
1341 } else if (pfindData->Type == UNIX_SOCKET) {
1342 *pobject_type = DT_SOCK;
1343 tmp_inode->i_mode |= S_IFSOCK;
1346 tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
1347 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
1348 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
1350 pfindData->NumOfBytes = le64_to_cpu(pfindData->NumOfBytes);
1351 pfindData->EndOfFile = le64_to_cpu(pfindData->EndOfFile);
1352 i_size_write(tmp_inode,pfindData->EndOfFile);
1353 tmp_inode->i_blocks =
1354 (tmp_inode->i_blksize - 1 + pfindData->NumOfBytes) >> tmp_inode->i_blkbits;
1356 if (S_ISREG(tmp_inode->i_mode)) {
1357 cFYI(1, ("File inode"));
1358 tmp_inode->i_op = &cifs_file_inode_ops;
1359 tmp_inode->i_fop = &cifs_file_ops;
1360 tmp_inode->i_data.a_ops = &cifs_addr_ops;
1361 } else if (S_ISDIR(tmp_inode->i_mode)) {
1362 cFYI(1, ("Directory inode"));
1363 tmp_inode->i_op = &cifs_dir_inode_ops;
1364 tmp_inode->i_fop = &cifs_dir_ops;
1365 } else if (S_ISLNK(tmp_inode->i_mode)) {
1366 cFYI(1, ("Symbolic Link inode"));
1367 tmp_inode->i_op = &cifs_symlink_inode_ops;
1368 /* tmp_inode->i_fop = *//* do not need to set to anything */
1370 cFYI(1, ("Special inode"));
1371 init_special_inode(tmp_inode, tmp_inode->i_mode,
1377 construct_dentry(struct qstr *qstring, struct file *file,
1378 struct inode **ptmp_inode, struct dentry **pnew_dentry)
1380 struct dentry *tmp_dentry;
1381 struct cifs_sb_info *cifs_sb;
1382 struct cifsTconInfo *pTcon;
1384 cFYI(1, ("For %s ", qstring->name));
1385 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1386 pTcon = cifs_sb->tcon;
1388 qstring->hash = full_name_hash(qstring->name, qstring->len);
1389 tmp_dentry = d_lookup(file->f_dentry, qstring);
1391 cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
1392 *ptmp_inode = tmp_dentry->d_inode;
1393 /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
1394 if(*ptmp_inode == NULL) {
1395 *ptmp_inode = new_inode(file->f_dentry->d_sb);
1396 d_instantiate(tmp_dentry, *ptmp_inode);
1399 tmp_dentry = d_alloc(file->f_dentry, qstring);
1400 if(tmp_dentry == NULL) {
1401 cERROR(1,("Failed allocating dentry"));
1405 *ptmp_inode = new_inode(file->f_dentry->d_sb);
1406 tmp_dentry->d_op = &cifs_dentry_ops;
1407 cFYI(0, (" instantiate dentry 0x%p with inode 0x%p ",
1408 tmp_dentry, *ptmp_inode));
1409 d_instantiate(tmp_dentry, *ptmp_inode);
1410 d_rehash(tmp_dentry);
1413 tmp_dentry->d_time = jiffies;
1414 *pnew_dentry = tmp_dentry;
1417 static void reset_resume_key(struct file * dir_file,
1418 unsigned char * filename,
1419 unsigned int len,int Unicode,struct nls_table * nls_tab) {
1420 struct cifsFileInfo *cifsFile;
1422 cifsFile = (struct cifsFileInfo *)dir_file->private_data;
1423 if(cifsFile == NULL)
1425 if(cifsFile->search_resume_name) {
1426 kfree(cifsFile->search_resume_name);
1431 cifsFile->resume_name_length = len;
1433 cifsFile->search_resume_name =
1434 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1436 if(cifsFile->search_resume_name == NULL) {
1437 cERROR(1,("failed new resume key allocate, length %d",
1438 cifsFile->resume_name_length));
1442 cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
1443 filename, len, nls_tab);
1445 memcpy(cifsFile->search_resume_name, filename,
1446 cifsFile->resume_name_length);
1447 cFYI(1,("Reset resume key to: %s with len %d",filename,len));
1454 cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
1455 struct file *file, filldir_t filldir, void *direntry)
1457 struct inode *tmp_inode;
1458 struct dentry *tmp_dentry;
1461 pqstring->name = pfindData->FileName;
1462 pqstring->len = pfindData->FileNameLength;
1464 construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
1466 fill_in_inode(tmp_inode, pfindData, &object_type);
1467 rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
1468 tmp_inode->i_ino, object_type);
1470 /* due to readdir error we need to recalculate resume
1471 key so next readdir will restart on right entry */
1472 cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
1479 cifs_filldir_unix(struct qstr *pqstring,
1480 FILE_UNIX_INFO * pUnixFindData, struct file *file,
1481 filldir_t filldir, void *direntry)
1483 struct inode *tmp_inode;
1484 struct dentry *tmp_dentry;
1485 int object_type, rc;
1487 pqstring->name = pUnixFindData->FileName;
1488 pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
1490 construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
1492 unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
1493 rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
1494 file->f_pos, tmp_inode->i_ino, object_type);
1496 /* due to readdir error we need to recalculate resume
1497 key so next readdir will restart on right entry */
1498 cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
1505 cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
1509 int Unicode = FALSE;
1510 int UnixSearch = FALSE;
1511 unsigned int bufsize, i;
1513 struct cifs_sb_info *cifs_sb;
1514 struct cifsTconInfo *pTcon;
1515 struct cifsFileInfo *cifsFile = NULL;
1516 char *full_path = NULL;
1518 struct qstr qstring;
1519 T2_FFIRST_RSP_PARMS findParms;
1520 T2_FNEXT_RSP_PARMS findNextParms;
1521 FILE_DIRECTORY_INFO *pfindData;
1522 FILE_DIRECTORY_INFO *lastFindData;
1523 FILE_UNIX_INFO *pfindDataUnix;
1527 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1528 pTcon = cifs_sb->tcon;
1529 bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
1530 if(bufsize > CIFS_MAX_MSGSIZE) {
1534 data = kmalloc(bufsize, GFP_KERNEL);
1535 pfindData = (FILE_DIRECTORY_INFO *) data;
1537 full_path = build_wildcard_path_from_dentry(file->f_dentry);
1539 cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
1541 switch ((int) file->f_pos) {
1543 if (filldir(direntry, ".", 1, file->f_pos,
1544 file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
1545 cERROR(1, ("Filldir for current dir failed "));
1551 if (filldir(direntry, "..", 2, file->f_pos,
1552 file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
1553 cERROR(1, ("Filldir for parent dir failed "));
1559 if (file->private_data != NULL) {
1561 (struct cifsFileInfo *) file->private_data;
1562 if (cifsFile->endOfSearch) {
1563 if(cifsFile->emptyDir) {
1564 cFYI(1, ("End of search, empty dir"));
1569 cifsFile->invalidHandle = TRUE;
1570 CIFSFindClose(xid, pTcon, cifsFile->netfid);
1572 if(cifsFile->search_resume_name) {
1573 kfree(cifsFile->search_resume_name);
1574 cifsFile->search_resume_name = NULL;
1577 rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
1578 &findParms, cifs_sb->local_nls,
1579 &Unicode, &UnixSearch);
1580 cFYI(1, ("Count: %d End: %d ", findParms.SearchCount,
1581 findParms.EndofSearch));
1584 searchHandle = findParms.SearchHandle;
1585 if(file->private_data == NULL)
1586 file->private_data =
1587 kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
1588 if (file->private_data) {
1589 memset(file->private_data, 0,
1590 sizeof (struct cifsFileInfo));
1592 (struct cifsFileInfo *) file->private_data;
1593 cifsFile->netfid = searchHandle;
1594 cifsFile->invalidHandle = FALSE;
1595 init_MUTEX(&cifsFile->fh_sem);
1601 renew_parental_timestamps(file->f_dentry);
1603 (FILE_DIRECTORY_INFO *) ((char *) pfindData +
1604 findParms.LastNameOffset);
1605 if((char *)lastFindData > (char *)pfindData + bufsize) {
1606 cFYI(1,("last search entry past end of packet"));
1610 /* Offset of resume key same for levels 257 and 514 */
1611 cifsFile->resume_key = lastFindData->FileIndex;
1612 if(UnixSearch == FALSE) {
1613 cifsFile->resume_name_length =
1614 le32_to_cpu(lastFindData->FileNameLength);
1615 if(cifsFile->resume_name_length > bufsize - 64) {
1616 cFYI(1,("Illegal resume file name length %d",
1617 cifsFile->resume_name_length));
1621 cifsFile->search_resume_name =
1622 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1623 cFYI(1,("Last file: %s with name %d bytes long",
1624 lastFindData->FileName,
1625 cifsFile->resume_name_length));
1626 memcpy(cifsFile->search_resume_name,
1627 lastFindData->FileName,
1628 cifsFile->resume_name_length);
1630 pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
1631 if (Unicode == TRUE) {
1632 for(i=0;(pfindDataUnix->FileName[i]
1633 | pfindDataUnix->FileName[i+1]);
1638 cifsFile->resume_name_length = i + 2;
1640 cifsFile->resume_name_length =
1641 strnlen(pfindDataUnix->FileName,
1644 if(cifsFile->resume_name_length > bufsize - 64) {
1645 cFYI(1,("Illegal resume file name length %d",
1646 cifsFile->resume_name_length));
1650 cifsFile->search_resume_name =
1651 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1652 cFYI(1,("Last file: %s with name %d bytes long",
1653 pfindDataUnix->FileName,
1654 cifsFile->resume_name_length));
1655 memcpy(cifsFile->search_resume_name,
1656 pfindDataUnix->FileName,
1657 cifsFile->resume_name_length);
1659 for (i = 2; i < (unsigned int)findParms.SearchCount + 2; i++) {
1660 if (UnixSearch == FALSE) {
1661 pfindData->FileNameLength =
1662 le32_to_cpu(pfindData->FileNameLength);
1663 if (Unicode == TRUE)
1664 pfindData->FileNameLength =
1666 (pfindData->FileName,
1668 pfindData->FileName,
1670 FileNameLength) / 2,
1671 cifs_sb->local_nls);
1672 qstring.len = pfindData->FileNameLength;
1673 if (((qstring.len != 1)
1674 || (pfindData->FileName[0] != '.'))
1675 && ((qstring.len != 2)
1679 FileName[1] != '.'))) {
1680 if(cifs_filldir(&qstring,
1684 /* do not end search if
1685 kernel not ready to take
1686 remaining entries yet */
1687 reset_resume_key(file, pfindData->FileName,qstring.len,
1688 Unicode, cifs_sb->local_nls);
1689 findParms.EndofSearch = 0;
1694 } else { /* UnixSearch */
1696 (FILE_UNIX_INFO *) pfindData;
1697 if (Unicode == TRUE)
1700 (pfindDataUnix->FileName,
1702 pfindDataUnix->FileName,
1704 cifs_sb->local_nls);
1707 strnlen(pfindDataUnix->
1710 if (((qstring.len != 1)
1712 FileName[0] != '.'))
1713 && ((qstring.len != 2)
1717 FileName[1] != '.'))) {
1718 if(cifs_filldir_unix(&qstring,
1723 /* do not end search if
1724 kernel not ready to take
1725 remaining entries yet */
1726 findParms.EndofSearch = 0;
1727 reset_resume_key(file, pfindDataUnix->FileName,
1728 qstring.len,Unicode,cifs_sb->local_nls);
1734 /* works also for Unix ff struct since first field of both */
1736 (FILE_DIRECTORY_INFO *) ((char *) pfindData
1737 + le32_to_cpu(pfindData->NextEntryOffset));
1738 /* BB also should check to make sure that pointer is not beyond the end of the SMB */
1739 /* if(pfindData > lastFindData) rc = -EIO; break; */
1740 } /* end for loop */
1741 if ((findParms.EndofSearch != 0) && cifsFile) {
1742 cifsFile->endOfSearch = TRUE;
1743 if(findParms.SearchCount == 2)
1744 cifsFile->emptyDir = TRUE;
1748 cifsFile->endOfSearch = TRUE;
1749 /* unless parent directory gone do not return error */
1754 if (file->private_data == NULL) {
1757 ("Readdir on closed srch, pos = %lld",
1760 cifsFile = (struct cifsFileInfo *) file->private_data;
1761 if (cifsFile->endOfSearch) {
1763 cFYI(1, ("End of search "));
1766 searchHandle = cifsFile->netfid;
1767 rc = CIFSFindNext(xid, pTcon, pfindData,
1768 &findNextParms, searchHandle,
1769 cifsFile->search_resume_name,
1770 cifsFile->resume_name_length,
1771 cifsFile->resume_key,
1772 &Unicode, &UnixSearch);
1773 cFYI(1,("Count: %d End: %d ",
1774 findNextParms.SearchCount,
1775 findNextParms.EndofSearch));
1776 if ((rc == 0) && (findNextParms.SearchCount != 0)) {
1777 /* BB save off resume key, key name and name length */
1779 (FILE_DIRECTORY_INFO *) ((char *) pfindData
1780 + findNextParms.LastNameOffset);
1781 if((char *)lastFindData > (char *)pfindData + bufsize) {
1782 cFYI(1,("last search entry past end of packet"));
1786 /* Offset of resume key same for levels 257 and 514 */
1787 cifsFile->resume_key = lastFindData->FileIndex;
1789 if(UnixSearch == FALSE) {
1790 cifsFile->resume_name_length =
1791 le32_to_cpu(lastFindData->FileNameLength);
1792 if(cifsFile->resume_name_length > bufsize - 64) {
1793 cFYI(1,("Illegal resume file name length %d",
1794 cifsFile->resume_name_length));
1798 /* Free the memory allocated by previous findfirst
1799 or findnext call - we can not reuse the memory since
1800 the resume name may not be same string length */
1801 if(cifsFile->search_resume_name)
1802 kfree(cifsFile->search_resume_name);
1803 cifsFile->search_resume_name =
1804 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1805 cFYI(1,("Last file: %s with name %d bytes long",
1806 lastFindData->FileName,
1807 cifsFile->resume_name_length));
1808 memcpy(cifsFile->search_resume_name,
1809 lastFindData->FileName,
1810 cifsFile->resume_name_length);
1812 pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
1813 if (Unicode == TRUE) {
1814 for(i=0;(pfindDataUnix->FileName[i]
1815 | pfindDataUnix->FileName[i+1]);
1820 cifsFile->resume_name_length = i + 2;
1822 cifsFile->resume_name_length =
1823 strnlen(pfindDataUnix->
1827 if(cifsFile->resume_name_length > bufsize - 64) {
1828 cFYI(1,("Illegal resume file name length %d",
1829 cifsFile->resume_name_length));
1833 /* Free the memory allocated by previous findfirst
1834 or findnext call - we can not reuse the memory since
1835 the resume name may not be same string length */
1836 if(cifsFile->search_resume_name)
1837 kfree(cifsFile->search_resume_name);
1838 cifsFile->search_resume_name =
1839 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1840 cFYI(1,("fnext last file: %s with name %d bytes long",
1841 pfindDataUnix->FileName,
1842 cifsFile->resume_name_length));
1843 memcpy(cifsFile->search_resume_name,
1844 pfindDataUnix->FileName,
1845 cifsFile->resume_name_length);
1848 for (i = 0; i < findNextParms.SearchCount; i++) {
1849 pfindData->FileNameLength =
1850 le32_to_cpu(pfindData->
1852 if (UnixSearch == FALSE) {
1853 if (Unicode == TRUE)
1854 pfindData->FileNameLength =
1856 (pfindData->FileName,
1858 pfindData->FileName,
1859 (pfindData->FileNameLength)/ 2,
1860 cifs_sb->local_nls);
1862 pfindData->FileNameLength;
1863 if (((qstring.len != 1)
1864 || (pfindData->FileName[0] != '.'))
1865 && ((qstring.len != 2)
1866 || (pfindData->FileName[0] != '.')
1867 || (pfindData->FileName[1] !=
1874 /* do not end search if
1875 kernel not ready to take
1876 remaining entries yet */
1877 findNextParms.EndofSearch = 0;
1878 reset_resume_key(file, pfindData->FileName,qstring.len,
1879 Unicode,cifs_sb->local_nls);
1884 } else { /* UnixSearch */
1888 if (Unicode == TRUE)
1891 (pfindDataUnix->FileName,
1893 pfindDataUnix->FileName,
1895 cifs_sb->local_nls);
1902 if (((qstring.len != 1)
1904 FileName[0] != '.'))
1905 && ((qstring.len != 2)
1911 if(cifs_filldir_unix
1916 /* do not end search if
1917 kernel not ready to take
1918 remaining entries yet */
1919 findNextParms.EndofSearch = 0;
1920 reset_resume_key(file, pfindDataUnix->FileName,qstring.len,
1921 Unicode,cifs_sb->local_nls);
1927 pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData +
1928 le32_to_cpu(pfindData->NextEntryOffset));
1929 /* works also for Unix find struct since first field of both */
1930 /* BB also should check to ensure pointer not beyond end of SMB */
1931 } /* end for loop */
1932 if (findNextParms.EndofSearch != 0) {
1933 cifsFile->endOfSearch = TRUE;
1936 cifsFile->endOfSearch = TRUE;
1937 rc = 0; /* unless parent directory disappeared - do not
1938 return error here (eg Access Denied or no more files) */
1950 int cifs_prepare_write(struct file *file, struct page *page,
1951 unsigned from, unsigned to)
1953 cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
1954 if (!PageUptodate(page)) {
1955 if (to - from != PAGE_CACHE_SIZE) {
1956 void *kaddr = kmap_atomic(page, KM_USER0);
1957 memset(kaddr, 0, from);
1958 memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
1959 flush_dcache_page(page);
1960 kunmap_atomic(kaddr, KM_USER0);
1962 SetPageUptodate(page);
1968 struct address_space_operations cifs_addr_ops = {
1969 .readpage = cifs_readpage,
1970 .readpages = cifs_readpages,
1971 .writepage = cifs_writepage,
1972 .prepare_write = simple_prepare_write, /* BB fixme BB */
1973 /* .prepare_write = cifs_prepare_write, */ /* BB removeme BB */
1974 .commit_write = cifs_commit_write,
1975 /* .sync_page = cifs_sync_page, */