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"
38 extern int cifs_readdir2(struct file *file, void *direntry, filldir_t filldir); /* BB removeme BB */
41 cifs_open(struct inode *inode, struct file *file)
45 struct cifs_sb_info *cifs_sb;
46 struct cifsTconInfo *pTcon;
47 struct cifsFileInfo *pCifsFile;
48 struct cifsInodeInfo *pCifsInode;
49 struct list_head * tmp;
50 char *full_path = NULL;
51 int desiredAccess = 0x20197;
54 FILE_ALL_INFO * buf = NULL;
58 cifs_sb = CIFS_SB(inode->i_sb);
59 pTcon = cifs_sb->tcon;
61 if (file->f_flags & O_CREAT) {
62 /* search inode for this file and fill in file->private_data = */
63 pCifsInode = CIFS_I(file->f_dentry->d_inode);
64 read_lock(&GlobalSMBSeslock);
65 list_for_each(tmp, &pCifsInode->openFileList) {
66 pCifsFile = list_entry(tmp,struct cifsFileInfo, flist);
67 if((pCifsFile->pfile == NULL)&& (pCifsFile->pid == current->tgid)){
68 /* mode set in cifs_create */
69 pCifsFile->pfile = file; /* needed for writepage */
70 file->private_data = pCifsFile;
74 read_unlock(&GlobalSMBSeslock);
75 if(file->private_data != NULL) {
80 if(file->f_flags & O_EXCL)
81 cERROR(1,("could not find file instance for new file %p ",file));
85 down(&inode->i_sb->s_vfs_rename_sem);
86 full_path = build_path_from_dentry(file->f_dentry);
87 up(&inode->i_sb->s_vfs_rename_sem);
88 if(full_path == NULL) {
93 cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
94 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
95 desiredAccess = GENERIC_READ;
96 else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
97 desiredAccess = GENERIC_WRITE;
98 else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
99 /* GENERIC_ALL is too much permission to request */
100 /* can cause unnecessary access denied on create */
101 /* desiredAccess = GENERIC_ALL; */
102 desiredAccess = GENERIC_READ | GENERIC_WRITE;
105 /*********************************************************************
106 * open flag mapping table:
108 * POSIX Flag CIFS Disposition
109 * ---------- ----------------
110 * O_CREAT FILE_OPEN_IF
111 * O_CREAT | O_EXCL FILE_CREATE
112 * O_CREAT | O_TRUNC FILE_OVERWRITE_IF
113 * O_TRUNC FILE_OVERWRITE
114 * none of the above FILE_OPEN
116 * Note that there is not a direct match between disposition
117 * FILE_SUPERSEDE (ie create whether or not file exists although
118 * O_CREAT | O_TRUNC is similar but truncates the existing
119 * file rather than creating a new file as FILE_SUPERSEDE does
120 * (which uses the attributes / metadata passed in on open call)
122 *? O_SYNC is a reasonable match to CIFS writethrough flag
123 *? and the read write flags match reasonably. O_LARGEFILE
124 *? is irrelevant because largefile support is always used
125 *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY,
126 * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation
127 *********************************************************************/
129 if((file->f_flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
130 disposition = FILE_CREATE;
131 else if((file->f_flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
132 disposition = FILE_OVERWRITE_IF;
133 else if((file->f_flags & O_CREAT) == O_CREAT)
134 disposition = FILE_OPEN_IF;
136 disposition = FILE_OPEN;
143 /* BB pass O_SYNC flag through on file attributes .. BB */
145 /* Also refresh inode by passing in file_info buf returned by SMBOpen
146 and calling get_inode_info with returned buf (at least
147 helps non-Unix server case */
149 /* BB we can not do this if this is the second open of a file
150 and the first handle has writebehind data, we might be
151 able to simply do a filemap_fdatawrite/filemap_fdatawait first */
152 buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
159 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
160 CREATE_NOT_DIR, &netfid, &oplock, buf, cifs_sb->local_nls);
162 cFYI(1, ("cifs_open returned 0x%x ", rc));
163 cFYI(1, ("oplock: %d ", oplock));
166 kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
167 if (file->private_data) {
168 memset(file->private_data, 0, sizeof(struct cifsFileInfo));
169 pCifsFile = (struct cifsFileInfo *) file->private_data;
170 pCifsFile->netfid = netfid;
171 pCifsFile->pid = current->tgid;
172 init_MUTEX(&pCifsFile->fh_sem);
173 pCifsFile->pfile = file; /* needed for writepage */
174 pCifsFile->pInode = inode;
175 pCifsFile->invalidHandle = FALSE;
176 pCifsFile->closePend = FALSE;
177 write_lock(&file->f_owner.lock);
178 write_lock(&GlobalSMBSeslock);
179 list_add(&pCifsFile->tlist,&pTcon->openFileList);
180 pCifsInode = CIFS_I(file->f_dentry->d_inode);
182 /* want handles we can use to read with first */
183 /* in the list so we do not have to walk the */
184 /* list to search for one in prepare_write */
185 if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
186 list_add_tail(&pCifsFile->flist,&pCifsInode->openFileList);
188 list_add(&pCifsFile->flist,&pCifsInode->openFileList);
190 write_unlock(&GlobalSMBSeslock);
191 write_unlock(&file->f_owner.lock);
192 if(pCifsInode->clientCanCacheRead) {
193 /* we have the inode open somewhere else
194 no need to discard cache data */
197 /* BB need same check in cifs_create too? */
199 /* if not oplocked, invalidate inode pages if mtime
200 or file size changed */
201 struct timespec temp;
202 temp = cifs_NTtimeToUnix(le64_to_cpu(buf->LastWriteTime));
203 if(timespec_equal(&file->f_dentry->d_inode->i_mtime,&temp) &&
204 (file->f_dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) {
205 cFYI(1,("inode unchanged on server"));
207 if(file->f_dentry->d_inode->i_mapping) {
208 /* BB no need to lock inode until after invalidate*/
209 /* since namei code should already have it locked?*/
210 filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
211 filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
213 cFYI(1,("invalidating remote inode since open detected it changed"));
214 invalidate_remote_inode(file->f_dentry->d_inode);
218 if (pTcon->ses->capabilities & CAP_UNIX)
219 rc = cifs_get_inode_info_unix(&file->f_dentry->d_inode,
220 full_path, inode->i_sb,xid);
222 rc = cifs_get_inode_info(&file->f_dentry->d_inode,
223 full_path, buf, inode->i_sb,xid);
225 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
226 pCifsInode->clientCanCacheAll = TRUE;
227 pCifsInode->clientCanCacheRead = TRUE;
228 cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
229 } else if((oplock & 0xF) == OPLOCK_READ)
230 pCifsInode->clientCanCacheRead = TRUE;
232 write_unlock(&GlobalSMBSeslock);
233 write_unlock(&file->f_owner.lock);
235 if(oplock & CIFS_CREATE_ACTION) {
236 /* time to set mode which we can not set earlier due
237 to problems creating new read-only files */
238 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
239 CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode,
244 else {/* BB implement via Windows security descriptors */
245 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
246 /* in the meantime could set r/o dos attribute when perms are eg:
261 /* Try to reaquire byte range locks that were released when session */
262 /* to server was lost */
263 static int cifs_relock_file(struct cifsFileInfo * cifsFile)
267 /* BB list all locks open on this file and relock */
272 static int cifs_reopen_file(struct inode *inode, struct file *file, int can_flush)
276 struct cifs_sb_info *cifs_sb;
277 struct cifsTconInfo *pTcon;
278 struct cifsFileInfo *pCifsFile;
279 struct cifsInodeInfo *pCifsInode;
280 char *full_path = NULL;
281 int desiredAccess = 0x20197;
282 int disposition = FILE_OPEN;
287 if (file->private_data) {
288 pCifsFile = (struct cifsFileInfo *) file->private_data;
293 down(&pCifsFile->fh_sem);
294 if(pCifsFile->invalidHandle == FALSE) {
295 up(&pCifsFile->fh_sem);
300 if(file->f_dentry == NULL) {
301 up(&pCifsFile->fh_sem);
302 cFYI(1,("failed file reopen, no valid name if dentry freed"));
306 cifs_sb = CIFS_SB(inode->i_sb);
307 pTcon = cifs_sb->tcon;
308 /* can not grab rename sem here because various ops, including
309 those that already have the rename sem can end up causing writepage
310 to get called and if the server was down that means we end up here,
311 and we can never tell if the caller already has the rename_sem */
312 full_path = build_path_from_dentry(file->f_dentry);
313 if(full_path == NULL) {
314 up(&pCifsFile->fh_sem);
319 cFYI(1, (" inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags,full_path));
320 if ((file->f_flags & O_ACCMODE) == O_RDONLY)
321 desiredAccess = GENERIC_READ;
322 else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
323 desiredAccess = GENERIC_WRITE;
324 else if ((file->f_flags & O_ACCMODE) == O_RDWR) {
325 /* GENERIC_ALL is too much permission to request */
326 /* can cause unnecessary access denied on create */
327 /* desiredAccess = GENERIC_ALL; */
328 desiredAccess = GENERIC_READ | GENERIC_WRITE;
337 /* Can not refresh inode by passing in file_info buf to be returned
338 by SMBOpen and then calling get_inode_info with returned buf
339 since file might have write behind data that needs to be flushed
340 and server version of file size can be stale. If we
341 knew for sure that inode was not dirty locally we could do this */
343 /* buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
345 up(&pCifsFile->fh_sem);
351 rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
352 CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls);
354 up(&pCifsFile->fh_sem);
355 cFYI(1, ("cifs_open returned 0x%x ", rc));
356 cFYI(1, ("oplock: %d ", oplock));
358 pCifsFile->netfid = netfid;
359 pCifsFile->invalidHandle = FALSE;
360 up(&pCifsFile->fh_sem);
361 pCifsInode = CIFS_I(inode);
364 filemap_fdatawrite(inode->i_mapping);
365 filemap_fdatawait(inode->i_mapping);
366 /* temporarily disable caching while we
367 go to server to get inode info */
368 pCifsInode->clientCanCacheAll = FALSE;
369 pCifsInode->clientCanCacheRead = FALSE;
370 if (pTcon->ses->capabilities & CAP_UNIX)
371 rc = cifs_get_inode_info_unix(&inode,
372 full_path, inode->i_sb,xid);
374 rc = cifs_get_inode_info(&inode,
375 full_path, NULL, inode->i_sb,xid);
376 } /* else we are writing out data to server already
377 and could deadlock if we tried to flush data, and
378 since we do not know if we have data that would
379 invalidate the current end of file on the server
380 we can not go to the server to get the new
382 if((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
383 pCifsInode->clientCanCacheAll = TRUE;
384 pCifsInode->clientCanCacheRead = TRUE;
385 cFYI(1,("Exclusive Oplock granted on inode %p",file->f_dentry->d_inode));
386 } else if((oplock & 0xF) == OPLOCK_READ) {
387 pCifsInode->clientCanCacheRead = TRUE;
388 pCifsInode->clientCanCacheAll = FALSE;
390 pCifsInode->clientCanCacheRead = FALSE;
391 pCifsInode->clientCanCacheAll = FALSE;
393 cifs_relock_file(pCifsFile);
404 cifs_close(struct inode *inode, struct file *file)
408 struct cifs_sb_info *cifs_sb;
409 struct cifsTconInfo *pTcon;
410 struct cifsFileInfo *pSMBFile =
411 (struct cifsFileInfo *) file->private_data;
415 cifs_sb = CIFS_SB(inode->i_sb);
416 pTcon = cifs_sb->tcon;
418 pSMBFile->closePend = TRUE;
419 write_lock(&file->f_owner.lock);
421 /* no sense reconnecting to close a file that is
423 if (pTcon->tidStatus != CifsNeedReconnect) {
424 write_unlock(&file->f_owner.lock);
425 rc = CIFSSMBClose(xid,pTcon,pSMBFile->netfid);
426 write_lock(&file->f_owner.lock);
429 list_del(&pSMBFile->flist);
430 list_del(&pSMBFile->tlist);
431 write_unlock(&file->f_owner.lock);
432 if(pSMBFile->search_resume_name)
433 kfree(pSMBFile->search_resume_name);
434 kfree(file->private_data);
435 file->private_data = NULL;
439 if(list_empty(&(CIFS_I(inode)->openFileList))) {
440 cFYI(1,("closing last open instance for inode %p",inode));
441 /* if the file is not open we do not know if we can cache
442 info on this inode, much less write behind and read ahead */
443 CIFS_I(inode)->clientCanCacheRead = FALSE;
444 CIFS_I(inode)->clientCanCacheAll = FALSE;
446 if((rc ==0) && CIFS_I(inode)->write_behind_rc)
447 rc = CIFS_I(inode)->write_behind_rc;
453 cifs_closedir(struct inode *inode, struct file *file)
457 struct cifsFileInfo *pCFileStruct =
458 (struct cifsFileInfo *) file->private_data;
461 cFYI(1, ("Closedir inode = 0x%p with ", inode));
466 struct cifsTconInfo *pTcon;
467 struct cifs_sb_info * cifs_sb = CIFS_SB(file->f_dentry->d_sb);
469 pTcon = cifs_sb->tcon;
471 cFYI(1, ("Freeing private data in close dir"));
472 if(pCFileStruct->srch_inf.endOfSearch == FALSE) {
473 pCFileStruct->invalidHandle = TRUE;
474 rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
475 cFYI(1,("Closing uncompleted readdir with rc %d",rc));
476 /* not much we can do if it fails anywway, ignore rc */
479 ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
481 cFYI(1,("freeing smb buf in srch struct in closedir")); /* BB removeme BB */
482 pCFileStruct->srch_inf.ntwrk_buf_start = NULL;
483 cifs_buf_release(ptmp);
485 ptmp = pCFileStruct->search_resume_name;
487 cFYI(1,("freeing resume name in closedir")); /* BB removeme BB */
488 pCFileStruct->search_resume_name = NULL;
491 kfree(file->private_data);
492 file->private_data = NULL;
494 /* BB can we lock the filestruct while this is going on? */
500 cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
503 __u32 lockType = LOCKING_ANDX_LARGE_FILES;
507 int wait_flag = FALSE;
508 struct cifs_sb_info *cifs_sb;
509 struct cifsTconInfo *pTcon;
510 length = 1 + pfLock->fl_end - pfLock->fl_start;
517 ("Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld end: %lld",
518 cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start,
521 if (pfLock->fl_flags & FL_POSIX)
523 if (pfLock->fl_flags & FL_FLOCK)
525 if (pfLock->fl_flags & FL_SLEEP) {
526 cFYI(1, ("Blocking lock "));
529 if (pfLock->fl_flags & FL_ACCESS)
530 cFYI(1, ("Process suspended by mandatory locking - not implemented yet "));
531 if (pfLock->fl_flags & FL_LEASE)
532 cFYI(1, ("Lease on file - not implemented yet"));
533 if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE)))
534 cFYI(1, ("Unknown lock flags 0x%x",pfLock->fl_flags));
536 if (pfLock->fl_type == F_WRLCK) {
537 cFYI(1, ("F_WRLCK "));
539 } else if (pfLock->fl_type == F_UNLCK) {
540 cFYI(1, ("F_UNLCK "));
542 } else if (pfLock->fl_type == F_RDLCK) {
543 cFYI(1, ("F_RDLCK "));
544 lockType |= LOCKING_ANDX_SHARED_LOCK;
546 } else if (pfLock->fl_type == F_EXLCK) {
547 cFYI(1, ("F_EXLCK "));
549 } else if (pfLock->fl_type == F_SHLCK) {
550 cFYI(1, ("F_SHLCK "));
551 lockType |= LOCKING_ANDX_SHARED_LOCK;
554 cFYI(1, ("Unknown type of lock "));
556 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
557 pTcon = cifs_sb->tcon;
559 if (file->private_data == NULL) {
565 rc = CIFSSMBLock(xid, pTcon,
566 ((struct cifsFileInfo *) file->
567 private_data)->netfid,
569 pfLock->fl_start, 0, 1, lockType,
572 rc = CIFSSMBLock(xid, pTcon,
573 ((struct cifsFileInfo *) file->
574 private_data)->netfid,
576 pfLock->fl_start, 1 /* numUnlock */ ,
577 0 /* numLock */ , lockType,
579 pfLock->fl_type = F_UNLCK;
582 ("Error unlocking previously locked range %d during test of lock ",
587 /* if rc == ERR_SHARING_VIOLATION ? */
588 rc = 0; /* do not change lock type to unlock since range in use */
595 rc = CIFSSMBLock(xid, pTcon,
596 ((struct cifsFileInfo *) file->private_data)->
598 pfLock->fl_start, numUnlock, numLock, lockType,
600 if (rc == 0 && (pfLock->fl_flags & FL_POSIX))
601 posix_lock_file_wait(file, pfLock);
607 cifs_user_write(struct file * file, const char __user * write_data,
608 size_t write_size, loff_t * poffset)
611 unsigned int bytes_written = 0;
612 unsigned int total_written;
613 struct cifs_sb_info *cifs_sb;
614 struct cifsTconInfo *pTcon;
616 struct cifsFileInfo * open_file;
618 if(file->f_dentry == NULL)
621 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
622 if(cifs_sb == NULL) {
625 pTcon = cifs_sb->tcon;
628 (" write %d bytes to offset %lld of %s", write_size,
629 *poffset, file->f_dentry->d_name.name)); */
631 if (file->private_data == NULL) {
634 open_file = (struct cifsFileInfo *) file->private_data;
638 if(file->f_dentry->d_inode == NULL) {
643 if (*poffset > file->f_dentry->d_inode->i_size)
644 long_op = 2; /* writes past end of file can take a long time */
648 for (total_written = 0; write_size > total_written;
649 total_written += bytes_written) {
651 while(rc == -EAGAIN) {
652 if(file->private_data == NULL) {
653 /* file has been closed on us */
655 /* if we have gotten here we have written some data
656 and blocked, and the file has been freed on us
657 while we blocked so return what we managed to write */
658 return total_written;
660 if(open_file->closePend) {
663 return total_written;
667 if (open_file->invalidHandle) {
668 if((file->f_dentry == NULL) ||
669 (file->f_dentry->d_inode == NULL)) {
671 return total_written;
673 /* we could deadlock if we called
674 filemap_fdatawait from here so tell
675 reopen_file not to flush data to server now */
676 rc = cifs_reopen_file(file->f_dentry->d_inode,
682 rc = CIFSSMBWrite(xid, pTcon,
684 write_size - total_written, *poffset,
686 NULL, write_data + total_written, long_op);
688 if (rc || (bytes_written == 0)) {
696 *poffset += bytes_written;
697 long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
700 #ifdef CONFIG_CIFS_STATS
701 if(total_written > 0) {
702 atomic_inc(&pTcon->num_writes);
703 spin_lock(&pTcon->stat_lock);
704 pTcon->bytes_written += total_written;
705 spin_unlock(&pTcon->stat_lock);
709 /* since the write may have blocked check these pointers again */
711 if(file->f_dentry->d_inode) {
712 struct inode *inode = file->f_dentry->d_inode;
713 inode->i_ctime = inode->i_mtime =
714 current_fs_time(inode->i_sb);
715 if (total_written > 0) {
716 if (*poffset > file->f_dentry->d_inode->i_size)
717 i_size_write(file->f_dentry->d_inode, *poffset);
719 mark_inode_dirty_sync(file->f_dentry->d_inode);
723 return total_written;
727 cifs_write(struct file * file, const char *write_data,
728 size_t write_size, loff_t * poffset)
731 unsigned int bytes_written = 0;
732 unsigned int total_written;
733 struct cifs_sb_info *cifs_sb;
734 struct cifsTconInfo *pTcon;
736 struct cifsFileInfo * open_file;
738 if(file->f_dentry == NULL)
741 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
742 if(cifs_sb == NULL) {
745 pTcon = cifs_sb->tcon;
748 (" write %d bytes to offset %lld of %s", write_size,
749 *poffset, file->f_dentry->d_name.name)); */
751 if (file->private_data == NULL) {
754 open_file = (struct cifsFileInfo *) file->private_data;
758 if(file->f_dentry->d_inode == NULL) {
763 if (*poffset > file->f_dentry->d_inode->i_size)
764 long_op = 2; /* writes past end of file can take a long time */
768 for (total_written = 0; write_size > total_written;
769 total_written += bytes_written) {
771 while(rc == -EAGAIN) {
772 if(file->private_data == NULL) {
773 /* file has been closed on us */
775 /* if we have gotten here we have written some data
776 and blocked, and the file has been freed on us
777 while we blocked so return what we managed to write */
778 return total_written;
780 if(open_file->closePend) {
783 return total_written;
787 if (open_file->invalidHandle) {
788 if((file->f_dentry == NULL) ||
789 (file->f_dentry->d_inode == NULL)) {
791 return total_written;
793 /* we could deadlock if we called
794 filemap_fdatawait from here so tell
795 reopen_file not to flush data to server now */
796 rc = cifs_reopen_file(file->f_dentry->d_inode,
802 rc = CIFSSMBWrite(xid, pTcon,
804 write_size - total_written, *poffset,
806 write_data + total_written, NULL, long_op);
808 if (rc || (bytes_written == 0)) {
816 *poffset += bytes_written;
817 long_op = FALSE; /* subsequent writes fast - 15 seconds is plenty */
820 #ifdef CONFIG_CIFS_STATS
821 if(total_written > 0) {
822 atomic_inc(&pTcon->num_writes);
823 spin_lock(&pTcon->stat_lock);
824 pTcon->bytes_written += total_written;
825 spin_unlock(&pTcon->stat_lock);
829 /* since the write may have blocked check these pointers again */
831 if(file->f_dentry->d_inode) {
832 file->f_dentry->d_inode->i_ctime = file->f_dentry->d_inode->i_mtime =
834 if (total_written > 0) {
835 if (*poffset > file->f_dentry->d_inode->i_size)
836 i_size_write(file->f_dentry->d_inode, *poffset);
838 mark_inode_dirty_sync(file->f_dentry->d_inode);
842 return total_written;
846 cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
848 struct address_space *mapping = page->mapping;
849 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
852 int bytes_written = 0;
853 struct cifs_sb_info *cifs_sb;
854 struct cifsTconInfo *pTcon;
856 struct cifsInodeInfo *cifsInode;
857 struct cifsFileInfo *open_file = NULL;
858 struct list_head *tmp;
859 struct list_head *tmp1;
863 } else if(!mapping->host) {
867 inode = page->mapping->host;
868 cifs_sb = CIFS_SB(inode->i_sb);
869 pTcon = cifs_sb->tcon;
871 offset += (loff_t)from;
872 write_data = kmap(page);
875 if((to > PAGE_CACHE_SIZE) || (from > to)) {
880 /* racing with truncate? */
881 if(offset > mapping->host->i_size) {
883 return 0; /* don't care */
886 /* check to make sure that we are not extending the file */
887 if(mapping->host->i_size - offset < (loff_t)to)
888 to = (unsigned)(mapping->host->i_size - offset);
891 cifsInode = CIFS_I(mapping->host);
892 read_lock(&GlobalSMBSeslock);
893 /* BB we should start at the end */
894 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
895 open_file = list_entry(tmp,struct cifsFileInfo, flist);
896 if(open_file->closePend)
898 /* We check if file is open for writing first */
899 if((open_file->pfile) &&
900 ((open_file->pfile->f_flags & O_RDWR) ||
901 (open_file->pfile->f_flags & O_WRONLY))) {
902 read_unlock(&GlobalSMBSeslock);
903 bytes_written = cifs_write(open_file->pfile, write_data,
905 read_lock(&GlobalSMBSeslock);
906 /* Does mm or vfs already set times? */
907 inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb);
908 if ((bytes_written > 0) && (offset)) {
910 } else if(bytes_written < 0) {
912 /* have seen a case in which
913 kernel seemed to have closed/freed a file
914 even with writes active so we might as well
915 see if there are other file structs to try
916 for the same inode before giving up */
921 break; /* now that we found a valid file handle
922 and tried to write to it we are done, no
923 sense continuing to loop looking for another */
925 if(tmp->next == NULL) {
926 cFYI(1,("File instance %p removed",tmp));
930 read_unlock(&GlobalSMBSeslock);
931 if(open_file == NULL) {
932 cFYI(1,("No writeable filehandles for inode"));
942 cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
948 /* call 16K write then Setpageuptodate */
955 cifs_writepage(struct page* page, struct writeback_control *wbc)
961 /* BB add check for wbc flags */
962 page_cache_get(page);
963 if (!PageUptodate(page)) {
964 cFYI(1,("ppw - page not up to date"));
967 rc = cifs_partialpagewrite(page,0,PAGE_CACHE_SIZE);
968 SetPageUptodate(page); /* BB add check for error and Clearuptodate? */
970 page_cache_release(page);
976 cifs_commit_write(struct file *file, struct page *page, unsigned offset,
981 struct inode *inode = page->mapping->host;
982 loff_t position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
986 cFYI(1,("commit write for page %p up to position %lld for %d",page,position,to));
987 if (position > inode->i_size){
988 i_size_write(inode, position);
989 /*if (file->private_data == NULL) {
992 open_file = (struct cifsFileInfo *)file->private_data;
993 cifs_sb = CIFS_SB(inode->i_sb);
995 while(rc == -EAGAIN) {
996 if((open_file->invalidHandle) &&
997 (!open_file->closePend)) {
998 rc = cifs_reopen_file(file->f_dentry->d_inode,file);
1002 if(!open_file->closePend) {
1003 rc = CIFSSMBSetFileSize(xid, cifs_sb->tcon,
1004 position, open_file->netfid,
1005 open_file->pid,FALSE);
1011 cFYI(1,(" SetEOF (commit write) rc = %d",rc));
1014 if (!PageUptodate(page)) {
1015 position = ((loff_t)page->index << PAGE_CACHE_SHIFT) + offset;
1016 /* can not rely on (or let) writepage write this data */
1018 cFYI(1,("Illegal offsets, can not copy from %d to %d",
1023 /* this is probably better than directly calling
1024 partialpage_write since in this function
1025 the file handle is known which we might as well
1027 /* BB check if anything else missing out of ppw */
1028 /* such as updating last write time */
1029 page_data = kmap(page);
1030 rc = cifs_write(file, page_data+offset,to-offset,
1034 /* else if rc < 0 should we set writebehind rc? */
1037 set_page_dirty(page);
1045 cifs_fsync(struct file *file, struct dentry *dentry, int datasync)
1049 struct inode * inode = file->f_dentry->d_inode;
1053 cFYI(1, ("Sync file - name: %s datasync: 0x%x ",
1054 dentry->d_name.name, datasync));
1056 rc = filemap_fdatawrite(inode->i_mapping);
1058 CIFS_I(inode)->write_behind_rc = 0;
1064 cifs_sync_page(struct page *page)
1066 struct address_space *mapping;
1067 struct inode *inode;
1068 unsigned long index = page->index;
1069 unsigned int rpages = 0;
1072 cFYI(1,("sync page %p",page));
1073 mapping = page->mapping;
1076 inode = mapping->host;
1080 /* fill in rpages then
1081 result = cifs_pagein_inode(inode, index, rpages); *//* BB finish */
1083 /* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
1091 * As file closes, flush all cached write data for this inode checking
1092 * for write behind errors.
1095 int cifs_flush(struct file *file)
1097 struct inode * inode = file->f_dentry->d_inode;
1100 /* Rather than do the steps manually: */
1101 /* lock the inode for writing */
1102 /* loop through pages looking for write behind data (dirty pages) */
1103 /* coalesce into contiguous 16K (or smaller) chunks to write to server */
1104 /* send to server (prefer in parallel) */
1105 /* deal with writebehind errors */
1106 /* unlock inode for writing */
1107 /* filemapfdatawrite appears easier for the time being */
1109 rc = filemap_fdatawrite(inode->i_mapping);
1110 if(rc == 0) /* reset wb rc if we were able to write out dirty pages */
1111 CIFS_I(inode)->write_behind_rc = 0;
1113 cFYI(1,("Flush inode %p file %p rc %d",inode,file,rc));
1120 cifs_user_read(struct file * file, char __user *read_data, size_t read_size,
1124 unsigned int bytes_read = 0;
1125 unsigned int total_read = 0;
1126 unsigned int current_read_size;
1127 struct cifs_sb_info *cifs_sb;
1128 struct cifsTconInfo *pTcon;
1130 struct cifsFileInfo * open_file;
1131 char * smb_read_data;
1132 char __user * current_offset;
1133 struct smb_com_read_rsp * pSMBr;
1136 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1137 pTcon = cifs_sb->tcon;
1139 if (file->private_data == NULL) {
1143 open_file = (struct cifsFileInfo *)file->private_data;
1145 if((file->f_flags & O_ACCMODE) == O_WRONLY) {
1146 cFYI(1,("attempting read on write only file instance"));
1149 for (total_read = 0,current_offset=read_data; read_size > total_read;
1150 total_read += bytes_read,current_offset+=bytes_read) {
1151 current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
1153 smb_read_data = NULL;
1154 while(rc == -EAGAIN) {
1155 if ((open_file->invalidHandle) && (!open_file->closePend)) {
1156 rc = cifs_reopen_file(file->f_dentry->d_inode,
1162 rc = CIFSSMBRead(xid, pTcon,
1164 current_read_size, *poffset,
1165 &bytes_read, &smb_read_data);
1167 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1168 copy_to_user(current_offset,smb_read_data + 4/* RFC1001 hdr*/
1169 + le16_to_cpu(pSMBr->DataOffset), bytes_read);
1171 cifs_buf_release(smb_read_data);
1172 smb_read_data = NULL;
1175 if (rc || (bytes_read == 0)) {
1183 #ifdef CONFIG_CIFS_STATS
1184 atomic_inc(&pTcon->num_reads);
1185 spin_lock(&pTcon->stat_lock);
1186 pTcon->bytes_read += total_read;
1187 spin_unlock(&pTcon->stat_lock);
1189 *poffset += bytes_read;
1197 cifs_read(struct file * file, char *read_data, size_t read_size,
1201 unsigned int bytes_read = 0;
1202 unsigned int total_read;
1203 unsigned int current_read_size;
1204 struct cifs_sb_info *cifs_sb;
1205 struct cifsTconInfo *pTcon;
1207 char * current_offset;
1208 struct cifsFileInfo * open_file;
1211 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1212 pTcon = cifs_sb->tcon;
1214 if (file->private_data == NULL) {
1218 open_file = (struct cifsFileInfo *)file->private_data;
1220 if((file->f_flags & O_ACCMODE) == O_WRONLY) {
1221 cFYI(1,("attempting read on write only file instance"));
1224 for (total_read = 0,current_offset=read_data; read_size > total_read;
1225 total_read += bytes_read,current_offset+=bytes_read) {
1226 current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize);
1228 while(rc == -EAGAIN) {
1229 if ((open_file->invalidHandle) && (!open_file->closePend)) {
1230 rc = cifs_reopen_file(file->f_dentry->d_inode,
1236 rc = CIFSSMBRead(xid, pTcon,
1238 current_read_size, *poffset,
1239 &bytes_read, ¤t_offset);
1241 if (rc || (bytes_read == 0)) {
1249 #ifdef CONFIG_CIFS_STATS
1250 atomic_inc(&pTcon->num_reads);
1251 spin_lock(&pTcon->stat_lock);
1252 pTcon->bytes_read += total_read;
1253 spin_unlock(&pTcon->stat_lock);
1255 *poffset += bytes_read;
1262 int cifs_file_mmap(struct file * file, struct vm_area_struct * vma)
1264 struct dentry * dentry = file->f_dentry;
1267 #ifdef CIFS_EXPERIMENTAL /* BB fixme reenable when cifs_read_wrapper fixed */
1269 struct cifs_sb_info *cifs_sb;
1270 cifs_sb = CIFS_SB(sb);
1271 if(cifs_sb != NULL) {
1272 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
1276 #endif /* CIFS_EXPERIMENTAL */
1279 rc = cifs_revalidate(dentry);
1281 cFYI(1,("Validation prior to mmap failed, error=%d", rc));
1285 rc = generic_file_mmap(file, vma);
1290 static void cifs_copy_cache_pages(struct address_space *mapping,
1291 struct list_head *pages, int bytes_read,
1292 char *data,struct pagevec * plru_pvec)
1297 while (bytes_read > 0) {
1298 if(list_empty(pages))
1301 page = list_entry(pages->prev, struct page, lru);
1302 list_del(&page->lru);
1304 if (add_to_page_cache(page, mapping, page->index, GFP_KERNEL)) {
1305 page_cache_release(page);
1306 cFYI(1,("Add page cache failed"));
1310 target = kmap_atomic(page,KM_USER0);
1312 if(PAGE_CACHE_SIZE > bytes_read) {
1313 memcpy(target,data,bytes_read);
1314 /* zero the tail end of this partial page */
1315 memset(target+bytes_read,0,PAGE_CACHE_SIZE-bytes_read);
1318 memcpy(target,data,PAGE_CACHE_SIZE);
1319 bytes_read -= PAGE_CACHE_SIZE;
1321 kunmap_atomic(target,KM_USER0);
1323 flush_dcache_page(page);
1324 SetPageUptodate(page);
1326 if (!pagevec_add(plru_pvec, page))
1327 __pagevec_lru_add(plru_pvec);
1328 data += PAGE_CACHE_SIZE;
1335 cifs_readpages(struct file *file, struct address_space *mapping,
1336 struct list_head *page_list, unsigned num_pages)
1342 struct cifs_sb_info *cifs_sb;
1343 struct cifsTconInfo *pTcon;
1345 unsigned int read_size,i;
1346 char * smb_read_data = NULL;
1347 struct smb_com_read_rsp * pSMBr;
1348 struct pagevec lru_pvec;
1349 struct cifsFileInfo * open_file;
1352 if (file->private_data == NULL) {
1356 open_file = (struct cifsFileInfo *)file->private_data;
1357 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1358 pTcon = cifs_sb->tcon;
1360 pagevec_init(&lru_pvec, 0);
1362 for(i = 0;i<num_pages;) {
1363 unsigned contig_pages;
1364 struct page * tmp_page;
1365 unsigned long expected_index;
1367 if(list_empty(page_list)) {
1370 page = list_entry(page_list->prev, struct page, lru);
1371 offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1373 /* count adjacent pages that we will read into */
1375 expected_index = list_entry(page_list->prev,struct page,lru)->index;
1376 list_for_each_entry_reverse(tmp_page,page_list,lru) {
1377 if(tmp_page->index == expected_index) {
1384 if(contig_pages + i > num_pages) {
1385 contig_pages = num_pages - i;
1388 /* for reads over a certain size could initiate async read ahead */
1390 read_size = contig_pages * PAGE_CACHE_SIZE;
1391 /* Read size needs to be in multiples of one page */
1392 read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK);
1395 while(rc == -EAGAIN) {
1396 if ((open_file->invalidHandle) && (!open_file->closePend)) {
1397 rc = cifs_reopen_file(file->f_dentry->d_inode,
1403 rc = CIFSSMBRead(xid, pTcon,
1406 &bytes_read, &smb_read_data);
1407 /* BB need to check return code here */
1410 cifs_buf_release(smb_read_data);
1411 smb_read_data = NULL;
1415 if ((rc < 0) || (smb_read_data == NULL)) {
1416 cFYI(1,("Read error in readpages: %d",rc));
1417 /* clean up remaing pages off list */
1418 while (!list_empty(page_list) && (i < num_pages)) {
1419 page = list_entry(page_list->prev, struct page, lru);
1420 list_del(&page->lru);
1421 page_cache_release(page);
1424 } else if (bytes_read > 0) {
1425 pSMBr = (struct smb_com_read_rsp *)smb_read_data;
1426 cifs_copy_cache_pages(mapping, page_list, bytes_read,
1427 smb_read_data + 4 /* RFC1001 hdr */ +
1428 le16_to_cpu(pSMBr->DataOffset), &lru_pvec);
1430 i += bytes_read >> PAGE_CACHE_SHIFT;
1431 #ifdef CONFIG_CIFS_STATS
1432 atomic_inc(&pTcon->num_reads);
1433 spin_lock(&pTcon->stat_lock);
1434 pTcon->bytes_read += bytes_read;
1435 spin_unlock(&pTcon->stat_lock);
1437 if((int)(bytes_read & PAGE_CACHE_MASK) != bytes_read) {
1438 i++; /* account for partial page */
1440 /* server copy of file can have smaller size than client */
1441 /* BB do we need to verify this common case ? this case is ok -
1442 if we are at server EOF we will hit it on next read */
1444 /* while(!list_empty(page_list) && (i < num_pages)) {
1445 page = list_entry(page_list->prev,struct page, list);
1446 list_del(&page->list);
1447 page_cache_release(page);
1452 cFYI(1,("No bytes read (%d) at offset %lld . Cleaning remaining pages from readahead list",bytes_read,offset));
1453 /* BB turn off caching and do new lookup on file size at server? */
1454 while (!list_empty(page_list) && (i < num_pages)) {
1455 page = list_entry(page_list->prev, struct page, lru);
1456 list_del(&page->lru);
1457 page_cache_release(page); /* BB removeme - replace with zero of page? */
1462 cifs_buf_release(smb_read_data);
1463 smb_read_data = NULL;
1468 pagevec_lru_add(&lru_pvec);
1470 /* need to free smb_read_data buf before exit */
1472 cifs_buf_release(smb_read_data);
1473 smb_read_data = NULL;
1480 static int cifs_readpage_worker(struct file *file, struct page *page, loff_t * poffset)
1485 page_cache_get(page);
1486 read_data = kmap(page);
1487 /* for reads over a certain size could initiate async read ahead */
1489 rc = cifs_read(file, read_data, PAGE_CACHE_SIZE, poffset);
1494 cFYI(1,("Bytes read %d ",rc));
1497 file->f_dentry->d_inode->i_atime =
1498 current_fs_time(file->f_dentry->d_inode->i_sb);
1500 if(PAGE_CACHE_SIZE > rc) {
1501 memset(read_data+rc, 0, PAGE_CACHE_SIZE - rc);
1503 flush_dcache_page(page);
1504 SetPageUptodate(page);
1509 page_cache_release(page);
1514 cifs_readpage(struct file *file, struct page *page)
1516 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
1522 if (file->private_data == NULL) {
1527 cFYI(1,("readpage %p at offset %d 0x%x\n",page,(int)offset,(int)offset));
1529 rc = cifs_readpage_worker(file,page,&offset);
1537 /* We do not want to update the file size from server for inodes
1538 open for write - to avoid races with writepage extending
1539 the file - in the future we could consider allowing
1540 refreshing the inode only on increases in the file size
1541 but this is tricky to do without racing with writebehind
1542 page caching in the current Linux kernel design */
1544 int is_size_safe_to_change(struct cifsInodeInfo * cifsInode)
1546 struct list_head *tmp;
1547 struct list_head *tmp1;
1548 struct cifsFileInfo *open_file = NULL;
1551 if(cifsInode == NULL)
1554 read_lock(&GlobalSMBSeslock);
1555 list_for_each_safe(tmp, tmp1, &cifsInode->openFileList) {
1556 open_file = list_entry(tmp,struct cifsFileInfo, flist);
1557 if(open_file == NULL)
1559 if(open_file->closePend)
1561 /* We check if file is open for writing,
1562 BB we could supplement this with a check to see if file size
1563 changes have been flushed to server - ie inode metadata dirty */
1564 if((open_file->pfile) &&
1565 ((open_file->pfile->f_flags & O_RDWR) ||
1566 (open_file->pfile->f_flags & O_WRONLY))) {
1570 if(tmp->next == NULL) {
1571 cFYI(1,("File instance %p removed",tmp));
1575 read_unlock(&GlobalSMBSeslock);
1581 fill_in_inode(struct inode *tmp_inode,
1582 FILE_DIRECTORY_INFO * pfindData, int *pobject_type)
1584 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
1585 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
1586 __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
1587 __u64 allocation_size = le64_to_cpu(pfindData->AllocationSize);
1588 __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
1590 cifsInfo->cifsAttrs = attr;
1591 cifsInfo->time = jiffies;
1593 /* Linux can not store file creation time unfortunately so ignore it */
1594 tmp_inode->i_atime =
1595 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
1596 tmp_inode->i_mtime =
1597 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
1598 tmp_inode->i_ctime =
1599 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
1600 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
1601 /* 2767 perms - indicate mandatory locking */
1602 /* BB fill in uid and gid here? with help from winbind?
1603 or retrieve from NTFS stream extended attribute */
1604 if(atomic_read(&cifsInfo->inUse) == 0) {
1605 tmp_inode->i_uid = cifs_sb->mnt_uid;
1606 tmp_inode->i_gid = cifs_sb->mnt_gid;
1607 /* set default mode. will override for dirs below */
1608 tmp_inode->i_mode = cifs_sb->mnt_file_mode;
1612 ("CIFS FFIRST: Attributes came in as 0x%x",
1614 if (attr & ATTR_DIRECTORY) {
1615 *pobject_type = DT_DIR;
1616 /* override default perms since we do not lock dirs */
1617 if(atomic_read(&cifsInfo->inUse) == 0) {
1618 tmp_inode->i_mode = cifs_sb->mnt_dir_mode;
1620 tmp_inode->i_mode |= S_IFDIR;
1621 /* we no longer mark these because we could not follow them */
1622 /* } else if (attr & ATTR_REPARSE) {
1623 *pobject_type = DT_LNK;
1624 tmp_inode->i_mode |= S_IFLNK;*/
1626 *pobject_type = DT_REG;
1627 tmp_inode->i_mode |= S_IFREG;
1628 if(attr & ATTR_READONLY)
1629 tmp_inode->i_mode &= ~(S_IWUGO);
1630 }/* could add code here - to validate if device or weird share type? */
1632 /* can not fill in nlink here as in qpathinfo version and Unx search */
1633 if(atomic_read(&cifsInfo->inUse) == 0) {
1634 atomic_set(&cifsInfo->inUse,1);
1637 if(is_size_safe_to_change(cifsInfo)) {
1638 /* can not safely change the file size here if the
1639 client is writing to it due to potential races */
1640 i_size_write(tmp_inode,end_of_file);
1642 /* 512 bytes (2**9) is the fake blocksize that must be used */
1643 /* for this calculation, even though the reported blocksize is larger */
1644 tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9;
1647 if (allocation_size < end_of_file)
1648 cFYI(1, ("Possible sparse file: allocation size less than end of file "));
1650 ("File Size %ld and blocks %ld and blocksize %ld",
1651 (unsigned long) tmp_inode->i_size, tmp_inode->i_blocks,
1652 tmp_inode->i_blksize));
1653 if (S_ISREG(tmp_inode->i_mode)) {
1654 cFYI(1, (" File inode "));
1655 tmp_inode->i_op = &cifs_file_inode_ops;
1656 tmp_inode->i_fop = &cifs_file_ops;
1657 tmp_inode->i_data.a_ops = &cifs_addr_ops;
1658 } else if (S_ISDIR(tmp_inode->i_mode)) {
1659 cFYI(1, (" Directory inode"));
1660 tmp_inode->i_op = &cifs_dir_inode_ops;
1661 tmp_inode->i_fop = &cifs_dir_ops;
1662 } else if (S_ISLNK(tmp_inode->i_mode)) {
1663 cFYI(1, (" Symbolic Link inode "));
1664 tmp_inode->i_op = &cifs_symlink_inode_ops;
1666 cFYI(1, (" Init special inode "));
1667 init_special_inode(tmp_inode, tmp_inode->i_mode,
1673 unix_fill_in_inode(struct inode *tmp_inode,
1674 FILE_UNIX_INFO * pfindData, int *pobject_type)
1676 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
1677 __u32 type = le32_to_cpu(pfindData->Type);
1678 __u64 num_of_bytes = le64_to_cpu(pfindData->NumOfBytes);
1679 __u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
1680 cifsInfo->time = jiffies;
1681 atomic_inc(&cifsInfo->inUse);
1683 tmp_inode->i_atime =
1684 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
1685 tmp_inode->i_mtime =
1686 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastModificationTime));
1687 tmp_inode->i_ctime =
1688 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
1690 tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
1691 if (type == UNIX_FILE) {
1692 *pobject_type = DT_REG;
1693 tmp_inode->i_mode |= S_IFREG;
1694 } else if (type == UNIX_SYMLINK) {
1695 *pobject_type = DT_LNK;
1696 tmp_inode->i_mode |= S_IFLNK;
1697 } else if (type == UNIX_DIR) {
1698 *pobject_type = DT_DIR;
1699 tmp_inode->i_mode |= S_IFDIR;
1700 } else if (type == UNIX_CHARDEV) {
1701 *pobject_type = DT_CHR;
1702 tmp_inode->i_mode |= S_IFCHR;
1703 tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
1704 le64_to_cpu(pfindData->DevMinor) & MINORMASK);
1705 } else if (type == UNIX_BLOCKDEV) {
1706 *pobject_type = DT_BLK;
1707 tmp_inode->i_mode |= S_IFBLK;
1708 tmp_inode->i_rdev = MKDEV(le64_to_cpu(pfindData->DevMajor),
1709 le64_to_cpu(pfindData->DevMinor) & MINORMASK);
1710 } else if (type == UNIX_FIFO) {
1711 *pobject_type = DT_FIFO;
1712 tmp_inode->i_mode |= S_IFIFO;
1713 } else if (type == UNIX_SOCKET) {
1714 *pobject_type = DT_SOCK;
1715 tmp_inode->i_mode |= S_IFSOCK;
1718 tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
1719 tmp_inode->i_gid = le64_to_cpu(pfindData->Gid);
1720 tmp_inode->i_nlink = le64_to_cpu(pfindData->Nlinks);
1723 if(is_size_safe_to_change(cifsInfo)) {
1724 /* can not safely change the file size here if the
1725 client is writing to it due to potential races */
1726 i_size_write(tmp_inode,end_of_file);
1728 /* 512 bytes (2**9) is the fake blocksize that must be used */
1729 /* for this calculation, not the real blocksize */
1730 tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
1733 if (S_ISREG(tmp_inode->i_mode)) {
1734 cFYI(1, ("File inode"));
1735 tmp_inode->i_op = &cifs_file_inode_ops;
1736 tmp_inode->i_fop = &cifs_file_ops;
1737 tmp_inode->i_data.a_ops = &cifs_addr_ops;
1738 } else if (S_ISDIR(tmp_inode->i_mode)) {
1739 cFYI(1, ("Directory inode"));
1740 tmp_inode->i_op = &cifs_dir_inode_ops;
1741 tmp_inode->i_fop = &cifs_dir_ops;
1742 } else if (S_ISLNK(tmp_inode->i_mode)) {
1743 cFYI(1, ("Symbolic Link inode"));
1744 tmp_inode->i_op = &cifs_symlink_inode_ops;
1745 /* tmp_inode->i_fop = *//* do not need to set to anything */
1747 cFYI(1, ("Special inode"));
1748 init_special_inode(tmp_inode, tmp_inode->i_mode,
1753 /* Returns one if new inode created (which therefore needs to be hashed) */
1754 /* Might check in the future if inode number changed so we can rehash inode */
1756 construct_dentry(struct qstr *qstring, struct file *file,
1757 struct inode **ptmp_inode, struct dentry **pnew_dentry)
1759 struct dentry *tmp_dentry;
1760 struct cifs_sb_info *cifs_sb;
1761 struct cifsTconInfo *pTcon;
1764 cFYI(1, ("For %s ", qstring->name));
1765 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1766 pTcon = cifs_sb->tcon;
1768 qstring->hash = full_name_hash(qstring->name, qstring->len);
1769 tmp_dentry = d_lookup(file->f_dentry, qstring);
1771 cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode));
1772 *ptmp_inode = tmp_dentry->d_inode;
1773 /* BB overwrite the old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len ?? */
1774 if(*ptmp_inode == NULL) {
1775 *ptmp_inode = new_inode(file->f_dentry->d_sb);
1776 if(*ptmp_inode == NULL)
1779 d_instantiate(tmp_dentry, *ptmp_inode);
1782 tmp_dentry = d_alloc(file->f_dentry, qstring);
1783 if(tmp_dentry == NULL) {
1784 cERROR(1,("Failed allocating dentry"));
1789 *ptmp_inode = new_inode(file->f_dentry->d_sb);
1790 tmp_dentry->d_op = &cifs_dentry_ops;
1791 if(*ptmp_inode == NULL)
1794 d_instantiate(tmp_dentry, *ptmp_inode);
1795 d_rehash(tmp_dentry);
1798 tmp_dentry->d_time = jiffies;
1799 *pnew_dentry = tmp_dentry;
1803 static void reset_resume_key(struct file * dir_file,
1804 unsigned char * filename,
1805 unsigned int len,int Unicode,struct nls_table * nls_tab) {
1806 struct cifsFileInfo *cifsFile;
1808 cifsFile = (struct cifsFileInfo *)dir_file->private_data;
1809 if(cifsFile == NULL)
1811 if(cifsFile->search_resume_name) {
1812 kfree(cifsFile->search_resume_name);
1817 cifsFile->resume_name_length = len;
1819 cifsFile->search_resume_name =
1820 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
1822 if(cifsFile->search_resume_name == NULL) {
1823 cERROR(1,("failed new resume key allocate, length %d",
1824 cifsFile->resume_name_length));
1828 cifs_strtoUCS((wchar_t *) cifsFile->search_resume_name,
1829 filename, len, nls_tab);
1831 memcpy(cifsFile->search_resume_name, filename,
1832 cifsFile->resume_name_length);
1833 cFYI(1,("Reset resume key to: %s with len %d",filename,len));
1840 cifs_filldir(struct qstr *pqstring, FILE_DIRECTORY_INFO * pfindData,
1841 struct file *file, filldir_t filldir, void *direntry)
1843 struct inode *tmp_inode;
1844 struct dentry *tmp_dentry;
1847 pqstring->name = pfindData->FileName;
1848 /* pqstring->len is already set by caller */
1850 rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
1851 if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
1854 fill_in_inode(tmp_inode, pfindData, &object_type);
1856 /* We have no reliable way to get inode numbers
1857 from servers w/o Unix extensions yet so we can not set
1858 i_ino from pfindData yet */
1860 /* new inode created, let us hash it */
1861 insert_inode_hash(tmp_inode);
1862 } /* else if inode number changed do we rehash it? */
1863 rc = filldir(direntry, pfindData->FileName, pqstring->len, file->f_pos,
1864 tmp_inode->i_ino, object_type);
1866 /* due to readdir error we need to recalculate resume
1867 key so next readdir will restart on right entry */
1868 cFYI(1,("Error %d on filldir of %s",rc ,pfindData->FileName));
1875 cifs_filldir_unix(struct qstr *pqstring,
1876 FILE_UNIX_INFO * pUnixFindData, struct file *file,
1877 filldir_t filldir, void *direntry)
1879 struct inode *tmp_inode;
1880 struct dentry *tmp_dentry;
1881 int object_type, rc;
1883 pqstring->name = pUnixFindData->FileName;
1884 pqstring->len = strnlen(pUnixFindData->FileName, MAX_PATHCONF);
1886 rc = construct_dentry(pqstring, file, &tmp_inode, &tmp_dentry);
1887 if((tmp_inode == NULL) || (tmp_dentry == NULL)) {
1891 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
1893 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
1895 (unsigned long)pUnixFindData->UniqueId;
1897 insert_inode_hash(tmp_inode);
1898 } /* else if i_ino has changed should we rehash it? */
1899 unix_fill_in_inode(tmp_inode, pUnixFindData, &object_type);
1900 rc = filldir(direntry, pUnixFindData->FileName, pqstring->len,
1901 file->f_pos, tmp_inode->i_ino, object_type);
1903 /* due to readdir error we need to recalculate resume
1904 key so next readdir will restart on right entry */
1905 cFYI(1,("Error %d on filldir of %s",rc ,pUnixFindData->FileName));
1912 cifs_readdir(struct file *file, void *direntry, filldir_t filldir)
1916 int Unicode = FALSE;
1917 int UnixSearch = FALSE;
1918 unsigned int bufsize, i;
1920 struct cifs_sb_info *cifs_sb;
1921 struct cifsTconInfo *pTcon;
1922 struct cifsFileInfo *cifsFile = NULL;
1923 char *full_path = NULL;
1925 struct qstr qstring;
1926 T2_FFIRST_RSP_PARMS findParms;
1927 T2_FNEXT_RSP_PARMS findNextParms;
1928 FILE_DIRECTORY_INFO *pfindData;
1929 FILE_DIRECTORY_INFO *lastFindData;
1930 FILE_UNIX_INFO *pfindDataUnix;
1933 /* BB removeme begin */
1935 return cifs_readdir2(file,direntry,filldir);
1936 /* BB removeme end */
1941 if(file->f_dentry == NULL) {
1946 cifs_sb = CIFS_SB(file->f_dentry->d_sb);
1947 pTcon = cifs_sb->tcon;
1948 bufsize = pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE;
1949 if(bufsize > CIFSMaxBufSize) {
1954 data = kmalloc(bufsize, GFP_KERNEL);
1955 pfindData = (FILE_DIRECTORY_INFO *) data;
1961 down(&file->f_dentry->d_sb->s_vfs_rename_sem);
1962 full_path = build_wildcard_path_from_dentry(file->f_dentry);
1963 up(&file->f_dentry->d_sb->s_vfs_rename_sem);
1965 if(full_path == NULL) {
1970 cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos));
1972 switch ((int) file->f_pos) {
1974 if (filldir(direntry, ".", 1, file->f_pos,
1975 file->f_dentry->d_inode->i_ino, DT_DIR) < 0) {
1976 cERROR(1, ("Filldir for current dir failed "));
1982 if (filldir(direntry, "..", 2, file->f_pos,
1983 file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
1984 cERROR(1, ("Filldir for parent dir failed "));
1990 if (file->private_data != NULL) {
1992 (struct cifsFileInfo *) file->private_data;
1993 if (cifsFile->srch_inf.endOfSearch) {
1994 if(cifsFile->srch_inf.emptyDir) {
1995 cFYI(1, ("End of search, empty dir"));
2000 cifsFile->invalidHandle = TRUE;
2001 CIFSFindClose(xid, pTcon, cifsFile->netfid);
2003 if(cifsFile->search_resume_name) {
2004 kfree(cifsFile->search_resume_name);
2005 cifsFile->search_resume_name = NULL;
2008 rc = CIFSFindFirst(xid, pTcon, full_path, pfindData,
2009 &findParms, cifs_sb->local_nls,
2010 &Unicode, &UnixSearch);
2011 cFYI(1, ("Count: %d End: %d ",
2012 le16_to_cpu(findParms.SearchCount),
2013 le16_to_cpu(findParms.EndofSearch)));
2016 __u16 count = le16_to_cpu(findParms.SearchCount);
2017 searchHandle = findParms.SearchHandle;
2018 if(file->private_data == NULL)
2019 file->private_data =
2020 kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL);
2021 if (file->private_data) {
2022 memset(file->private_data, 0,
2023 sizeof (struct cifsFileInfo));
2025 (struct cifsFileInfo *) file->private_data;
2026 cifsFile->netfid = searchHandle;
2027 cifsFile->invalidHandle = FALSE;
2028 init_MUTEX(&cifsFile->fh_sem);
2034 renew_parental_timestamps(file->f_dentry);
2036 (FILE_DIRECTORY_INFO *) ((char *) pfindData +
2037 le16_to_cpu(findParms.LastNameOffset));
2038 if((char *)lastFindData > (char *)pfindData + bufsize) {
2039 cFYI(1,("last search entry past end of packet"));
2043 /* Offset of resume key same for levels 257 and 514 */
2044 cifsFile->srch_inf.resume_key = lastFindData->FileIndex;
2045 if(UnixSearch == FALSE) {
2046 cifsFile->resume_name_length =
2047 le32_to_cpu(lastFindData->FileNameLength);
2048 if(cifsFile->resume_name_length > bufsize - 64) {
2049 cFYI(1,("Illegal resume file name length %d",
2050 cifsFile->resume_name_length));
2054 cifsFile->search_resume_name =
2055 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
2056 cFYI(1,("Last file: %s with name %d bytes long",
2057 lastFindData->FileName,
2058 cifsFile->resume_name_length));
2059 if(cifsFile->search_resume_name == NULL) {
2063 memcpy(cifsFile->search_resume_name,
2064 lastFindData->FileName,
2065 cifsFile->resume_name_length);
2067 pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
2068 if (Unicode == TRUE) {
2069 for(i=0;(pfindDataUnix->FileName[i]
2070 | pfindDataUnix->FileName[i+1]);
2075 cifsFile->resume_name_length = i + 2;
2077 cifsFile->resume_name_length =
2078 strnlen(pfindDataUnix->FileName,
2081 if(cifsFile->resume_name_length > bufsize - 64) {
2082 cFYI(1,("Illegal resume file name length %d",
2083 cifsFile->resume_name_length));
2087 cifsFile->search_resume_name =
2088 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
2089 cFYI(1,("Last file: %s with name %d bytes long",
2090 pfindDataUnix->FileName,
2091 cifsFile->resume_name_length));
2092 if(cifsFile->search_resume_name == NULL) {
2096 memcpy(cifsFile->search_resume_name,
2097 pfindDataUnix->FileName,
2098 cifsFile->resume_name_length);
2100 for (i = 2; i < count + 2; i++) {
2101 if (UnixSearch == FALSE) {
2102 __u32 len = le32_to_cpu(pfindData->FileNameLength);
2103 if (Unicode == TRUE)
2106 (pfindData->FileName,
2108 pfindData->FileName,
2110 cifs_sb->local_nls);
2113 || (pfindData->FileName[0] != '.'))
2118 FileName[1] != '.'))) {
2119 if(cifs_filldir(&qstring,
2123 /* do not end search if
2124 kernel not ready to take
2125 remaining entries yet */
2126 reset_resume_key(file, pfindData->FileName,qstring.len,
2127 Unicode, cifs_sb->local_nls);
2128 findParms.EndofSearch = 0;
2133 } else { /* UnixSearch */
2135 (FILE_UNIX_INFO *) pfindData;
2136 if (Unicode == TRUE)
2139 (pfindDataUnix->FileName,
2141 pfindDataUnix->FileName,
2143 cifs_sb->local_nls);
2146 strnlen(pfindDataUnix->
2149 if (((qstring.len != 1)
2151 FileName[0] != '.'))
2152 && ((qstring.len != 2)
2156 FileName[1] != '.'))) {
2157 if(cifs_filldir_unix(&qstring,
2162 /* do not end search if
2163 kernel not ready to take
2164 remaining entries yet */
2165 findParms.EndofSearch = 0;
2166 reset_resume_key(file, pfindDataUnix->FileName,
2167 qstring.len,Unicode,cifs_sb->local_nls);
2173 /* works also for Unix ff struct since first field of both */
2175 (FILE_DIRECTORY_INFO *) ((char *) pfindData
2176 + le32_to_cpu(pfindData->NextEntryOffset));
2177 /* BB also should check to make sure that pointer is not beyond the end of the SMB */
2178 /* if(pfindData > lastFindData) rc = -EIO; break; */
2179 } /* end for loop */
2180 if ((findParms.EndofSearch != 0) && cifsFile) {
2181 cifsFile->srch_inf.endOfSearch = TRUE;
2182 if(findParms.SearchCount == cpu_to_le16(2))
2183 cifsFile->srch_inf.emptyDir = TRUE;
2187 cifsFile->srch_inf.endOfSearch = TRUE;
2188 /* unless parent directory gone do not return error */
2193 if (file->private_data == NULL) {
2196 ("Readdir on closed srch, pos = %lld",
2199 cifsFile = (struct cifsFileInfo *) file->private_data;
2200 if (cifsFile->srch_inf.endOfSearch) {
2202 cFYI(1, ("End of search "));
2205 searchHandle = cifsFile->netfid;
2206 rc = CIFSFindNext(xid, pTcon, pfindData,
2207 &findNextParms, searchHandle,
2208 cifsFile->search_resume_name,
2209 cifsFile->resume_name_length,
2210 cifsFile->srch_inf.resume_key,
2211 &Unicode, &UnixSearch);
2212 cFYI(1,("Count: %d End: %d ",
2213 le16_to_cpu(findNextParms.SearchCount),
2214 le16_to_cpu(findNextParms.EndofSearch)));
2215 if ((rc == 0) && (findNextParms.SearchCount != 0)) {
2216 /* BB save off resume key, key name and name length */
2217 __u16 count = le16_to_cpu(findNextParms.SearchCount);
2219 (FILE_DIRECTORY_INFO *) ((char *) pfindData
2220 + le16_to_cpu(findNextParms.LastNameOffset));
2221 if((char *)lastFindData > (char *)pfindData + bufsize) {
2222 cFYI(1,("last search entry past end of packet"));
2226 /* Offset of resume key same for levels 257 and 514 */
2227 cifsFile->srch_inf.resume_key = lastFindData->FileIndex;
2229 if(UnixSearch == FALSE) {
2230 cifsFile->resume_name_length =
2231 le32_to_cpu(lastFindData->FileNameLength);
2232 if(cifsFile->resume_name_length > bufsize - 64) {
2233 cFYI(1,("Illegal resume file name length %d",
2234 cifsFile->resume_name_length));
2238 /* Free the memory allocated by previous findfirst
2239 or findnext call - we can not reuse the memory since
2240 the resume name may not be same string length */
2241 if(cifsFile->search_resume_name)
2242 kfree(cifsFile->search_resume_name);
2243 cifsFile->search_resume_name =
2244 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
2245 cFYI(1,("Last file: %s with name %d bytes long",
2246 lastFindData->FileName,
2247 cifsFile->resume_name_length));
2248 if(cifsFile->search_resume_name == NULL) {
2253 memcpy(cifsFile->search_resume_name,
2254 lastFindData->FileName,
2255 cifsFile->resume_name_length);
2257 pfindDataUnix = (FILE_UNIX_INFO *)lastFindData;
2258 if (Unicode == TRUE) {
2259 for(i=0;(pfindDataUnix->FileName[i]
2260 | pfindDataUnix->FileName[i+1]);
2265 cifsFile->resume_name_length = i + 2;
2267 cifsFile->resume_name_length =
2268 strnlen(pfindDataUnix->
2272 if(cifsFile->resume_name_length > bufsize - 64) {
2273 cFYI(1,("Illegal resume file name length %d",
2274 cifsFile->resume_name_length));
2278 /* Free the memory allocated by previous findfirst
2279 or findnext call - we can not reuse the memory since
2280 the resume name may not be same string length */
2281 if(cifsFile->search_resume_name)
2282 kfree(cifsFile->search_resume_name);
2283 cifsFile->search_resume_name =
2284 kmalloc(cifsFile->resume_name_length, GFP_KERNEL);
2285 cFYI(1,("fnext last file: %s with name %d bytes long",
2286 pfindDataUnix->FileName,
2287 cifsFile->resume_name_length));
2288 if(cifsFile->search_resume_name == NULL) {
2292 memcpy(cifsFile->search_resume_name,
2293 pfindDataUnix->FileName,
2294 cifsFile->resume_name_length);
2297 for (i = 0; i < count; i++) {
2298 __u32 len = le32_to_cpu(pfindData->
2300 if (UnixSearch == FALSE) {
2301 if (Unicode == TRUE)
2304 (pfindData->FileName,
2306 pfindData->FileName,
2308 cifs_sb->local_nls);
2311 || (pfindData->FileName[0] != '.'))
2313 || (pfindData->FileName[0] != '.')
2314 || (pfindData->FileName[1] !=
2321 /* do not end search if
2322 kernel not ready to take
2323 remaining entries yet */
2324 findNextParms.EndofSearch = 0;
2325 reset_resume_key(file, pfindData->FileName,qstring.len,
2326 Unicode,cifs_sb->local_nls);
2331 } else { /* UnixSearch */
2335 if (Unicode == TRUE)
2338 (pfindDataUnix->FileName,
2340 pfindDataUnix->FileName,
2342 cifs_sb->local_nls);
2349 if (((qstring.len != 1)
2351 FileName[0] != '.'))
2352 && ((qstring.len != 2)
2358 if(cifs_filldir_unix
2363 /* do not end search if
2364 kernel not ready to take
2365 remaining entries yet */
2366 findNextParms.EndofSearch = 0;
2367 reset_resume_key(file, pfindDataUnix->FileName,qstring.len,
2368 Unicode,cifs_sb->local_nls);
2374 pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData +
2375 le32_to_cpu(pfindData->NextEntryOffset));
2376 /* works also for Unix find struct since first field of both */
2377 /* BB also should check to ensure pointer not beyond end of SMB */
2378 } /* end for loop */
2379 if (findNextParms.EndofSearch != 0) {
2380 cifsFile->srch_inf.endOfSearch = TRUE;
2383 cifsFile->srch_inf.endOfSearch = TRUE;
2384 rc = 0; /* unless parent directory disappeared - do not
2385 return error here (eg Access Denied or no more files) */
2397 int cifs_prepare_write(struct file *file, struct page *page,
2398 unsigned from, unsigned to)
2401 loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
2402 cFYI(1,("prepare write for page %p from %d to %d",page,from,to));
2403 if (!PageUptodate(page)) {
2404 /* if (to - from != PAGE_CACHE_SIZE) {
2405 void *kaddr = kmap_atomic(page, KM_USER0);
2406 memset(kaddr, 0, from);
2407 memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
2408 flush_dcache_page(page);
2409 kunmap_atomic(kaddr, KM_USER0);
2411 /* If we are writing a full page it will be up to date,
2412 no need to read from the server */
2413 if((to==PAGE_CACHE_SIZE) && (from == 0))
2414 SetPageUptodate(page);
2416 /* might as well read a page, it is fast enough */
2417 if((file->f_flags & O_ACCMODE) != O_WRONLY) {
2418 rc = cifs_readpage_worker(file,page,&offset);
2420 /* should we try using another
2421 file handle if there is one - how would we lock it
2422 to prevent close of that handle racing with this read? */
2423 /* In any case this will be written out by commit_write */
2427 /* BB should we pass any errors back? e.g. if we do not have read access to the file */
2432 struct address_space_operations cifs_addr_ops = {
2433 .readpage = cifs_readpage,
2434 .readpages = cifs_readpages,
2435 .writepage = cifs_writepage,
2436 .prepare_write = cifs_prepare_write,
2437 .commit_write = cifs_commit_write,
2438 .set_page_dirty = __set_page_dirty_nobuffers,
2439 /* .sync_page = cifs_sync_page, */