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 /* Is an i_ino of zero legal? */
89 /* Are there sanity checks we can use to ensure that
90 the server is really filling in that field? */
91 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
93 (unsigned long)findData.UniqueId;
94 } /* note ino incremented to unique num in new_inode */
95 insert_inode_hash(*pinode);
99 cifsInfo = CIFS_I(inode);
101 cFYI(1, (" Old time %ld ", cifsInfo->time));
102 cifsInfo->time = jiffies;
103 cFYI(1, (" New time %ld ", cifsInfo->time));
104 atomic_set(&cifsInfo->inUse,1); /* ok to set on every refresh of inode */
107 cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
109 cifs_NTtimeToUnix(le64_to_cpu
110 (findData.LastModificationTime));
112 cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
113 inode->i_mode = le64_to_cpu(findData.Permissions);
114 if (type == UNIX_FILE) {
115 inode->i_mode |= S_IFREG;
116 } else if (type == UNIX_SYMLINK) {
117 inode->i_mode |= S_IFLNK;
118 } else if (type == UNIX_DIR) {
119 inode->i_mode |= S_IFDIR;
120 } else if (type == UNIX_CHARDEV) {
121 inode->i_mode |= S_IFCHR;
122 inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
123 le64_to_cpu(findData.DevMinor) & MINORMASK);
124 } else if (type == UNIX_BLOCKDEV) {
125 inode->i_mode |= S_IFBLK;
126 inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
127 le64_to_cpu(findData.DevMinor) & MINORMASK);
128 } else if (type == UNIX_FIFO) {
129 inode->i_mode |= S_IFIFO;
130 } else if (type == UNIX_SOCKET) {
131 inode->i_mode |= S_IFSOCK;
133 inode->i_uid = le64_to_cpu(findData.Uid);
134 inode->i_gid = le64_to_cpu(findData.Gid);
135 inode->i_nlink = le64_to_cpu(findData.Nlinks);
137 if(is_size_safe_to_change(cifsInfo)) {
138 /* can not safely change the file size here if the
139 client is writing to it due to potential races */
141 i_size_write(inode, end_of_file);
142 /* blksize needs to be multiple of two. So safer to default to blksize
143 and blkbits set in superblock so 2**blkbits and blksize will match */
144 /* inode->i_blksize =
145 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
147 /* This seems incredibly stupid but it turns out that
148 i_blocks is not related to (i_size / i_blksize), instead a
149 size of 512 is required to be used for calculating num blocks */
153 (inode->i_blksize - 1 + num_of_bytes) >> inode->i_blkbits;*/
155 /* 512 bytes (2**9) is the fake blocksize that must be used */
156 /* for this calculation */
157 inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
160 if (num_of_bytes < end_of_file)
161 cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
163 ("Size %ld and blocks %ld ",
164 (unsigned long) inode->i_size, inode->i_blocks));
165 if (S_ISREG(inode->i_mode)) {
166 cFYI(1, (" File inode "));
167 inode->i_op = &cifs_file_inode_ops;
168 inode->i_fop = &cifs_file_ops;
169 inode->i_data.a_ops = &cifs_addr_ops;
170 } else if (S_ISDIR(inode->i_mode)) {
171 cFYI(1, (" Directory inode"));
172 inode->i_op = &cifs_dir_inode_ops;
173 inode->i_fop = &cifs_dir_ops;
174 } else if (S_ISLNK(inode->i_mode)) {
175 cFYI(1, (" Symbolic Link inode "));
176 inode->i_op = &cifs_symlink_inode_ops;
177 /* tmp_inode->i_fop = *//* do not need to set to anything */
179 cFYI(1, (" Init special inode "));
180 init_special_inode(inode, inode->i_mode,
188 cifs_get_inode_info(struct inode **pinode, const unsigned char *search_path,
189 FILE_ALL_INFO * pfindData, struct super_block *sb, int xid)
192 struct cifsTconInfo *pTcon;
194 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
198 pTcon = cifs_sb->tcon;
199 cFYI(1,("Getting info on %s ", search_path));
201 if((pfindData == NULL) && (*pinode != NULL)) {
202 if(CIFS_I(*pinode)->clientCanCacheRead) {
203 cFYI(1,("No need to revalidate inode sizes on cached file "));
208 /* if file info not passed in then get it from server */
209 if(pfindData == NULL) {
210 buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL);
213 pfindData = (FILE_ALL_INFO *)buf;
214 /* could do find first instead but this returns more info */
215 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
218 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
220 if (rc == -EREMOTE) {
225 strnlen(search_path, MAX_PATHCONF) + 1,
227 if (tmp_path == NULL) {
233 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
234 strncat(tmp_path, search_path, MAX_PATHCONF);
235 rc = connect_to_dfs_path(xid, pTcon->ses,
236 /* treename + */ tmp_path,
239 /* BB fix up inode etc. */
246 struct cifsInodeInfo *cifsInfo;
247 __u32 attr = le32_to_cpu(pfindData->Attributes);
250 if (*pinode == NULL) {
251 *pinode = new_inode(sb);
254 /* Is an i_ino of zero legal? */
255 /* Are there sanity checks we can use to ensure that
256 the server is really filling in that field? */
258 /* We can not use the IndexNumber from either
259 Windows or Samba as it is frequently set to zero */
260 /* There may be higher info levels that work but
261 Are there Windows server or network appliances
262 for which IndexNumber field is not guaranteed unique? */
264 /* if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
266 (unsigned long)pfindData->IndexNumber;
267 } */ /*NB: ino incremented to unique num in new_inode*/
269 insert_inode_hash(*pinode);
272 cifsInfo = CIFS_I(inode);
273 cifsInfo->cifsAttrs = attr;
274 cFYI(1, (" Old time %ld ", cifsInfo->time));
275 cifsInfo->time = jiffies;
276 cFYI(1, (" New time %ld ", cifsInfo->time));
278 /* blksize needs to be multiple of two. So safer to default to blksize
279 and blkbits set in superblock so 2**blkbits and blksize will match */
280 /* inode->i_blksize =
281 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
283 /* Linux can not store file creation time unfortunately so we ignore it */
285 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
287 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
289 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
291 (" Attributes came in as 0x%x ", attr));
293 /* set default mode. will override for dirs below */
294 if(atomic_read(&cifsInfo->inUse) == 0)
295 /* new inode, can safely set these fields */
296 inode->i_mode = cifs_sb->mnt_file_mode;
298 /* if (attr & ATTR_REPARSE) */
299 /* We no longer handle these as symlinks because we could not */
300 /* follow them due to the absolute path with drive letter */
301 if (attr & ATTR_DIRECTORY) {
302 /* override default perms since we do not do byte range locking on dirs */
303 inode->i_mode = cifs_sb->mnt_dir_mode;
304 inode->i_mode |= S_IFDIR;
306 inode->i_mode |= S_IFREG;
307 /* treat the dos attribute of read-only as read-only mode e.g. 555 */
308 if(cifsInfo->cifsAttrs & ATTR_READONLY)
309 inode->i_mode &= ~(S_IWUGO);
310 /* BB add code here - validate if device or weird share or device type? */
312 if(is_size_safe_to_change(cifsInfo)) {
313 /* can not safely change the file size here if the
314 client is writing to it due to potential races */
316 i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
318 /* 512 bytes (2**9) is the fake blocksize that must be used */
319 /* for this calculation */
320 inode->i_blocks = (512 - 1 + le64_to_cpu(pfindData->AllocationSize))
324 inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
326 /* BB fill in uid and gid here? with help from winbind?
327 or retrieve from NTFS stream extended attribute */
328 if(atomic_read(&cifsInfo->inUse) == 0) {
329 inode->i_uid = cifs_sb->mnt_uid;
330 inode->i_gid = cifs_sb->mnt_gid;
331 /* set so we do not keep refreshing these fields with
332 bad data after user has changed them in memory */
333 atomic_set(&cifsInfo->inUse,1);
336 if (S_ISREG(inode->i_mode)) {
337 cFYI(1, (" File inode "));
338 inode->i_op = &cifs_file_inode_ops;
339 inode->i_fop = &cifs_file_ops;
340 inode->i_data.a_ops = &cifs_addr_ops;
341 } else if (S_ISDIR(inode->i_mode)) {
342 cFYI(1, (" Directory inode "));
343 inode->i_op = &cifs_dir_inode_ops;
344 inode->i_fop = &cifs_dir_ops;
345 } else if (S_ISLNK(inode->i_mode)) {
346 cFYI(1, (" Symbolic Link inode "));
347 inode->i_op = &cifs_symlink_inode_ops;
349 init_special_inode(inode, inode->i_mode,
359 cifs_read_inode(struct inode *inode)
360 { /* gets root inode */
362 struct cifs_sb_info *cifs_sb;
364 cifs_sb = CIFS_SB(inode->i_sb);
366 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
367 cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
369 cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
370 /* can not call macro FreeXid here since in a void func */
375 cifs_unlink(struct inode *inode, struct dentry *direntry)
379 struct cifs_sb_info *cifs_sb;
380 struct cifsTconInfo *pTcon;
381 char *full_path = NULL;
382 struct cifsInodeInfo *cifsInode;
383 FILE_BASIC_INFO * pinfo_buf;
385 cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
389 cifs_sb = CIFS_SB(inode->i_sb);
390 pTcon = cifs_sb->tcon;
392 /* Unlink can be called from rename so we can not grab
393 the sem here since we deadlock otherwise */
394 /* down(&direntry->d_sb->s_vfs_rename_sem);*/
395 full_path = build_path_from_dentry(direntry);
396 /* up(&direntry->d_sb->s_vfs_rename_sem);*/
397 if(full_path == NULL) {
401 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
404 direntry->d_inode->i_nlink--;
405 } else if (rc == -ENOENT) {
407 } else if (rc == -ETXTBSY) {
411 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
412 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
413 &netfid, &oplock, NULL, cifs_sb->local_nls);
415 CIFSSMBRenameOpenFile(xid,pTcon,netfid,
416 NULL, cifs_sb->local_nls);
417 CIFSSMBClose(xid, pTcon, netfid);
418 direntry->d_inode->i_nlink--;
420 } else if (rc == -EACCES) {
421 /* try only if r/o attribute set in local lookup data? */
422 pinfo_buf = (FILE_BASIC_INFO *)kmalloc(sizeof(FILE_BASIC_INFO),GFP_KERNEL);
424 memset(pinfo_buf,0,sizeof(FILE_BASIC_INFO));
425 /* ATTRS set to normal clears r/o bit */
426 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
427 rc = CIFSSMBSetTimes(xid, pTcon, full_path, pinfo_buf,
432 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls);
434 direntry->d_inode->i_nlink--;
435 } else if (rc == -ETXTBSY) {
439 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
440 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
441 &netfid, &oplock, NULL, cifs_sb->local_nls);
443 CIFSSMBRenameOpenFile(xid,pTcon,netfid,NULL,cifs_sb->local_nls);
444 CIFSSMBClose(xid, pTcon, netfid);
445 direntry->d_inode->i_nlink--;
447 /* BB if rc = -ETXTBUSY goto the rename logic BB */
451 cifsInode = CIFS_I(direntry->d_inode);
452 cifsInode->time = 0; /* will force revalidate to get info when needed */
453 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
455 cifsInode = CIFS_I(inode);
456 cifsInode->time = 0; /* force revalidate of dir as well */
465 cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
469 struct cifs_sb_info *cifs_sb;
470 struct cifsTconInfo *pTcon;
471 char *full_path = NULL;
472 struct inode *newinode = NULL;
474 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
478 cifs_sb = CIFS_SB(inode->i_sb);
479 pTcon = cifs_sb->tcon;
481 down(&inode->i_sb->s_vfs_rename_sem);
482 full_path = build_path_from_dentry(direntry);
483 up(&inode->i_sb->s_vfs_rename_sem);
484 if(full_path == NULL) {
488 /* BB add setting the equivalent of mode via CreateX w/ACLs */
489 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls);
491 cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
495 if (pTcon->ses->capabilities & CAP_UNIX)
496 rc = cifs_get_inode_info_unix(&newinode, full_path,
499 rc = cifs_get_inode_info(&newinode, full_path,NULL,
502 direntry->d_op = &cifs_dentry_ops;
503 d_instantiate(direntry, newinode);
504 if(direntry->d_inode)
505 direntry->d_inode->i_nlink = 2;
506 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
507 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
508 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
509 (__u64)current->euid,
510 (__u64)current->egid,
514 CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
520 else { /* BB to be implemented via Windows secrty descriptors*/
521 /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/
532 cifs_rmdir(struct inode *inode, struct dentry *direntry)
536 struct cifs_sb_info *cifs_sb;
537 struct cifsTconInfo *pTcon;
538 char *full_path = NULL;
539 struct cifsInodeInfo *cifsInode;
541 cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
545 cifs_sb = CIFS_SB(inode->i_sb);
546 pTcon = cifs_sb->tcon;
548 down(&inode->i_sb->s_vfs_rename_sem);
549 full_path = build_path_from_dentry(direntry);
550 up(&inode->i_sb->s_vfs_rename_sem);
551 if(full_path == NULL) {
556 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls);
560 i_size_write(direntry->d_inode,0);
561 direntry->d_inode->i_nlink = 0;
564 cifsInode = CIFS_I(direntry->d_inode);
565 cifsInode->time = 0; /* force revalidate to go get info when needed */
566 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
576 cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
577 struct inode *target_inode, struct dentry *target_direntry)
581 struct cifs_sb_info *cifs_sb_source;
582 struct cifs_sb_info *cifs_sb_target;
583 struct cifsTconInfo *pTcon;
589 cifs_sb_target = CIFS_SB(target_inode->i_sb);
590 cifs_sb_source = CIFS_SB(source_inode->i_sb);
591 pTcon = cifs_sb_source->tcon;
593 if (pTcon != cifs_sb_target->tcon) {
595 return -EXDEV; /* BB actually could be allowed if same server, but
596 different share. Might eventually add support for this */
599 /* we already have the rename sem so we do not need
600 to grab it again here to protect the path integrity */
601 fromName = build_path_from_dentry(source_direntry);
602 toName = build_path_from_dentry(target_direntry);
603 if((fromName == NULL) || (toName == NULL)) {
605 goto cifs_rename_exit;
608 rc = CIFSSMBRename(xid, pTcon, fromName, toName,
609 cifs_sb_source->local_nls);
611 /* check if they are the same file
612 because rename of hardlinked files is a noop */
613 FILE_UNIX_BASIC_INFO * info_buf_source;
614 FILE_UNIX_BASIC_INFO * info_buf_target;
617 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),GFP_KERNEL);
618 if(info_buf_source != NULL) {
619 info_buf_target = info_buf_source+1;
620 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
621 info_buf_source, cifs_sb_source->local_nls);
623 rc = CIFSSMBUnixQPathInfo(xid,pTcon,toName,
625 cifs_sb_target->local_nls);
628 (info_buf_source->UniqueId ==
629 info_buf_target->UniqueId)) {
630 /* do not rename since the files are hardlinked
633 /* we either can not tell the files are hardlinked
634 (as with Windows servers) or files are not hardlinked
635 so delete the target manually before renaming to
636 follow POSIX rather than Windows semantics */
637 cifs_unlink(target_inode, target_direntry);
638 rc = CIFSSMBRename(xid, pTcon, fromName, toName,
639 cifs_sb_source->local_nls);
641 kfree(info_buf_source);
642 } /* if we can not get memory just leave rc as EEXIST */
645 if((rc == -EIO)||(rc == -EEXIST)) {
649 rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
651 &netfid, &oplock, NULL, cifs_sb_source->local_nls);
653 CIFSSMBRenameOpenFile(xid,pTcon,netfid,
654 toName, cifs_sb_source->local_nls);
655 CIFSSMBClose(xid, pTcon, netfid);
670 cifs_revalidate(struct dentry *direntry)
675 struct cifs_sb_info *cifs_sb;
676 struct cifsInodeInfo *cifsInode;
678 struct timespec local_mtime;
679 int invalidate_inode = FALSE;
681 if(direntry->d_inode == NULL)
684 cifsInode = CIFS_I(direntry->d_inode);
686 if(cifsInode == NULL)
689 /* no sense revalidating inode info on file that no one can write */
690 if(CIFS_I(direntry->d_inode)->clientCanCacheRead)
695 cifs_sb = CIFS_SB(direntry->d_sb);
697 /* can not safely grab the rename sem here if
698 rename calls revalidate since that would deadlock */
699 full_path = build_path_from_dentry(direntry);
700 if(full_path == NULL) {
705 ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld",
706 full_path, direntry->d_inode,
707 direntry->d_inode->i_count.counter, direntry,
708 direntry->d_time, jiffies));
710 if (cifsInode->time == 0){
711 /* was set to zero previously to force revalidate */
712 } else if (time_before(jiffies, cifsInode->time + HZ) && lookupCacheEnabled) {
713 if((S_ISREG(direntry->d_inode->i_mode) == 0) ||
714 (direntry->d_inode->i_nlink == 1)) {
720 cFYI(1,("Have to revalidate file due to hardlinks"));
724 /* save mtime and size */
725 local_mtime = direntry->d_inode->i_mtime;
726 local_size = direntry->d_inode->i_size;
728 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
729 rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
732 cFYI(1,("error on getting revalidate info %d",rc));
734 rc = 0; */ /* BB should we cache info on certain errors? */
737 rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
740 cFYI(1,("error on getting revalidate info %d",rc));
742 rc = 0; */ /* BB should we cache info on certain errors? */
745 /* should we remap certain errors, access denied?, to zero */
747 /* if not oplocked, we invalidate inode pages if mtime
748 or file size had changed on server */
750 if(timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
751 (local_size == direntry->d_inode->i_size)) {
752 cFYI(1,("cifs_revalidate - inode unchanged"));
754 /* file may have changed on server */
755 if(cifsInode->clientCanCacheRead) {
756 /* no need to invalidate inode pages since we were
757 the only ones who could have modified the file and
758 the server copy is staler than ours */
760 invalidate_inode = TRUE;
764 /* can not grab this sem since kernel filesys locking
765 documentation indicates i_sem may be taken by the kernel
766 on lookup and rename which could deadlock if we grab
767 the i_sem here as well */
768 /* down(&direntry->d_inode->i_sem);*/
769 /* need to write out dirty pages here */
770 if(direntry->d_inode->i_mapping) {
771 /* do we need to lock inode until after invalidate completes below? */
772 filemap_fdatawrite(direntry->d_inode->i_mapping);
774 if(invalidate_inode) {
775 filemap_fdatawait(direntry->d_inode->i_mapping);
776 /* may eventually have to do this for open files too */
777 if(list_empty(&(cifsInode->openFileList))) {
778 /* Has changed on server - flush read ahead pages */
779 cFYI(1,("Invalidating read ahead data on closed file"));
780 invalidate_remote_inode(direntry->d_inode);
783 /* up(&direntry->d_inode->i_sem);*/
792 int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
794 int err = cifs_revalidate(dentry);
796 generic_fillattr(dentry->d_inode, stat);
800 static int cifs_truncate_page(struct address_space *mapping, loff_t from)
802 pgoff_t index = from >> PAGE_CACHE_SHIFT;
803 unsigned offset = from & (PAGE_CACHE_SIZE-1);
808 page = grab_cache_page(mapping, index);
812 kaddr = kmap_atomic(page, KM_USER0);
813 memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
814 flush_dcache_page(page);
815 kunmap_atomic(kaddr, KM_USER0);
817 page_cache_release(page);
822 cifs_setattr(struct dentry *direntry, struct iattr *attrs)
825 struct cifs_sb_info *cifs_sb;
826 struct cifsTconInfo *pTcon;
827 char *full_path = NULL;
830 struct cifsFileInfo *open_file = NULL;
831 FILE_BASIC_INFO time_buf;
832 int set_time = FALSE;
833 __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
834 __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
835 __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
836 struct cifsInodeInfo *cifsInode;
837 struct list_head * tmp;
842 (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
843 direntry->d_name.name, attrs->ia_valid));
844 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
845 pTcon = cifs_sb->tcon;
847 down(&direntry->d_sb->s_vfs_rename_sem);
848 full_path = build_path_from_dentry(direntry);
849 up(&direntry->d_sb->s_vfs_rename_sem);
850 if(full_path == NULL) {
854 cifsInode = CIFS_I(direntry->d_inode);
856 /* BB check if we need to refresh inode from server now ? BB */
858 /* need to flush data before changing file size on server */
859 filemap_fdatawrite(direntry->d_inode->i_mapping);
860 filemap_fdatawait(direntry->d_inode->i_mapping);
862 if (attrs->ia_valid & ATTR_SIZE) {
863 read_lock(&GlobalSMBSeslock);
864 /* To avoid spurious oplock breaks from server, in the case
865 of inodes that we already have open, avoid doing path
866 based setting of file size if we can do it by handle.
867 This keeps our caching token (oplock) and avoids
868 timeouts when the local oplock break takes longer to flush
869 writebehind data than the SMB timeout for the SetPathInfo
870 request would allow */
871 list_for_each(tmp, &cifsInode->openFileList) {
872 open_file = list_entry(tmp,struct cifsFileInfo, flist);
873 /* We check if file is open for writing first */
874 if((open_file->pfile) &&
875 ((open_file->pfile->f_flags & O_RDWR) ||
876 (open_file->pfile->f_flags & O_WRONLY))) {
877 if(open_file->invalidHandle == FALSE) {
878 /* we found a valid, writeable network file
879 handle to use to try to set the file size */
880 __u16 nfid = open_file->netfid;
881 __u32 npid = open_file->pid;
882 read_unlock(&GlobalSMBSeslock);
884 rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
886 cFYI(1,("SetFileSize by handle (setattrs) rc = %d",rc));
887 /* Do not need reopen and retry on EAGAIN since we will
888 retry by pathname below */
890 break; /* now that we found one valid file handle no
891 sense continuing to loop trying others */
896 read_unlock(&GlobalSMBSeslock);
901 /* Set file size by pathname rather than by handle either
902 because no valid, writeable file handle for it was found or
903 because there was an error setting it by handle */
904 rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,FALSE,
906 cFYI(1,(" SetEOF by path (setattrs) rc = %d",rc));
909 /* Server is ok setting allocation size implicitly - no need to call: */
910 /*CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE, cifs_sb->local_nls);*/
913 rc = vmtruncate(direntry->d_inode, attrs->ia_size);
914 cifs_truncate_page(direntry->d_inode->i_mapping, direntry->d_inode->i_size);
917 if (attrs->ia_valid & ATTR_UID) {
918 cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
920 /* entry->uid = cpu_to_le16(attr->ia_uid); */
922 if (attrs->ia_valid & ATTR_GID) {
923 cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
925 /* entry->gid = cpu_to_le16(attr->ia_gid); */
928 time_buf.Attributes = 0;
929 if (attrs->ia_valid & ATTR_MODE) {
930 cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
931 mode = attrs->ia_mode;
932 /* entry->mode = cpu_to_le16(attr->ia_mode); */
935 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
936 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
937 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
938 0 /* dev_t */, cifs_sb->local_nls);
939 else if (attrs->ia_valid & ATTR_MODE) {
940 if((mode & S_IWUGO) == 0) /* not writeable */ {
941 if((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
942 time_buf.Attributes =
943 cpu_to_le32(cifsInode->cifsAttrs | ATTR_READONLY);
944 } else if((mode & S_IWUGO) == S_IWUGO) {
945 if(cifsInode->cifsAttrs & ATTR_READONLY)
946 time_buf.Attributes =
947 cpu_to_le32(cifsInode->cifsAttrs & (~ATTR_READONLY));
949 /* BB to be implemented - via Windows security descriptors or streams */
950 /* CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,uid,gid,cifs_sb->local_nls);*/
953 if (attrs->ia_valid & ATTR_ATIME) {
955 time_buf.LastAccessTime =
956 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
958 time_buf.LastAccessTime = 0;
960 if (attrs->ia_valid & ATTR_MTIME) {
962 time_buf.LastWriteTime =
963 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
965 time_buf.LastWriteTime = 0;
967 if (attrs->ia_valid & ATTR_CTIME) {
969 cFYI(1, (" CIFS - CTIME changed ")); /* BB probably do not need */
970 time_buf.ChangeTime =
971 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
973 time_buf.ChangeTime = 0;
975 if (set_time || time_buf.Attributes) {
976 /* BB what if setting one attribute fails
977 (such as size) but time setting works */
978 time_buf.CreationTime = 0; /* do not change */
979 /* In the future we should experiment - try setting timestamps
980 via Handle (SetFileInfo) instead of by path */
981 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
983 if(rc == -EOPNOTSUPP) {
984 cFYI(1,("OS2 level of SetPathInfo not implemented"));
985 /* Need to convert time_buf into old format,
986 but probably better to do that inside the function
987 below rather than here */
988 /* Better to return EOPNOTSUPP until function
990 /* CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
991 FILE_INFO_STANDARD * data, cifs_sb->local_nls); */
995 /* do not need local check to inode_check_ok since the server does that */
997 rc = inode_setattr(direntry->d_inode, attrs);
1005 cifs_delete_inode(struct inode *inode)
1007 cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
1008 /* may have to add back in if and when safe distributed caching of
1009 directories added e.g. via FindNotify */