4 * Copyright (C) International Business Machines Corp., 2002,2003
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/buffer_head.h>
23 #include <linux/stat.h>
24 #include <linux/pagemap.h>
25 #include <asm/div64.h>
29 #include "cifsproto.h"
30 #include "cifs_debug.h"
31 #include "cifs_fs_sb.h"
33 extern int is_size_safe_to_change(struct cifsInodeInfo
*);
36 cifs_get_inode_info_unix(struct inode
**pinode
,
37 const unsigned char *search_path
,
38 struct super_block
*sb
,int xid
)
41 FILE_UNIX_BASIC_INFO findData
;
42 struct cifsTconInfo
*pTcon
;
44 struct cifs_sb_info
*cifs_sb
= CIFS_SB(sb
);
47 pTcon
= cifs_sb
->tcon
;
48 cFYI(1, (" Getting info on %s ", search_path
));
49 /* we could have done a find first instead but this returns more info */
50 rc
= CIFSSMBUnixQPathInfo(xid
, pTcon
, search_path
, &findData
,
52 /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */
59 strnlen(search_path
, MAX_PATHCONF
) + 1,
61 if (tmp_path
== NULL
) {
64 /* have to skip first of the double backslash of UNC name */
65 strncpy(tmp_path
, pTcon
->treeName
, MAX_TREE_SIZE
);
66 strncat(tmp_path
, search_path
, MAX_PATHCONF
);
67 rc
= connect_to_dfs_path(xid
, pTcon
->ses
,
68 /* treename + */ tmp_path
,
72 /* BB fix up inode etc. */
78 struct cifsInodeInfo
*cifsInfo
;
79 __u32 type
= le32_to_cpu(findData
.Type
);
80 __u64 num_of_bytes
= le64_to_cpu(findData
.NumOfBytes
);
81 __u64 end_of_file
= le64_to_cpu(findData
.EndOfFile
);
84 if (*pinode
== NULL
) {
85 *pinode
= new_inode(sb
);
88 insert_inode_hash(*pinode
);
92 cifsInfo
= CIFS_I(inode
);
94 cFYI(1, (" Old time %ld ", cifsInfo
->time
));
95 cifsInfo
->time
= jiffies
;
96 cFYI(1, (" New time %ld ", cifsInfo
->time
));
97 atomic_set(&cifsInfo
->inUse
,1); /* ok to set on every refresh of inode */
100 cifs_NTtimeToUnix(le64_to_cpu(findData
.LastAccessTime
));
102 cifs_NTtimeToUnix(le64_to_cpu
103 (findData
.LastModificationTime
));
105 cifs_NTtimeToUnix(le64_to_cpu(findData
.LastStatusChange
));
106 inode
->i_mode
= le64_to_cpu(findData
.Permissions
);
107 if (type
== UNIX_FILE
) {
108 inode
->i_mode
|= S_IFREG
;
109 } else if (type
== UNIX_SYMLINK
) {
110 inode
->i_mode
|= S_IFLNK
;
111 } else if (type
== UNIX_DIR
) {
112 inode
->i_mode
|= S_IFDIR
;
113 } else if (type
== UNIX_CHARDEV
) {
114 inode
->i_mode
|= S_IFCHR
;
115 inode
->i_rdev
= MKDEV(le64_to_cpu(findData
.DevMajor
),
116 le64_to_cpu(findData
.DevMinor
) & MINORMASK
);
117 } else if (type
== UNIX_BLOCKDEV
) {
118 inode
->i_mode
|= S_IFBLK
;
119 inode
->i_rdev
= MKDEV(le64_to_cpu(findData
.DevMajor
),
120 le64_to_cpu(findData
.DevMinor
) & MINORMASK
);
121 } else if (type
== UNIX_FIFO
) {
122 inode
->i_mode
|= S_IFIFO
;
123 } else if (type
== UNIX_SOCKET
) {
124 inode
->i_mode
|= S_IFSOCK
;
126 inode
->i_uid
= le64_to_cpu(findData
.Uid
);
127 inode
->i_gid
= le64_to_cpu(findData
.Gid
);
128 inode
->i_nlink
= le64_to_cpu(findData
.Nlinks
);
130 if(is_size_safe_to_change(cifsInfo
)) {
131 /* can not safely change the file size here if the
132 client is writing to it due to potential races */
134 i_size_write(inode
, end_of_file
);
135 /* blksize needs to be multiple of two. So safer to default to blksize
136 and blkbits set in superblock so 2**blkbits and blksize will match */
137 /* inode->i_blksize =
138 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
140 /* This seems incredibly stupid but it turns out that
141 i_blocks is not related to (i_size / i_blksize), instead a
142 size of 512 is required to be used for calculating num blocks */
146 (inode->i_blksize - 1 + num_of_bytes) >> inode->i_blkbits;*/
148 /* 512 bytes (2**9) is the fake blocksize that must be used */
149 /* for this calculation */
150 inode
->i_blocks
= (512 - 1 + num_of_bytes
) >> 9;
153 if (num_of_bytes
< end_of_file
)
154 cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
156 ("Size %ld and blocks %ld ",
157 (unsigned long) inode
->i_size
, inode
->i_blocks
));
158 if (S_ISREG(inode
->i_mode
)) {
159 cFYI(1, (" File inode "));
160 inode
->i_op
= &cifs_file_inode_ops
;
161 inode
->i_fop
= &cifs_file_ops
;
162 inode
->i_data
.a_ops
= &cifs_addr_ops
;
163 } else if (S_ISDIR(inode
->i_mode
)) {
164 cFYI(1, (" Directory inode"));
165 inode
->i_op
= &cifs_dir_inode_ops
;
166 inode
->i_fop
= &cifs_dir_ops
;
167 } else if (S_ISLNK(inode
->i_mode
)) {
168 cFYI(1, (" Symbolic Link inode "));
169 inode
->i_op
= &cifs_symlink_inode_ops
;
170 /* tmp_inode->i_fop = *//* do not need to set to anything */
172 cFYI(1, (" Init special inode "));
173 init_special_inode(inode
, inode
->i_mode
,
181 cifs_get_inode_info(struct inode
**pinode
, const unsigned char *search_path
,
182 FILE_ALL_INFO
* pfindData
, struct super_block
*sb
, int xid
)
185 struct cifsTconInfo
*pTcon
;
187 struct cifs_sb_info
*cifs_sb
= CIFS_SB(sb
);
191 pTcon
= cifs_sb
->tcon
;
192 cFYI(1,("Getting info on %s ", search_path
));
194 if((pfindData
== NULL
) && (*pinode
!= NULL
)) {
195 if(CIFS_I(*pinode
)->clientCanCacheRead
) {
196 cFYI(1,("No need to revalidate inode sizes on cached file "));
201 /* if file info not passed in then get it from server */
202 if(pfindData
== NULL
) {
203 buf
= kmalloc(sizeof(FILE_ALL_INFO
),GFP_KERNEL
);
206 pfindData
= (FILE_ALL_INFO
*)buf
;
207 /* could do find first instead but this returns more info */
208 rc
= CIFSSMBQPathInfo(xid
, pTcon
, search_path
, pfindData
,
211 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
213 if (rc
== -EREMOTE
) {
218 strnlen(search_path
, MAX_PATHCONF
) + 1,
220 if (tmp_path
== NULL
) {
226 strncpy(tmp_path
, pTcon
->treeName
, MAX_TREE_SIZE
);
227 strncat(tmp_path
, search_path
, MAX_PATHCONF
);
228 rc
= connect_to_dfs_path(xid
, pTcon
->ses
,
229 /* treename + */ tmp_path
,
232 /* BB fix up inode etc. */
239 struct cifsInodeInfo
*cifsInfo
;
240 __u32 attr
= le32_to_cpu(pfindData
->Attributes
);
243 if (*pinode
== NULL
) {
244 *pinode
= new_inode(sb
);
247 insert_inode_hash(*pinode
);
250 cifsInfo
= CIFS_I(inode
);
251 cifsInfo
->cifsAttrs
= attr
;
252 cFYI(1, (" Old time %ld ", cifsInfo
->time
));
253 cifsInfo
->time
= jiffies
;
254 cFYI(1, (" New time %ld ", cifsInfo
->time
));
256 /* blksize needs to be multiple of two. So safer to default to blksize
257 and blkbits set in superblock so 2**blkbits and blksize will match */
258 /* inode->i_blksize =
259 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
261 /* Linux can not store file creation time unfortunately so we ignore it */
263 cifs_NTtimeToUnix(le64_to_cpu(pfindData
->LastAccessTime
));
265 cifs_NTtimeToUnix(le64_to_cpu(pfindData
->LastWriteTime
));
267 cifs_NTtimeToUnix(le64_to_cpu(pfindData
->ChangeTime
));
269 (" Attributes came in as 0x%x ", attr
));
271 /* set default mode. will override for dirs below */
272 if(atomic_read(&cifsInfo
->inUse
) == 0)
273 /* new inode, can safely set these fields */
274 inode
->i_mode
= cifs_sb
->mnt_file_mode
;
276 if (attr
& ATTR_REPARSE
) {
277 /* Can IFLNK be set as it basically is on windows with IFREG or IFDIR? */
278 inode
->i_mode
|= S_IFLNK
;
279 } else if (attr
& ATTR_DIRECTORY
) {
280 /* override default perms since we do not do byte range locking on dirs */
281 inode
->i_mode
= cifs_sb
->mnt_dir_mode
;
282 inode
->i_mode
|= S_IFDIR
;
284 inode
->i_mode
|= S_IFREG
;
285 /* treat the dos attribute of read-only as read-only mode e.g. 555 */
286 if(cifsInfo
->cifsAttrs
& ATTR_READONLY
)
287 inode
->i_mode
&= ~(S_IWUGO
);
288 /* BB add code here - validate if device or weird share or device type? */
290 if(is_size_safe_to_change(cifsInfo
)) {
291 /* can not safely change the file size here if the
292 client is writing to it due to potential races */
294 i_size_write(inode
,le64_to_cpu(pfindData
->EndOfFile
));
296 /* 512 bytes (2**9) is the fake blocksize that must be used */
297 /* for this calculation */
298 inode
->i_blocks
= (512 - 1 + le64_to_cpu(pfindData
->AllocationSize
))
302 inode
->i_nlink
= le32_to_cpu(pfindData
->NumberOfLinks
);
304 /* BB fill in uid and gid here? with help from winbind?
305 or retrieve from NTFS stream extended attribute */
306 if(atomic_read(&cifsInfo
->inUse
) == 0) {
307 inode
->i_uid
= cifs_sb
->mnt_uid
;
308 inode
->i_gid
= cifs_sb
->mnt_gid
;
309 /* set so we do not keep refreshing these fields with
310 bad data after user has changed them in memory */
311 atomic_set(&cifsInfo
->inUse
,1);
314 if (S_ISREG(inode
->i_mode
)) {
315 cFYI(1, (" File inode "));
316 inode
->i_op
= &cifs_file_inode_ops
;
317 inode
->i_fop
= &cifs_file_ops
;
318 inode
->i_data
.a_ops
= &cifs_addr_ops
;
319 } else if (S_ISDIR(inode
->i_mode
)) {
320 cFYI(1, (" Directory inode "));
321 inode
->i_op
= &cifs_dir_inode_ops
;
322 inode
->i_fop
= &cifs_dir_ops
;
323 } else if (S_ISLNK(inode
->i_mode
)) {
324 cFYI(1, (" Symbolic Link inode "));
325 inode
->i_op
= &cifs_symlink_inode_ops
;
327 init_special_inode(inode
, inode
->i_mode
,
337 cifs_read_inode(struct inode
*inode
)
338 { /* gets root inode */
340 struct cifs_sb_info
*cifs_sb
;
342 cifs_sb
= CIFS_SB(inode
->i_sb
);
344 if (cifs_sb
->tcon
->ses
->capabilities
& CAP_UNIX
)
345 cifs_get_inode_info_unix(&inode
, "", inode
->i_sb
,xid
);
347 cifs_get_inode_info(&inode
, "", NULL
, inode
->i_sb
,xid
);
348 /* can not call macro FreeXid here since in a void func */
353 cifs_unlink(struct inode
*inode
, struct dentry
*direntry
)
357 struct cifs_sb_info
*cifs_sb
;
358 struct cifsTconInfo
*pTcon
;
359 char *full_path
= NULL
;
360 struct cifsInodeInfo
*cifsInode
;
361 FILE_BASIC_INFO
* pinfo_buf
;
363 cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode
));
367 cifs_sb
= CIFS_SB(inode
->i_sb
);
368 pTcon
= cifs_sb
->tcon
;
370 /* Unlink can be called from rename so we can not grab
371 the sem here since we deadlock otherwise */
372 /* down(&direntry->d_sb->s_vfs_rename_sem);*/
373 full_path
= build_path_from_dentry(direntry
);
374 /* up(&direntry->d_sb->s_vfs_rename_sem);*/
375 if(full_path
== NULL
) {
379 rc
= CIFSSMBDelFile(xid
, pTcon
, full_path
, cifs_sb
->local_nls
);
382 direntry
->d_inode
->i_nlink
--;
383 } else if (rc
== -ENOENT
) {
385 } else if (rc
== -ETXTBSY
) {
389 rc
= CIFSSMBOpen(xid
, pTcon
, full_path
, FILE_OPEN
, DELETE
,
390 CREATE_NOT_DIR
| CREATE_DELETE_ON_CLOSE
,
391 &netfid
, &oplock
, NULL
, cifs_sb
->local_nls
);
393 CIFSSMBRenameOpenFile(xid
,pTcon
,netfid
,
394 NULL
, cifs_sb
->local_nls
);
395 CIFSSMBClose(xid
, pTcon
, netfid
);
396 direntry
->d_inode
->i_nlink
--;
398 } else if (rc
== -EACCES
) {
399 /* try only if r/o attribute set in local lookup data? */
400 pinfo_buf
= (FILE_BASIC_INFO
*)kmalloc(sizeof(FILE_BASIC_INFO
),GFP_KERNEL
);
402 memset(pinfo_buf
,0,sizeof(FILE_BASIC_INFO
));
403 /* ATTRS set to normal clears r/o bit */
404 pinfo_buf
->Attributes
= cpu_to_le32(ATTR_NORMAL
);
405 rc
= CIFSSMBSetTimes(xid
, pTcon
, full_path
, pinfo_buf
,
410 rc
= CIFSSMBDelFile(xid
, pTcon
, full_path
, cifs_sb
->local_nls
);
412 direntry
->d_inode
->i_nlink
--;
413 } else if (rc
== -ETXTBSY
) {
417 rc
= CIFSSMBOpen(xid
, pTcon
, full_path
, FILE_OPEN
, DELETE
,
418 CREATE_NOT_DIR
| CREATE_DELETE_ON_CLOSE
,
419 &netfid
, &oplock
, NULL
, cifs_sb
->local_nls
);
421 CIFSSMBRenameOpenFile(xid
,pTcon
,netfid
,NULL
,cifs_sb
->local_nls
);
422 CIFSSMBClose(xid
, pTcon
, netfid
);
423 direntry
->d_inode
->i_nlink
--;
425 /* BB if rc = -ETXTBUSY goto the rename logic BB */
429 cifsInode
= CIFS_I(direntry
->d_inode
);
430 cifsInode
->time
= 0; /* will force revalidate to get info when needed */
431 direntry
->d_inode
->i_ctime
= inode
->i_ctime
= inode
->i_mtime
=
433 cifsInode
= CIFS_I(inode
);
434 cifsInode
->time
= 0; /* force revalidate of dir as well */
443 cifs_mkdir(struct inode
*inode
, struct dentry
*direntry
, int mode
)
447 struct cifs_sb_info
*cifs_sb
;
448 struct cifsTconInfo
*pTcon
;
449 char *full_path
= NULL
;
450 struct inode
*newinode
= NULL
;
452 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode
, inode
));
456 cifs_sb
= CIFS_SB(inode
->i_sb
);
457 pTcon
= cifs_sb
->tcon
;
459 down(&inode
->i_sb
->s_vfs_rename_sem
);
460 full_path
= build_path_from_dentry(direntry
);
461 up(&inode
->i_sb
->s_vfs_rename_sem
);
462 if(full_path
== NULL
) {
466 /* BB add setting the equivalent of mode via CreateX w/ACLs */
467 rc
= CIFSSMBMkDir(xid
, pTcon
, full_path
, cifs_sb
->local_nls
);
469 cFYI(1, ("cifs_mkdir returned 0x%x ", rc
));
473 if (pTcon
->ses
->capabilities
& CAP_UNIX
)
474 rc
= cifs_get_inode_info_unix(&newinode
, full_path
,
477 rc
= cifs_get_inode_info(&newinode
, full_path
,NULL
,
480 direntry
->d_op
= &cifs_dentry_ops
;
481 d_instantiate(direntry
, newinode
);
482 if(direntry
->d_inode
)
483 direntry
->d_inode
->i_nlink
= 2;
484 if (cifs_sb
->tcon
->ses
->capabilities
& CAP_UNIX
)
485 if(cifs_sb
->mnt_cifs_flags
& CIFS_MOUNT_SET_UID
) {
486 CIFSSMBUnixSetPerms(xid
, pTcon
, full_path
, mode
,
487 (__u64
)current
->euid
,
488 (__u64
)current
->egid
,
492 CIFSSMBUnixSetPerms(xid
, pTcon
, full_path
, mode
,
498 else { /* BB to be implemented via Windows secrty descriptors*/
499 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
510 cifs_rmdir(struct inode
*inode
, struct dentry
*direntry
)
514 struct cifs_sb_info
*cifs_sb
;
515 struct cifsTconInfo
*pTcon
;
516 char *full_path
= NULL
;
517 struct cifsInodeInfo
*cifsInode
;
519 cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode
));
523 cifs_sb
= CIFS_SB(inode
->i_sb
);
524 pTcon
= cifs_sb
->tcon
;
526 down(&inode
->i_sb
->s_vfs_rename_sem
);
527 full_path
= build_path_from_dentry(direntry
);
528 up(&inode
->i_sb
->s_vfs_rename_sem
);
529 if(full_path
== NULL
) {
534 rc
= CIFSSMBRmDir(xid
, pTcon
, full_path
, cifs_sb
->local_nls
);
538 i_size_write(direntry
->d_inode
,0);
539 direntry
->d_inode
->i_nlink
= 0;
542 cifsInode
= CIFS_I(direntry
->d_inode
);
543 cifsInode
->time
= 0; /* force revalidate to go get info when needed */
544 direntry
->d_inode
->i_ctime
= inode
->i_ctime
= inode
->i_mtime
=
554 cifs_rename(struct inode
*source_inode
, struct dentry
*source_direntry
,
555 struct inode
*target_inode
, struct dentry
*target_direntry
)
559 struct cifs_sb_info
*cifs_sb_source
;
560 struct cifs_sb_info
*cifs_sb_target
;
561 struct cifsTconInfo
*pTcon
;
567 cifs_sb_target
= CIFS_SB(target_inode
->i_sb
);
568 cifs_sb_source
= CIFS_SB(source_inode
->i_sb
);
569 pTcon
= cifs_sb_source
->tcon
;
571 if (pTcon
!= cifs_sb_target
->tcon
) {
573 return -EXDEV
; /* BB actually could be allowed if same server, but
574 different share. Might eventually add support for this */
577 /* we already have the rename sem so we do not need
578 to grab it again here to protect the path integrity */
579 fromName
= build_path_from_dentry(source_direntry
);
580 toName
= build_path_from_dentry(target_direntry
);
581 if((fromName
== NULL
) || (toName
== NULL
)) {
583 goto cifs_rename_exit
;
586 rc
= CIFSSMBRename(xid
, pTcon
, fromName
, toName
,
587 cifs_sb_source
->local_nls
);
589 /* check if they are the same file
590 because rename of hardlinked files is a noop */
591 FILE_UNIX_BASIC_INFO
* info_buf_source
;
592 FILE_UNIX_BASIC_INFO
* info_buf_target
;
595 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO
),GFP_KERNEL
);
596 if(info_buf_source
!= NULL
) {
597 info_buf_target
= info_buf_source
+1;
598 rc
= CIFSSMBUnixQPathInfo(xid
, pTcon
, fromName
,
599 info_buf_source
, cifs_sb_source
->local_nls
);
601 rc
= CIFSSMBUnixQPathInfo(xid
,pTcon
,toName
,
603 cifs_sb_target
->local_nls
);
606 (info_buf_source
->UniqueId
==
607 info_buf_target
->UniqueId
)) {
608 /* do not rename since the files are hardlinked
611 /* we either can not tell the files are hardlinked
612 (as with Windows servers) or files are not hardlinked
613 so delete the target manually before renaming to
614 follow POSIX rather than Windows semantics */
615 cifs_unlink(target_inode
, target_direntry
);
616 rc
= CIFSSMBRename(xid
, pTcon
, fromName
, toName
,
617 cifs_sb_source
->local_nls
);
619 kfree(info_buf_source
);
620 } /* if we can not get memory just leave rc as EEXIST */
623 if((rc
== -EIO
)||(rc
== -EEXIST
)) {
627 rc
= CIFSSMBOpen(xid
, pTcon
, fromName
, FILE_OPEN
, GENERIC_READ
,
629 &netfid
, &oplock
, NULL
, cifs_sb_source
->local_nls
);
631 CIFSSMBRenameOpenFile(xid
,pTcon
,netfid
,
632 toName
, cifs_sb_source
->local_nls
);
633 CIFSSMBClose(xid
, pTcon
, netfid
);
648 cifs_revalidate(struct dentry
*direntry
)
653 struct cifs_sb_info
*cifs_sb
;
654 struct cifsInodeInfo
*cifsInode
;
656 struct timespec local_mtime
;
657 int invalidate_inode
= FALSE
;
659 if(direntry
->d_inode
== NULL
)
662 cifsInode
= CIFS_I(direntry
->d_inode
);
664 if(cifsInode
== NULL
)
667 /* no sense revalidating inode info on file that no one can write */
668 if(CIFS_I(direntry
->d_inode
)->clientCanCacheRead
)
673 cifs_sb
= CIFS_SB(direntry
->d_sb
);
675 /* can not safely grab the rename sem here if
676 rename calls revalidate since that would deadlock */
677 full_path
= build_path_from_dentry(direntry
);
678 if(full_path
== NULL
) {
683 ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
684 full_path
, direntry
->d_inode
,
685 direntry
->d_inode
->i_count
.counter
, direntry
,
686 direntry
->d_time
, jiffies
));
688 if (cifsInode
->time
== 0){
689 /* was set to zero previously to force revalidate */
690 } else if (time_before(jiffies
, cifsInode
->time
+ HZ
) && lookupCacheEnabled
) {
691 if((S_ISREG(direntry
->d_inode
->i_mode
) == 0) ||
692 (direntry
->d_inode
->i_nlink
== 1)) {
698 cFYI(1,("Have to revalidate file due to hardlinks"));
702 /* save mtime and size */
703 local_mtime
= direntry
->d_inode
->i_mtime
;
704 local_size
= direntry
->d_inode
->i_size
;
706 if (cifs_sb
->tcon
->ses
->capabilities
& CAP_UNIX
) {
707 rc
= cifs_get_inode_info_unix(&direntry
->d_inode
, full_path
,
710 cFYI(1,("error on getting revalidate info %d",rc
));
712 rc = 0; */ /* BB should we cache info on certain errors? */
715 rc
= cifs_get_inode_info(&direntry
->d_inode
, full_path
, NULL
,
718 cFYI(1,("error on getting revalidate info %d",rc
));
720 rc = 0; */ /* BB should we cache info on certain errors? */
723 /* should we remap certain errors, access denied?, to zero */
725 /* if not oplocked, we invalidate inode pages if mtime
726 or file size had changed on server */
728 if(timespec_equal(&local_mtime
,&direntry
->d_inode
->i_mtime
) &&
729 (local_size
== direntry
->d_inode
->i_size
)) {
730 cFYI(1,("cifs_revalidate - inode unchanged"));
732 /* file may have changed on server */
733 if(cifsInode
->clientCanCacheRead
) {
734 /* no need to invalidate inode pages since we were
735 the only ones who could have modified the file and
736 the server copy is staler than ours */
738 invalidate_inode
= TRUE
;
742 /* can not grab this sem since kernel filesys locking
743 documentation indicates i_sem may be taken by the kernel
744 on lookup and rename which could deadlock if we grab
745 the i_sem here as well */
746 /* down(&direntry->d_inode->i_sem);*/
747 /* need to write out dirty pages here */
748 if(direntry
->d_inode
->i_mapping
) {
749 /* do we need to lock inode until after invalidate completes below? */
750 filemap_fdatawrite(direntry
->d_inode
->i_mapping
);
752 if(invalidate_inode
) {
753 filemap_fdatawait(direntry
->d_inode
->i_mapping
);
754 /* may eventually have to do this for open files too */
755 if(list_empty(&(cifsInode
->openFileList
))) {
756 /* Has changed on server - flush read ahead pages */
757 cFYI(1,("Invalidating read ahead data on closed file"));
758 invalidate_remote_inode(direntry
->d_inode
);
761 /* up(&direntry->d_inode->i_sem);*/
770 int cifs_getattr(struct vfsmount
*mnt
, struct dentry
*dentry
, struct kstat
*stat
)
772 int err
= cifs_revalidate(dentry
);
774 generic_fillattr(dentry
->d_inode
, stat
);
778 static int cifs_truncate_page(struct address_space
*mapping
, loff_t from
)
780 pgoff_t index
= from
>> PAGE_CACHE_SHIFT
;
781 unsigned offset
= from
& (PAGE_CACHE_SIZE
-1);
786 page
= grab_cache_page(mapping
, index
);
790 kaddr
= kmap_atomic(page
, KM_USER0
);
791 memset(kaddr
+ offset
, 0, PAGE_CACHE_SIZE
- offset
);
792 flush_dcache_page(page
);
793 kunmap_atomic(kaddr
, KM_USER0
);
795 page_cache_release(page
);
800 cifs_setattr(struct dentry
*direntry
, struct iattr
*attrs
)
803 struct cifs_sb_info
*cifs_sb
;
804 struct cifsTconInfo
*pTcon
;
805 char *full_path
= NULL
;
808 struct cifsFileInfo
*open_file
= NULL
;
809 FILE_BASIC_INFO time_buf
;
810 int set_time
= FALSE
;
811 __u64 mode
= 0xFFFFFFFFFFFFFFFFULL
;
812 __u64 uid
= 0xFFFFFFFFFFFFFFFFULL
;
813 __u64 gid
= 0xFFFFFFFFFFFFFFFFULL
;
814 struct cifsInodeInfo
*cifsInode
;
815 struct list_head
* tmp
;
820 (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
821 direntry
->d_name
.name
, attrs
->ia_valid
));
822 cifs_sb
= CIFS_SB(direntry
->d_inode
->i_sb
);
823 pTcon
= cifs_sb
->tcon
;
825 down(&direntry
->d_sb
->s_vfs_rename_sem
);
826 full_path
= build_path_from_dentry(direntry
);
827 up(&direntry
->d_sb
->s_vfs_rename_sem
);
828 if(full_path
== NULL
) {
832 cifsInode
= CIFS_I(direntry
->d_inode
);
834 /* BB check if we need to refresh inode from server now ? BB */
836 /* need to flush data before changing file size on server */
837 filemap_fdatawrite(direntry
->d_inode
->i_mapping
);
838 filemap_fdatawait(direntry
->d_inode
->i_mapping
);
840 if (attrs
->ia_valid
& ATTR_SIZE
) {
841 read_lock(&GlobalSMBSeslock
);
842 /* To avoid spurious oplock breaks from server, in the case
843 of inodes that we already have open, avoid doing path
844 based setting of file size if we can do it by handle.
845 This keeps our caching token (oplock) and avoids
846 timeouts when the local oplock break takes longer to flush
847 writebehind data than the SMB timeout for the SetPathInfo
848 request would allow */
849 list_for_each(tmp
, &cifsInode
->openFileList
) {
850 open_file
= list_entry(tmp
,struct cifsFileInfo
, flist
);
851 /* We check if file is open for writing first */
852 if((open_file
->pfile
) &&
853 ((open_file
->pfile
->f_flags
& O_RDWR
) ||
854 (open_file
->pfile
->f_flags
& O_WRONLY
))) {
855 if(open_file
->invalidHandle
== FALSE
) {
856 /* we found a valid, writeable network file
857 handle to use to try to set the file size */
858 __u16 nfid
= open_file
->netfid
;
859 __u32 npid
= open_file
->pid
;
860 read_unlock(&GlobalSMBSeslock
);
862 rc
= CIFSSMBSetFileSize(xid
, pTcon
, attrs
->ia_size
,
864 cFYI(1,("SetFileSize by handle (setattrs) rc = %d",rc
));
865 /* Do not need reopen and retry on EAGAIN since we will
866 retry by pathname below */
868 break; /* now that we found one valid file handle no
869 sense continuing to loop trying others */
874 read_unlock(&GlobalSMBSeslock
);
879 /* Set file size by pathname rather than by handle either
880 because no valid, writeable file handle for it was found or
881 because there was an error setting it by handle */
882 rc
= CIFSSMBSetEOF(xid
, pTcon
, full_path
, attrs
->ia_size
,FALSE
,
884 cFYI(1,(" SetEOF by path (setattrs) rc = %d",rc
));
887 /* Server is ok setting allocation size implicitly - no need to call: */
888 /*CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
891 rc
= vmtruncate(direntry
->d_inode
, attrs
->ia_size
);
892 cifs_truncate_page(direntry
->d_inode
->i_mapping
, direntry
->d_inode
->i_size
);
895 if (attrs
->ia_valid
& ATTR_UID
) {
896 cFYI(1, (" CIFS - UID changed to %d", attrs
->ia_uid
));
898 /* entry->uid = cpu_to_le16(attr->ia_uid); */
900 if (attrs
->ia_valid
& ATTR_GID
) {
901 cFYI(1, (" CIFS - GID changed to %d", attrs
->ia_gid
));
903 /* entry->gid = cpu_to_le16(attr->ia_gid); */
906 time_buf
.Attributes
= 0;
907 if (attrs
->ia_valid
& ATTR_MODE
) {
908 cFYI(1, (" CIFS - Mode changed to 0x%x", attrs
->ia_mode
));
909 mode
= attrs
->ia_mode
;
910 /* entry->mode = cpu_to_le16(attr->ia_mode); */
913 if ((cifs_sb
->tcon
->ses
->capabilities
& CAP_UNIX
)
914 && (attrs
->ia_valid
& (ATTR_MODE
| ATTR_GID
| ATTR_UID
)))
915 rc
= CIFSSMBUnixSetPerms(xid
, pTcon
, full_path
, mode
, uid
, gid
,
916 0 /* dev_t */, cifs_sb
->local_nls
);
917 else if (attrs
->ia_valid
& ATTR_MODE
) {
918 if((mode
& S_IWUGO
) == 0) /* not writeable */ {
919 if((cifsInode
->cifsAttrs
& ATTR_READONLY
) == 0)
920 time_buf
.Attributes
=
921 cpu_to_le32(cifsInode
->cifsAttrs
| ATTR_READONLY
);
922 } else if((mode
& S_IWUGO
) == S_IWUGO
) {
923 if(cifsInode
->cifsAttrs
& ATTR_READONLY
)
924 time_buf
.Attributes
=
925 cpu_to_le32(cifsInode
->cifsAttrs
& (~ATTR_READONLY
));
927 /* BB to be implemented - via Windows security descriptors or streams */
928 /* CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,uid,gid,cifs_sb->local_nls);*/
931 if (attrs
->ia_valid
& ATTR_ATIME
) {
933 time_buf
.LastAccessTime
=
934 cpu_to_le64(cifs_UnixTimeToNT(attrs
->ia_atime
));
936 time_buf
.LastAccessTime
= 0;
938 if (attrs
->ia_valid
& ATTR_MTIME
) {
940 time_buf
.LastWriteTime
=
941 cpu_to_le64(cifs_UnixTimeToNT(attrs
->ia_mtime
));
943 time_buf
.LastWriteTime
= 0;
945 if (attrs
->ia_valid
& ATTR_CTIME
) {
947 cFYI(1, (" CIFS - CTIME changed ")); /* BB probably do not need */
948 time_buf
.ChangeTime
=
949 cpu_to_le64(cifs_UnixTimeToNT(attrs
->ia_ctime
));
951 time_buf
.ChangeTime
= 0;
953 if (set_time
|| time_buf
.Attributes
) {
954 /* BB what if setting one attribute fails
955 (such as size) but time setting works */
956 time_buf
.CreationTime
= 0; /* do not change */
957 /* In the future we should experiment - try setting timestamps
958 via Handle (SetFileInfo) instead of by path */
959 rc
= CIFSSMBSetTimes(xid
, pTcon
, full_path
, &time_buf
,
963 /* do not need local check to inode_check_ok since the server does that */
965 rc
= inode_setattr(direntry
->d_inode
, attrs
);
973 cifs_delete_inode(struct inode
*inode
)
975 cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode
));
976 /* may have to add back in if and when safe distributed caching of
977 directories added e.g. via FindNotify */