4 * Copyright (C) International Business Machines Corp., 2002,2005
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 int cifs_get_inode_info_unix(struct inode **pinode,
34 const unsigned char *search_path, struct super_block *sb, int xid)
37 FILE_UNIX_BASIC_INFO findData;
38 struct cifsTconInfo *pTcon;
40 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
43 pTcon = cifs_sb->tcon;
44 cFYI(1, (" Getting info on %s ", search_path));
45 /* could have done a find first instead but this returns more info */
46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
48 CIFS_MOUNT_MAP_SPECIAL_CHR);
49 /* dump_mem("\nUnixQPathInfo return data", &findData,
54 kmalloc(strnlen(pTcon->treeName,
56 strnlen(search_path, MAX_PATHCONF) + 1,
58 if (tmp_path == NULL) {
61 /* have to skip first of the double backslash of
63 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
64 strncat(tmp_path, search_path, MAX_PATHCONF);
65 rc = connect_to_dfs_path(xid, pTcon->ses,
66 /* treename + */ tmp_path,
68 cifs_sb->mnt_cifs_flags &
69 CIFS_MOUNT_MAP_SPECIAL_CHR);
72 /* BB fix up inode etc. */
77 struct cifsInodeInfo *cifsInfo;
78 __u32 type = le32_to_cpu(findData.Type);
79 __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
80 __u64 end_of_file = le64_to_cpu(findData.EndOfFile);
83 if (*pinode == NULL) {
84 *pinode = new_inode(sb);
87 /* Is an i_ino of zero legal? */
88 /* Are there sanity checks we can use to ensure that
89 the server is really filling in that field? */
90 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
92 (unsigned long)findData.UniqueId;
93 } /* note ino incremented to unique num in new_inode */
94 insert_inode_hash(*pinode);
98 cifsInfo = CIFS_I(inode);
100 cFYI(1, (" Old time %ld ", cifsInfo->time));
101 cifsInfo->time = jiffies;
102 cFYI(1, (" New time %ld ", cifsInfo->time));
103 /* this is ok to set on every inode revalidate */
104 atomic_set(&cifsInfo->inUse,1);
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);
143 /* blksize needs to be multiple of two. So safer to default to
144 blksize and blkbits set in superblock so 2**blkbits and blksize
145 will match rather than setting to:
146 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
148 /* This seems incredibly stupid but it turns out that i_blocks
149 is not related to (i_size / i_blksize), instead 512 byte size
150 is required for calculating num blocks */
152 /* 512 bytes (2**9) is the fake blocksize that must be used */
153 /* for this calculation */
154 inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
157 if (num_of_bytes < end_of_file)
158 cFYI(1, ("allocation size less than end of file "));
160 ("Size %ld and blocks %ld",
161 (unsigned long) inode->i_size, inode->i_blocks));
162 if (S_ISREG(inode->i_mode)) {
163 cFYI(1, (" File inode "));
164 inode->i_op = &cifs_file_inode_ops;
165 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
166 inode->i_fop = &cifs_file_direct_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,
187 int cifs_get_inode_info(struct inode **pinode,
188 const unsigned char *search_path, FILE_ALL_INFO *pfindData,
189 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 cached inode sizes"));
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,
216 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
217 CIFS_MOUNT_MAP_SPECIAL_CHR);
219 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
221 if (rc == -EREMOTE) {
226 strnlen(search_path, MAX_PATHCONF) + 1,
228 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,
238 cifs_sb->mnt_cifs_flags &
239 CIFS_MOUNT_MAP_SPECIAL_CHR);
241 /* BB fix up inode etc. */
247 struct cifsInodeInfo *cifsInfo;
248 __u32 attr = le32_to_cpu(pfindData->Attributes);
251 if (*pinode == NULL) {
252 *pinode = new_inode(sb);
255 /* Is an i_ino of zero legal? Can we use that to check
256 if the server supports returning inode numbers? Are
257 there other sanity checks we can use to ensure that
258 the server is really filling in that field? */
260 /* We can not use the IndexNumber field by default from
261 Windows or Samba (in ALL_INFO buf) but we can request
262 it explicitly. It may not be unique presumably if
263 the server has multiple devices mounted under one
266 /* There may be higher info levels that work but are
267 there Windows server or network appliances for which
268 IndexNumber field is not guaranteed unique? */
270 #ifdef CONFIG_CIFS_EXPERIMENTAL
271 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
275 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
276 search_path, &inode_num,
278 cifs_sb->mnt_cifs_flags &
279 CIFS_MOUNT_MAP_SPECIAL_CHR);
281 cFYI(1,("GetSrvInodeNum rc %d", rc1));
282 /* BB EOPNOSUPP disable SERVER_INUM? */
283 } else /* do we need cast or hash to ino? */
284 (*pinode)->i_ino = inode_num;
285 } /* else ino incremented to unique num in new_inode*/
286 #endif /* CIFS_EXPERIMENTAL */
287 insert_inode_hash(*pinode);
290 cifsInfo = CIFS_I(inode);
291 cifsInfo->cifsAttrs = attr;
292 cFYI(1, (" Old time %ld ", cifsInfo->time));
293 cifsInfo->time = jiffies;
294 cFYI(1, (" New time %ld ", cifsInfo->time));
296 /* blksize needs to be multiple of two. So safer to default to
297 blksize and blkbits set in superblock so 2**blkbits and blksize
298 will match rather than setting to:
299 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
301 /* Linux can not store file creation time unfortunately so we ignore it */
303 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
305 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
307 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
308 cFYI(0, (" Attributes came in as 0x%x ", attr));
310 /* set default mode. will override for dirs below */
311 if (atomic_read(&cifsInfo->inUse) == 0)
312 /* new inode, can safely set these fields */
313 inode->i_mode = cifs_sb->mnt_file_mode;
315 /* if (attr & ATTR_REPARSE) */
316 /* We no longer handle these as symlinks because we could not
317 follow them due to the absolute path with drive letter */
318 if (attr & ATTR_DIRECTORY) {
319 /* override default perms since we do not do byte range locking
321 inode->i_mode = cifs_sb->mnt_dir_mode;
322 inode->i_mode |= S_IFDIR;
323 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
324 (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
325 /* No need to le64 convert size of zero */
326 (pfindData->EndOfFile == 0)) {
327 inode->i_mode = cifs_sb->mnt_file_mode;
328 inode->i_mode |= S_IFIFO;
329 /* BB Finish for SFU style symlinks and devies */
330 /* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
331 (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */
334 inode->i_mode |= S_IFREG;
335 /* treat the dos attribute of read-only as read-only
337 if (cifsInfo->cifsAttrs & ATTR_READONLY)
338 inode->i_mode &= ~(S_IWUGO);
339 /* BB add code here -
340 validate if device or weird share or device type? */
342 if (is_size_safe_to_change(cifsInfo)) {
343 /* can not safely change the file size here if the
344 client is writing to it due to potential races */
345 i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
347 /* 512 bytes (2**9) is the fake blocksize that must be
348 used for this calculation */
349 inode->i_blocks = (512 - 1 + le64_to_cpu(
350 pfindData->AllocationSize)) >> 9;
353 inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
355 /* BB fill in uid and gid here? with help from winbind?
356 or retrieve from NTFS stream extended attribute */
357 if (atomic_read(&cifsInfo->inUse) == 0) {
358 inode->i_uid = cifs_sb->mnt_uid;
359 inode->i_gid = cifs_sb->mnt_gid;
360 /* set so we do not keep refreshing these fields with
361 bad data after user has changed them in memory */
362 atomic_set(&cifsInfo->inUse,1);
365 if (S_ISREG(inode->i_mode)) {
366 cFYI(1, (" File inode "));
367 inode->i_op = &cifs_file_inode_ops;
368 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
369 inode->i_fop = &cifs_file_direct_ops;
371 inode->i_fop = &cifs_file_ops;
372 inode->i_data.a_ops = &cifs_addr_ops;
373 } else if (S_ISDIR(inode->i_mode)) {
374 cFYI(1, (" Directory inode "));
375 inode->i_op = &cifs_dir_inode_ops;
376 inode->i_fop = &cifs_dir_ops;
377 } else if (S_ISLNK(inode->i_mode)) {
378 cFYI(1, (" Symbolic Link inode "));
379 inode->i_op = &cifs_symlink_inode_ops;
381 init_special_inode(inode, inode->i_mode,
389 /* gets root inode */
390 void cifs_read_inode(struct inode *inode)
393 struct cifs_sb_info *cifs_sb;
395 cifs_sb = CIFS_SB(inode->i_sb);
397 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
398 cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
400 cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
401 /* can not call macro FreeXid here since in a void func */
405 int cifs_unlink(struct inode *inode, struct dentry *direntry)
409 struct cifs_sb_info *cifs_sb;
410 struct cifsTconInfo *pTcon;
411 char *full_path = NULL;
412 struct cifsInodeInfo *cifsInode;
413 FILE_BASIC_INFO *pinfo_buf;
415 cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
419 cifs_sb = CIFS_SB(inode->i_sb);
420 pTcon = cifs_sb->tcon;
422 /* Unlink can be called from rename so we can not grab the sem here
423 since we deadlock otherwise */
424 /* down(&direntry->d_sb->s_vfs_rename_sem);*/
425 full_path = build_path_from_dentry(direntry, cifs_sb);
426 /* up(&direntry->d_sb->s_vfs_rename_sem);*/
427 if (full_path == NULL) {
431 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
432 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
435 if (direntry->d_inode)
436 direntry->d_inode->i_nlink--;
437 } else if (rc == -ENOENT) {
439 } else if (rc == -ETXTBSY) {
443 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
444 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
445 &netfid, &oplock, NULL, cifs_sb->local_nls,
446 cifs_sb->mnt_cifs_flags &
447 CIFS_MOUNT_MAP_SPECIAL_CHR);
449 CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
451 cifs_sb->mnt_cifs_flags &
452 CIFS_MOUNT_MAP_SPECIAL_CHR);
453 CIFSSMBClose(xid, pTcon, netfid);
454 if (direntry->d_inode)
455 direntry->d_inode->i_nlink--;
457 } else if (rc == -EACCES) {
458 /* try only if r/o attribute set in local lookup data? */
459 pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
461 memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO));
462 /* ATTRS set to normal clears r/o bit */
463 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
464 if (!(pTcon->ses->flags & CIFS_SES_NT4))
465 rc = CIFSSMBSetTimes(xid, pTcon, full_path,
468 cifs_sb->mnt_cifs_flags &
469 CIFS_MOUNT_MAP_SPECIAL_CHR);
473 if (rc == -EOPNOTSUPP) {
476 /* rc = CIFSSMBSetAttrLegacy(xid, pTcon,
480 For some strange reason it seems that NT4 eats the
481 old setattr call without actually setting the
482 attributes so on to the third attempted workaround
485 /* BB could scan to see if we already have it open
486 and pass in pid of opener to function */
487 rc = CIFSSMBOpen(xid, pTcon, full_path,
488 FILE_OPEN, SYNCHRONIZE |
489 FILE_WRITE_ATTRIBUTES, 0,
490 &netfid, &oplock, NULL,
492 cifs_sb->mnt_cifs_flags &
493 CIFS_MOUNT_MAP_SPECIAL_CHR);
495 rc = CIFSSMBSetFileTimes(xid, pTcon,
498 CIFSSMBClose(xid, pTcon, netfid);
504 rc = CIFSSMBDelFile(xid, pTcon, full_path,
506 cifs_sb->mnt_cifs_flags &
507 CIFS_MOUNT_MAP_SPECIAL_CHR);
509 if (direntry->d_inode)
510 direntry->d_inode->i_nlink--;
511 } else if (rc == -ETXTBSY) {
515 rc = CIFSSMBOpen(xid, pTcon, full_path,
518 CREATE_DELETE_ON_CLOSE,
519 &netfid, &oplock, NULL,
521 cifs_sb->mnt_cifs_flags &
522 CIFS_MOUNT_MAP_SPECIAL_CHR);
524 CIFSSMBRenameOpenFile(xid, pTcon,
527 cifs_sb->mnt_cifs_flags &
528 CIFS_MOUNT_MAP_SPECIAL_CHR);
529 CIFSSMBClose(xid, pTcon, netfid);
530 if (direntry->d_inode)
531 direntry->d_inode->i_nlink--;
533 /* BB if rc = -ETXTBUSY goto the rename logic BB */
537 if (direntry->d_inode) {
538 cifsInode = CIFS_I(direntry->d_inode);
539 cifsInode->time = 0; /* will force revalidate to get info
541 direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
543 inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
544 cifsInode = CIFS_I(inode);
545 cifsInode->time = 0; /* force revalidate of dir as well */
552 int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
556 struct cifs_sb_info *cifs_sb;
557 struct cifsTconInfo *pTcon;
558 char *full_path = NULL;
559 struct inode *newinode = NULL;
561 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
565 cifs_sb = CIFS_SB(inode->i_sb);
566 pTcon = cifs_sb->tcon;
568 down(&inode->i_sb->s_vfs_rename_sem);
569 full_path = build_path_from_dentry(direntry, cifs_sb);
570 up(&inode->i_sb->s_vfs_rename_sem);
571 if (full_path == NULL) {
575 /* BB add setting the equivalent of mode via CreateX w/ACLs */
576 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
577 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
579 cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
583 if (pTcon->ses->capabilities & CAP_UNIX)
584 rc = cifs_get_inode_info_unix(&newinode, full_path,
587 rc = cifs_get_inode_info(&newinode, full_path, NULL,
590 direntry->d_op = &cifs_dentry_ops;
591 d_instantiate(direntry, newinode);
592 if (direntry->d_inode)
593 direntry->d_inode->i_nlink = 2;
594 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
595 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
596 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
598 (__u64)current->euid,
599 (__u64)current->egid,
602 cifs_sb->mnt_cifs_flags &
603 CIFS_MOUNT_MAP_SPECIAL_CHR);
605 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
607 (__u64)-1, 0 /* dev_t */,
609 cifs_sb->mnt_cifs_flags &
610 CIFS_MOUNT_MAP_SPECIAL_CHR);
613 /* BB to be implemented via Windows secrty descriptors
614 eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
615 -1, -1, local_nls); */
623 int cifs_rmdir(struct inode *inode, struct dentry *direntry)
627 struct cifs_sb_info *cifs_sb;
628 struct cifsTconInfo *pTcon;
629 char *full_path = NULL;
630 struct cifsInodeInfo *cifsInode;
632 cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
636 cifs_sb = CIFS_SB(inode->i_sb);
637 pTcon = cifs_sb->tcon;
639 down(&inode->i_sb->s_vfs_rename_sem);
640 full_path = build_path_from_dentry(direntry, cifs_sb);
641 up(&inode->i_sb->s_vfs_rename_sem);
642 if (full_path == NULL) {
647 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
648 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
652 i_size_write(direntry->d_inode,0);
653 direntry->d_inode->i_nlink = 0;
656 cifsInode = CIFS_I(direntry->d_inode);
657 cifsInode->time = 0; /* force revalidate to go get info when
659 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
660 current_fs_time(inode->i_sb);
667 int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
668 struct inode *target_inode, struct dentry *target_direntry)
672 struct cifs_sb_info *cifs_sb_source;
673 struct cifs_sb_info *cifs_sb_target;
674 struct cifsTconInfo *pTcon;
680 cifs_sb_target = CIFS_SB(target_inode->i_sb);
681 cifs_sb_source = CIFS_SB(source_inode->i_sb);
682 pTcon = cifs_sb_source->tcon;
684 if (pTcon != cifs_sb_target->tcon) {
686 return -EXDEV; /* BB actually could be allowed if same server,
688 Might eventually add support for this */
691 /* we already have the rename sem so we do not need to grab it again
692 here to protect the path integrity */
693 fromName = build_path_from_dentry(source_direntry, cifs_sb_source);
694 toName = build_path_from_dentry(target_direntry, cifs_sb_target);
695 if ((fromName == NULL) || (toName == NULL)) {
697 goto cifs_rename_exit;
700 rc = CIFSSMBRename(xid, pTcon, fromName, toName,
701 cifs_sb_source->local_nls,
702 cifs_sb_source->mnt_cifs_flags &
703 CIFS_MOUNT_MAP_SPECIAL_CHR);
705 /* check if they are the same file because rename of hardlinked
707 FILE_UNIX_BASIC_INFO *info_buf_source;
708 FILE_UNIX_BASIC_INFO *info_buf_target;
711 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
712 if (info_buf_source != NULL) {
713 info_buf_target = info_buf_source + 1;
714 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
715 info_buf_source, cifs_sb_source->local_nls,
716 cifs_sb_source->mnt_cifs_flags &
717 CIFS_MOUNT_MAP_SPECIAL_CHR);
719 rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
721 cifs_sb_target->local_nls,
722 /* remap based on source sb */
723 cifs_sb_source->mnt_cifs_flags &
724 CIFS_MOUNT_MAP_SPECIAL_CHR);
727 (info_buf_source->UniqueId ==
728 info_buf_target->UniqueId)) {
729 /* do not rename since the files are hardlinked which
732 /* we either can not tell the files are hardlinked
733 (as with Windows servers) or files are not
734 hardlinked so delete the target manually before
735 renaming to follow POSIX rather than Windows
737 cifs_unlink(target_inode, target_direntry);
738 rc = CIFSSMBRename(xid, pTcon, fromName,
740 cifs_sb_source->local_nls,
741 cifs_sb_source->mnt_cifs_flags
742 & CIFS_MOUNT_MAP_SPECIAL_CHR);
744 kfree(info_buf_source);
745 } /* if we can not get memory just leave rc as EEXIST */
749 cFYI(1, ("rename rc %d", rc));
752 if ((rc == -EIO) || (rc == -EEXIST)) {
756 /* BB FIXME Is Generic Read correct for rename? */
757 /* if renaming directory - we should not say CREATE_NOT_DIR,
758 need to test renaming open directory, also GENERIC_READ
759 might not right be right access to request */
760 rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
761 CREATE_NOT_DIR, &netfid, &oplock, NULL,
762 cifs_sb_source->local_nls,
763 cifs_sb_source->mnt_cifs_flags &
764 CIFS_MOUNT_MAP_SPECIAL_CHR);
766 CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
767 cifs_sb_source->local_nls,
768 cifs_sb_source->mnt_cifs_flags &
769 CIFS_MOUNT_MAP_SPECIAL_CHR);
770 CIFSSMBClose(xid, pTcon, netfid);
781 int cifs_revalidate(struct dentry *direntry)
786 struct cifs_sb_info *cifs_sb;
787 struct cifsInodeInfo *cifsInode;
789 struct timespec local_mtime;
790 int invalidate_inode = FALSE;
792 if (direntry->d_inode == NULL)
795 cifsInode = CIFS_I(direntry->d_inode);
797 if (cifsInode == NULL)
800 /* no sense revalidating inode info on file that no one can write */
801 if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
806 cifs_sb = CIFS_SB(direntry->d_sb);
808 /* can not safely grab the rename sem here if rename calls revalidate
809 since that would deadlock */
810 full_path = build_path_from_dentry(direntry, cifs_sb);
811 if (full_path == NULL) {
815 cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
816 "jiffies %ld", full_path, direntry->d_inode,
817 direntry->d_inode->i_count.counter, direntry,
818 direntry->d_time, jiffies));
820 if (cifsInode->time == 0) {
821 /* was set to zero previously to force revalidate */
822 } else if (time_before(jiffies, cifsInode->time + HZ) &&
823 lookupCacheEnabled) {
824 if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
825 (direntry->d_inode->i_nlink == 1)) {
830 cFYI(1, ("Have to revalidate file due to hardlinks"));
834 /* save mtime and size */
835 local_mtime = direntry->d_inode->i_mtime;
836 local_size = direntry->d_inode->i_size;
838 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
839 rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
842 cFYI(1, ("error on getting revalidate info %d", rc));
843 /* if (rc != -ENOENT)
844 rc = 0; */ /* BB should we cache info on
848 rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
851 cFYI(1, ("error on getting revalidate info %d", rc));
852 /* if (rc != -ENOENT)
853 rc = 0; */ /* BB should we cache info on
857 /* should we remap certain errors, access denied?, to zero */
859 /* if not oplocked, we invalidate inode pages if mtime or file size
860 had changed on server */
862 if (timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
863 (local_size == direntry->d_inode->i_size)) {
864 cFYI(1, ("cifs_revalidate - inode unchanged"));
866 /* file may have changed on server */
867 if (cifsInode->clientCanCacheRead) {
868 /* no need to invalidate inode pages since we were the
869 only ones who could have modified the file and the
870 server copy is staler than ours */
872 invalidate_inode = TRUE;
876 /* can not grab this sem since kernel filesys locking documentation
877 indicates i_sem may be taken by the kernel on lookup and rename
878 which could deadlock if we grab the i_sem here as well */
879 /* down(&direntry->d_inode->i_sem);*/
880 /* need to write out dirty pages here */
881 if (direntry->d_inode->i_mapping) {
882 /* do we need to lock inode until after invalidate completes
884 filemap_fdatawrite(direntry->d_inode->i_mapping);
886 if (invalidate_inode) {
887 if (direntry->d_inode->i_mapping)
888 filemap_fdatawait(direntry->d_inode->i_mapping);
889 /* may eventually have to do this for open files too */
890 if (list_empty(&(cifsInode->openFileList))) {
891 /* Has changed on server - flush read ahead pages */
892 cFYI(1, ("Invalidating read ahead data on "
894 invalidate_remote_inode(direntry->d_inode);
897 /* up(&direntry->d_inode->i_sem); */
904 int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
907 int err = cifs_revalidate(dentry);
909 generic_fillattr(dentry->d_inode, stat);
913 static int cifs_truncate_page(struct address_space *mapping, loff_t from)
915 pgoff_t index = from >> PAGE_CACHE_SHIFT;
916 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
921 page = grab_cache_page(mapping, index);
925 kaddr = kmap_atomic(page, KM_USER0);
926 memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
927 flush_dcache_page(page);
928 kunmap_atomic(kaddr, KM_USER0);
930 page_cache_release(page);
934 int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
937 struct cifs_sb_info *cifs_sb;
938 struct cifsTconInfo *pTcon;
939 char *full_path = NULL;
942 struct cifsFileInfo *open_file = NULL;
943 FILE_BASIC_INFO time_buf;
944 int set_time = FALSE;
945 __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
946 __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
947 __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
948 struct cifsInodeInfo *cifsInode;
949 struct list_head *tmp;
953 cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
954 direntry->d_name.name, attrs->ia_valid));
955 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
956 pTcon = cifs_sb->tcon;
958 down(&direntry->d_sb->s_vfs_rename_sem);
959 full_path = build_path_from_dentry(direntry, cifs_sb);
960 up(&direntry->d_sb->s_vfs_rename_sem);
961 if (full_path == NULL) {
965 cifsInode = CIFS_I(direntry->d_inode);
967 /* BB check if we need to refresh inode from server now ? BB */
969 /* need to flush data before changing file size on server */
970 filemap_fdatawrite(direntry->d_inode->i_mapping);
971 filemap_fdatawait(direntry->d_inode->i_mapping);
973 if (attrs->ia_valid & ATTR_SIZE) {
974 read_lock(&GlobalSMBSeslock);
975 /* To avoid spurious oplock breaks from server, in the case of
976 inodes that we already have open, avoid doing path based
977 setting of file size if we can do it by handle.
978 This keeps our caching token (oplock) and avoids timeouts
979 when the local oplock break takes longer to flush
980 writebehind data than the SMB timeout for the SetPathInfo
981 request would allow */
982 list_for_each(tmp, &cifsInode->openFileList) {
983 open_file = list_entry(tmp, struct cifsFileInfo,
985 /* We check if file is open for writing first */
986 if ((open_file->pfile) &&
987 ((open_file->pfile->f_flags & O_RDWR) ||
988 (open_file->pfile->f_flags & O_WRONLY))) {
989 if (open_file->invalidHandle == FALSE) {
990 /* we found a valid, writeable network
991 file handle to use to try to set the
993 __u16 nfid = open_file->netfid;
994 __u32 npid = open_file->pid;
995 read_unlock(&GlobalSMBSeslock);
997 rc = CIFSSMBSetFileSize(xid, pTcon,
998 attrs->ia_size, nfid, npid,
1000 cFYI(1, ("SetFileSize by handle "
1001 "(setattrs) rc = %d", rc));
1002 /* Do not need reopen and retry on
1003 EAGAIN since we will retry by
1006 /* now that we found one valid file
1007 handle no sense continuing to loop
1008 trying others, so break here */
1014 read_unlock(&GlobalSMBSeslock);
1017 /* Set file size by pathname rather than by handle
1018 either because no valid, writeable file handle for
1019 it was found or because there was an error setting
1021 rc = CIFSSMBSetEOF(xid, pTcon, full_path,
1022 attrs->ia_size, FALSE,
1024 cifs_sb->mnt_cifs_flags &
1025 CIFS_MOUNT_MAP_SPECIAL_CHR);
1026 cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc));
1029 /* Server is ok setting allocation size implicitly - no need
1031 CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE,
1032 cifs_sb->local_nls);
1036 rc = vmtruncate(direntry->d_inode, attrs->ia_size);
1037 cifs_truncate_page(direntry->d_inode->i_mapping,
1038 direntry->d_inode->i_size);
1041 if (attrs->ia_valid & ATTR_UID) {
1042 cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
1043 uid = attrs->ia_uid;
1044 /* entry->uid = cpu_to_le16(attr->ia_uid); */
1046 if (attrs->ia_valid & ATTR_GID) {
1047 cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
1048 gid = attrs->ia_gid;
1049 /* entry->gid = cpu_to_le16(attr->ia_gid); */
1052 time_buf.Attributes = 0;
1053 if (attrs->ia_valid & ATTR_MODE) {
1054 cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
1055 mode = attrs->ia_mode;
1056 /* entry->mode = cpu_to_le16(attr->ia_mode); */
1059 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
1060 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
1061 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
1062 0 /* dev_t */, cifs_sb->local_nls,
1063 cifs_sb->mnt_cifs_flags &
1064 CIFS_MOUNT_MAP_SPECIAL_CHR);
1065 else if (attrs->ia_valid & ATTR_MODE) {
1066 if ((mode & S_IWUGO) == 0) /* not writeable */ {
1067 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
1068 time_buf.Attributes =
1069 cpu_to_le32(cifsInode->cifsAttrs |
1071 } else if ((mode & S_IWUGO) == S_IWUGO) {
1072 if (cifsInode->cifsAttrs & ATTR_READONLY)
1073 time_buf.Attributes =
1074 cpu_to_le32(cifsInode->cifsAttrs &
1077 /* BB to be implemented -
1078 via Windows security descriptors or streams */
1079 /* CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, uid, gid,
1080 cifs_sb->local_nls); */
1083 if (attrs->ia_valid & ATTR_ATIME) {
1085 time_buf.LastAccessTime =
1086 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1088 time_buf.LastAccessTime = 0;
1090 if (attrs->ia_valid & ATTR_MTIME) {
1092 time_buf.LastWriteTime =
1093 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1095 time_buf.LastWriteTime = 0;
1097 if (attrs->ia_valid & ATTR_CTIME) {
1099 cFYI(1, (" CIFS - CTIME changed ")); /* BB probably no need */
1100 time_buf.ChangeTime =
1101 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1103 time_buf.ChangeTime = 0;
1105 if (set_time || time_buf.Attributes) {
1106 /* BB what if setting one attribute fails (such as size) but
1107 time setting works? */
1108 time_buf.CreationTime = 0; /* do not change */
1109 /* In the future we should experiment - try setting timestamps
1110 via Handle (SetFileInfo) instead of by path */
1111 if (!(pTcon->ses->flags & CIFS_SES_NT4))
1112 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
1114 cifs_sb->mnt_cifs_flags &
1115 CIFS_MOUNT_MAP_SPECIAL_CHR);
1119 if (rc == -EOPNOTSUPP) {
1123 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
1124 "times not supported by this server"));
1125 /* BB we could scan to see if we already have it open
1126 and pass in pid of opener to function */
1127 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1128 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1129 CREATE_NOT_DIR, &netfid, &oplock,
1130 NULL, cifs_sb->local_nls,
1131 cifs_sb->mnt_cifs_flags &
1132 CIFS_MOUNT_MAP_SPECIAL_CHR);
1134 rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
1136 CIFSSMBClose(xid, pTcon, netfid);
1138 /* BB For even older servers we could convert time_buf
1139 into old DOS style which uses two second
1142 /* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
1143 &time_buf, cifs_sb->local_nls); */
1148 /* do not need local check to inode_check_ok since the server does
1151 rc = inode_setattr(direntry->d_inode, attrs);
1157 void cifs_delete_inode(struct inode *inode)
1159 cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
1160 /* may have to add back in if and when safe distributed caching of
1161 directories added e.g. via FindNotify */