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 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
170 inode->i_fop->lock = NULL;
171 inode->i_data.a_ops = &cifs_addr_ops;
172 } else if (S_ISDIR(inode->i_mode)) {
173 cFYI(1, (" Directory inode"));
174 inode->i_op = &cifs_dir_inode_ops;
175 inode->i_fop = &cifs_dir_ops;
176 } else if (S_ISLNK(inode->i_mode)) {
177 cFYI(1, (" Symbolic Link inode "));
178 inode->i_op = &cifs_symlink_inode_ops;
179 /* tmp_inode->i_fop = */ /* do not need to set to anything */
181 cFYI(1, (" Init special inode "));
182 init_special_inode(inode, inode->i_mode,
189 int cifs_get_inode_info(struct inode **pinode,
190 const unsigned char *search_path, FILE_ALL_INFO *pfindData,
191 struct super_block *sb, int xid)
194 struct cifsTconInfo *pTcon;
196 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
200 pTcon = cifs_sb->tcon;
201 cFYI(1,("Getting info on %s ", search_path));
203 if ((pfindData == NULL) && (*pinode != NULL)) {
204 if (CIFS_I(*pinode)->clientCanCacheRead) {
205 cFYI(1,("No need to revalidate cached inode sizes"));
210 /* if file info not passed in then get it from server */
211 if (pfindData == NULL) {
212 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
215 pfindData = (FILE_ALL_INFO *)buf;
216 /* could do find first instead but this returns more info */
217 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
218 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
219 CIFS_MOUNT_MAP_SPECIAL_CHR);
221 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
223 if (rc == -EREMOTE) {
228 strnlen(search_path, MAX_PATHCONF) + 1,
230 if (tmp_path == NULL) {
235 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
236 strncat(tmp_path, search_path, MAX_PATHCONF);
237 rc = connect_to_dfs_path(xid, pTcon->ses,
238 /* treename + */ tmp_path,
240 cifs_sb->mnt_cifs_flags &
241 CIFS_MOUNT_MAP_SPECIAL_CHR);
243 /* BB fix up inode etc. */
249 struct cifsInodeInfo *cifsInfo;
250 __u32 attr = le32_to_cpu(pfindData->Attributes);
253 if (*pinode == NULL) {
254 *pinode = new_inode(sb);
257 /* Is an i_ino of zero legal? Can we use that to check
258 if the server supports returning inode numbers? Are
259 there other sanity checks we can use to ensure that
260 the server is really filling in that field? */
262 /* We can not use the IndexNumber field by default from
263 Windows or Samba (in ALL_INFO buf) but we can request
264 it explicitly. It may not be unique presumably if
265 the server has multiple devices mounted under one
268 /* There may be higher info levels that work but are
269 there Windows server or network appliances for which
270 IndexNumber field is not guaranteed unique? */
272 #ifdef CONFIG_CIFS_EXPERIMENTAL
273 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
277 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
278 search_path, &inode_num,
280 cifs_sb->mnt_cifs_flags &
281 CIFS_MOUNT_MAP_SPECIAL_CHR);
283 cFYI(1,("GetSrvInodeNum rc %d", rc1));
284 /* BB EOPNOSUPP disable SERVER_INUM? */
285 } else /* do we need cast or hash to ino? */
286 (*pinode)->i_ino = inode_num;
287 } /* else ino incremented to unique num in new_inode*/
288 #endif /* CIFS_EXPERIMENTAL */
289 insert_inode_hash(*pinode);
292 cifsInfo = CIFS_I(inode);
293 cifsInfo->cifsAttrs = attr;
294 cFYI(1, (" Old time %ld ", cifsInfo->time));
295 cifsInfo->time = jiffies;
296 cFYI(1, (" New time %ld ", cifsInfo->time));
298 /* blksize needs to be multiple of two. So safer to default to
299 blksize and blkbits set in superblock so 2**blkbits and blksize
300 will match rather than setting to:
301 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
303 /* Linux can not store file creation time unfortunately so we ignore it */
305 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
307 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
309 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
310 cFYI(0, (" Attributes came in as 0x%x ", attr));
312 /* set default mode. will override for dirs below */
313 if (atomic_read(&cifsInfo->inUse) == 0)
314 /* new inode, can safely set these fields */
315 inode->i_mode = cifs_sb->mnt_file_mode;
317 /* if (attr & ATTR_REPARSE) */
318 /* We no longer handle these as symlinks because we could not
319 follow them due to the absolute path with drive letter */
320 if (attr & ATTR_DIRECTORY) {
321 /* override default perms since we do not do byte range locking
323 inode->i_mode = cifs_sb->mnt_dir_mode;
324 inode->i_mode |= S_IFDIR;
325 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
326 (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
327 /* No need to le64 convert size of zero */
328 (pfindData->EndOfFile == 0)) {
329 inode->i_mode = cifs_sb->mnt_file_mode;
330 inode->i_mode |= S_IFIFO;
331 /* BB Finish for SFU style symlinks and devies */
332 /* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
333 (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */
336 inode->i_mode |= S_IFREG;
337 /* treat the dos attribute of read-only as read-only
339 if (cifsInfo->cifsAttrs & ATTR_READONLY)
340 inode->i_mode &= ~(S_IWUGO);
341 /* BB add code here -
342 validate if device or weird share or device type? */
344 if (is_size_safe_to_change(cifsInfo)) {
345 /* can not safely change the file size here if the
346 client is writing to it due to potential races */
347 i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
349 /* 512 bytes (2**9) is the fake blocksize that must be
350 used for this calculation */
351 inode->i_blocks = (512 - 1 + le64_to_cpu(
352 pfindData->AllocationSize)) >> 9;
355 inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
357 /* BB fill in uid and gid here? with help from winbind?
358 or retrieve from NTFS stream extended attribute */
359 if (atomic_read(&cifsInfo->inUse) == 0) {
360 inode->i_uid = cifs_sb->mnt_uid;
361 inode->i_gid = cifs_sb->mnt_gid;
362 /* set so we do not keep refreshing these fields with
363 bad data after user has changed them in memory */
364 atomic_set(&cifsInfo->inUse,1);
367 if (S_ISREG(inode->i_mode)) {
368 cFYI(1, (" File inode "));
369 inode->i_op = &cifs_file_inode_ops;
370 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
371 inode->i_fop = &cifs_file_direct_ops;
373 inode->i_fop = &cifs_file_ops;
374 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
375 inode->i_fop->lock = NULL;
376 inode->i_data.a_ops = &cifs_addr_ops;
377 } else if (S_ISDIR(inode->i_mode)) {
378 cFYI(1, (" Directory inode "));
379 inode->i_op = &cifs_dir_inode_ops;
380 inode->i_fop = &cifs_dir_ops;
381 } else if (S_ISLNK(inode->i_mode)) {
382 cFYI(1, (" Symbolic Link inode "));
383 inode->i_op = &cifs_symlink_inode_ops;
385 init_special_inode(inode, inode->i_mode,
393 /* gets root inode */
394 void cifs_read_inode(struct inode *inode)
397 struct cifs_sb_info *cifs_sb;
399 cifs_sb = CIFS_SB(inode->i_sb);
401 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
402 cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
404 cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
405 /* can not call macro FreeXid here since in a void func */
409 int cifs_unlink(struct inode *inode, struct dentry *direntry)
413 struct cifs_sb_info *cifs_sb;
414 struct cifsTconInfo *pTcon;
415 char *full_path = NULL;
416 struct cifsInodeInfo *cifsInode;
417 FILE_BASIC_INFO *pinfo_buf;
419 cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
423 cifs_sb = CIFS_SB(inode->i_sb);
424 pTcon = cifs_sb->tcon;
426 /* Unlink can be called from rename so we can not grab the sem here
427 since we deadlock otherwise */
428 /* down(&direntry->d_sb->s_vfs_rename_sem);*/
429 full_path = build_path_from_dentry(direntry, cifs_sb);
430 /* up(&direntry->d_sb->s_vfs_rename_sem);*/
431 if (full_path == NULL) {
435 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
436 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
439 if (direntry->d_inode)
440 direntry->d_inode->i_nlink--;
441 } else if (rc == -ENOENT) {
443 } else if (rc == -ETXTBSY) {
447 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
448 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
449 &netfid, &oplock, NULL, cifs_sb->local_nls,
450 cifs_sb->mnt_cifs_flags &
451 CIFS_MOUNT_MAP_SPECIAL_CHR);
453 CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
455 cifs_sb->mnt_cifs_flags &
456 CIFS_MOUNT_MAP_SPECIAL_CHR);
457 CIFSSMBClose(xid, pTcon, netfid);
458 if (direntry->d_inode)
459 direntry->d_inode->i_nlink--;
461 } else if (rc == -EACCES) {
462 /* try only if r/o attribute set in local lookup data? */
463 pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
465 memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO));
466 /* ATTRS set to normal clears r/o bit */
467 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
468 if (!(pTcon->ses->flags & CIFS_SES_NT4))
469 rc = CIFSSMBSetTimes(xid, pTcon, full_path,
472 cifs_sb->mnt_cifs_flags &
473 CIFS_MOUNT_MAP_SPECIAL_CHR);
477 if (rc == -EOPNOTSUPP) {
480 /* rc = CIFSSMBSetAttrLegacy(xid, pTcon,
484 For some strange reason it seems that NT4 eats the
485 old setattr call without actually setting the
486 attributes so on to the third attempted workaround
489 /* BB could scan to see if we already have it open
490 and pass in pid of opener to function */
491 rc = CIFSSMBOpen(xid, pTcon, full_path,
492 FILE_OPEN, SYNCHRONIZE |
493 FILE_WRITE_ATTRIBUTES, 0,
494 &netfid, &oplock, NULL,
496 cifs_sb->mnt_cifs_flags &
497 CIFS_MOUNT_MAP_SPECIAL_CHR);
499 rc = CIFSSMBSetFileTimes(xid, pTcon,
502 CIFSSMBClose(xid, pTcon, netfid);
508 rc = CIFSSMBDelFile(xid, pTcon, full_path,
510 cifs_sb->mnt_cifs_flags &
511 CIFS_MOUNT_MAP_SPECIAL_CHR);
513 if (direntry->d_inode)
514 direntry->d_inode->i_nlink--;
515 } else if (rc == -ETXTBSY) {
519 rc = CIFSSMBOpen(xid, pTcon, full_path,
522 CREATE_DELETE_ON_CLOSE,
523 &netfid, &oplock, NULL,
525 cifs_sb->mnt_cifs_flags &
526 CIFS_MOUNT_MAP_SPECIAL_CHR);
528 CIFSSMBRenameOpenFile(xid, pTcon,
531 cifs_sb->mnt_cifs_flags &
532 CIFS_MOUNT_MAP_SPECIAL_CHR);
533 CIFSSMBClose(xid, pTcon, netfid);
534 if (direntry->d_inode)
535 direntry->d_inode->i_nlink--;
537 /* BB if rc = -ETXTBUSY goto the rename logic BB */
541 if (direntry->d_inode) {
542 cifsInode = CIFS_I(direntry->d_inode);
543 cifsInode->time = 0; /* will force revalidate to get info
545 direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
547 inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
548 cifsInode = CIFS_I(inode);
549 cifsInode->time = 0; /* force revalidate of dir as well */
556 int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
560 struct cifs_sb_info *cifs_sb;
561 struct cifsTconInfo *pTcon;
562 char *full_path = NULL;
563 struct inode *newinode = NULL;
565 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
569 cifs_sb = CIFS_SB(inode->i_sb);
570 pTcon = cifs_sb->tcon;
572 down(&inode->i_sb->s_vfs_rename_sem);
573 full_path = build_path_from_dentry(direntry, cifs_sb);
574 up(&inode->i_sb->s_vfs_rename_sem);
575 if (full_path == NULL) {
579 /* BB add setting the equivalent of mode via CreateX w/ACLs */
580 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
581 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
583 cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
587 if (pTcon->ses->capabilities & CAP_UNIX)
588 rc = cifs_get_inode_info_unix(&newinode, full_path,
591 rc = cifs_get_inode_info(&newinode, full_path, NULL,
595 direntry->d_op = &cifs_ci_dentry_ops;
597 direntry->d_op = &cifs_dentry_ops;
598 d_instantiate(direntry, newinode);
599 if (direntry->d_inode)
600 direntry->d_inode->i_nlink = 2;
601 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
602 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
603 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
605 (__u64)current->euid,
606 (__u64)current->egid,
609 cifs_sb->mnt_cifs_flags &
610 CIFS_MOUNT_MAP_SPECIAL_CHR);
612 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
614 (__u64)-1, 0 /* dev_t */,
616 cifs_sb->mnt_cifs_flags &
617 CIFS_MOUNT_MAP_SPECIAL_CHR);
620 /* BB to be implemented via Windows secrty descriptors
621 eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
622 -1, -1, local_nls); */
630 int cifs_rmdir(struct inode *inode, struct dentry *direntry)
634 struct cifs_sb_info *cifs_sb;
635 struct cifsTconInfo *pTcon;
636 char *full_path = NULL;
637 struct cifsInodeInfo *cifsInode;
639 cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
643 cifs_sb = CIFS_SB(inode->i_sb);
644 pTcon = cifs_sb->tcon;
646 down(&inode->i_sb->s_vfs_rename_sem);
647 full_path = build_path_from_dentry(direntry, cifs_sb);
648 up(&inode->i_sb->s_vfs_rename_sem);
649 if (full_path == NULL) {
654 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
655 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
659 i_size_write(direntry->d_inode,0);
660 direntry->d_inode->i_nlink = 0;
663 cifsInode = CIFS_I(direntry->d_inode);
664 cifsInode->time = 0; /* force revalidate to go get info when
666 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
667 current_fs_time(inode->i_sb);
674 int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
675 struct inode *target_inode, struct dentry *target_direntry)
679 struct cifs_sb_info *cifs_sb_source;
680 struct cifs_sb_info *cifs_sb_target;
681 struct cifsTconInfo *pTcon;
687 cifs_sb_target = CIFS_SB(target_inode->i_sb);
688 cifs_sb_source = CIFS_SB(source_inode->i_sb);
689 pTcon = cifs_sb_source->tcon;
691 if (pTcon != cifs_sb_target->tcon) {
693 return -EXDEV; /* BB actually could be allowed if same server,
695 Might eventually add support for this */
698 /* we already have the rename sem so we do not need to grab it again
699 here to protect the path integrity */
700 fromName = build_path_from_dentry(source_direntry, cifs_sb_source);
701 toName = build_path_from_dentry(target_direntry, cifs_sb_target);
702 if ((fromName == NULL) || (toName == NULL)) {
704 goto cifs_rename_exit;
707 rc = CIFSSMBRename(xid, pTcon, fromName, toName,
708 cifs_sb_source->local_nls,
709 cifs_sb_source->mnt_cifs_flags &
710 CIFS_MOUNT_MAP_SPECIAL_CHR);
712 /* check if they are the same file because rename of hardlinked
714 FILE_UNIX_BASIC_INFO *info_buf_source;
715 FILE_UNIX_BASIC_INFO *info_buf_target;
718 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
719 if (info_buf_source != NULL) {
720 info_buf_target = info_buf_source + 1;
721 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
722 info_buf_source, cifs_sb_source->local_nls,
723 cifs_sb_source->mnt_cifs_flags &
724 CIFS_MOUNT_MAP_SPECIAL_CHR);
726 rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
728 cifs_sb_target->local_nls,
729 /* remap based on source sb */
730 cifs_sb_source->mnt_cifs_flags &
731 CIFS_MOUNT_MAP_SPECIAL_CHR);
734 (info_buf_source->UniqueId ==
735 info_buf_target->UniqueId)) {
736 /* do not rename since the files are hardlinked which
739 /* we either can not tell the files are hardlinked
740 (as with Windows servers) or files are not
741 hardlinked so delete the target manually before
742 renaming to follow POSIX rather than Windows
744 cifs_unlink(target_inode, target_direntry);
745 rc = CIFSSMBRename(xid, pTcon, fromName,
747 cifs_sb_source->local_nls,
748 cifs_sb_source->mnt_cifs_flags
749 & CIFS_MOUNT_MAP_SPECIAL_CHR);
751 kfree(info_buf_source);
752 } /* if we can not get memory just leave rc as EEXIST */
756 cFYI(1, ("rename rc %d", rc));
759 if ((rc == -EIO) || (rc == -EEXIST)) {
763 /* BB FIXME Is Generic Read correct for rename? */
764 /* if renaming directory - we should not say CREATE_NOT_DIR,
765 need to test renaming open directory, also GENERIC_READ
766 might not right be right access to request */
767 rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
768 CREATE_NOT_DIR, &netfid, &oplock, NULL,
769 cifs_sb_source->local_nls,
770 cifs_sb_source->mnt_cifs_flags &
771 CIFS_MOUNT_MAP_SPECIAL_CHR);
773 CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
774 cifs_sb_source->local_nls,
775 cifs_sb_source->mnt_cifs_flags &
776 CIFS_MOUNT_MAP_SPECIAL_CHR);
777 CIFSSMBClose(xid, pTcon, netfid);
788 int cifs_revalidate(struct dentry *direntry)
793 struct cifs_sb_info *cifs_sb;
794 struct cifsInodeInfo *cifsInode;
796 struct timespec local_mtime;
797 int invalidate_inode = FALSE;
799 if (direntry->d_inode == NULL)
802 cifsInode = CIFS_I(direntry->d_inode);
804 if (cifsInode == NULL)
807 /* no sense revalidating inode info on file that no one can write */
808 if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
813 cifs_sb = CIFS_SB(direntry->d_sb);
815 /* can not safely grab the rename sem here if rename calls revalidate
816 since that would deadlock */
817 full_path = build_path_from_dentry(direntry, cifs_sb);
818 if (full_path == NULL) {
822 cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
823 "jiffies %ld", full_path, direntry->d_inode,
824 direntry->d_inode->i_count.counter, direntry,
825 direntry->d_time, jiffies));
827 if (cifsInode->time == 0) {
828 /* was set to zero previously to force revalidate */
829 } else if (time_before(jiffies, cifsInode->time + HZ) &&
830 lookupCacheEnabled) {
831 if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
832 (direntry->d_inode->i_nlink == 1)) {
837 cFYI(1, ("Have to revalidate file due to hardlinks"));
841 /* save mtime and size */
842 local_mtime = direntry->d_inode->i_mtime;
843 local_size = direntry->d_inode->i_size;
845 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
846 rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
849 cFYI(1, ("error on getting revalidate info %d", rc));
850 /* if (rc != -ENOENT)
851 rc = 0; */ /* BB should we cache info on
855 rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
858 cFYI(1, ("error on getting revalidate info %d", rc));
859 /* if (rc != -ENOENT)
860 rc = 0; */ /* BB should we cache info on
864 /* should we remap certain errors, access denied?, to zero */
866 /* if not oplocked, we invalidate inode pages if mtime or file size
867 had changed on server */
869 if (timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
870 (local_size == direntry->d_inode->i_size)) {
871 cFYI(1, ("cifs_revalidate - inode unchanged"));
873 /* file may have changed on server */
874 if (cifsInode->clientCanCacheRead) {
875 /* no need to invalidate inode pages since we were the
876 only ones who could have modified the file and the
877 server copy is staler than ours */
879 invalidate_inode = TRUE;
883 /* can not grab this sem since kernel filesys locking documentation
884 indicates i_sem may be taken by the kernel on lookup and rename
885 which could deadlock if we grab the i_sem here as well */
886 /* down(&direntry->d_inode->i_sem);*/
887 /* need to write out dirty pages here */
888 if (direntry->d_inode->i_mapping) {
889 /* do we need to lock inode until after invalidate completes
891 filemap_fdatawrite(direntry->d_inode->i_mapping);
893 if (invalidate_inode) {
894 if (direntry->d_inode->i_mapping)
895 filemap_fdatawait(direntry->d_inode->i_mapping);
896 /* may eventually have to do this for open files too */
897 if (list_empty(&(cifsInode->openFileList))) {
898 /* Has changed on server - flush read ahead pages */
899 cFYI(1, ("Invalidating read ahead data on "
901 invalidate_remote_inode(direntry->d_inode);
904 /* up(&direntry->d_inode->i_sem); */
911 int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
914 int err = cifs_revalidate(dentry);
916 generic_fillattr(dentry->d_inode, stat);
920 static int cifs_truncate_page(struct address_space *mapping, loff_t from)
922 pgoff_t index = from >> PAGE_CACHE_SHIFT;
923 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
928 page = grab_cache_page(mapping, index);
932 kaddr = kmap_atomic(page, KM_USER0);
933 memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
934 flush_dcache_page(page);
935 kunmap_atomic(kaddr, KM_USER0);
937 page_cache_release(page);
941 int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
944 struct cifs_sb_info *cifs_sb;
945 struct cifsTconInfo *pTcon;
946 char *full_path = NULL;
949 struct cifsFileInfo *open_file = NULL;
950 FILE_BASIC_INFO time_buf;
951 int set_time = FALSE;
952 __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
953 __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
954 __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
955 struct cifsInodeInfo *cifsInode;
956 struct list_head *tmp;
960 cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
961 direntry->d_name.name, attrs->ia_valid));
962 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
963 pTcon = cifs_sb->tcon;
965 down(&direntry->d_sb->s_vfs_rename_sem);
966 full_path = build_path_from_dentry(direntry, cifs_sb);
967 up(&direntry->d_sb->s_vfs_rename_sem);
968 if (full_path == NULL) {
972 cifsInode = CIFS_I(direntry->d_inode);
974 /* BB check if we need to refresh inode from server now ? BB */
976 /* need to flush data before changing file size on server */
977 filemap_fdatawrite(direntry->d_inode->i_mapping);
978 filemap_fdatawait(direntry->d_inode->i_mapping);
980 if (attrs->ia_valid & ATTR_SIZE) {
981 read_lock(&GlobalSMBSeslock);
982 /* To avoid spurious oplock breaks from server, in the case of
983 inodes that we already have open, avoid doing path based
984 setting of file size if we can do it by handle.
985 This keeps our caching token (oplock) and avoids timeouts
986 when the local oplock break takes longer to flush
987 writebehind data than the SMB timeout for the SetPathInfo
988 request would allow */
989 list_for_each(tmp, &cifsInode->openFileList) {
990 open_file = list_entry(tmp, struct cifsFileInfo,
992 /* We check if file is open for writing first */
993 if ((open_file->pfile) &&
994 ((open_file->pfile->f_flags & O_RDWR) ||
995 (open_file->pfile->f_flags & O_WRONLY))) {
996 if (open_file->invalidHandle == FALSE) {
997 /* we found a valid, writeable network
998 file handle to use to try to set the
1000 __u16 nfid = open_file->netfid;
1001 __u32 npid = open_file->pid;
1002 read_unlock(&GlobalSMBSeslock);
1004 rc = CIFSSMBSetFileSize(xid, pTcon,
1005 attrs->ia_size, nfid, npid,
1007 cFYI(1, ("SetFileSize by handle "
1008 "(setattrs) rc = %d", rc));
1009 /* Do not need reopen and retry on
1010 EAGAIN since we will retry by
1013 /* now that we found one valid file
1014 handle no sense continuing to loop
1015 trying others, so break here */
1021 read_unlock(&GlobalSMBSeslock);
1024 /* Set file size by pathname rather than by handle
1025 either because no valid, writeable file handle for
1026 it was found or because there was an error setting
1028 rc = CIFSSMBSetEOF(xid, pTcon, full_path,
1029 attrs->ia_size, FALSE,
1031 cifs_sb->mnt_cifs_flags &
1032 CIFS_MOUNT_MAP_SPECIAL_CHR);
1033 cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc));
1036 /* Server is ok setting allocation size implicitly - no need
1038 CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE,
1039 cifs_sb->local_nls);
1043 rc = vmtruncate(direntry->d_inode, attrs->ia_size);
1044 cifs_truncate_page(direntry->d_inode->i_mapping,
1045 direntry->d_inode->i_size);
1048 if (attrs->ia_valid & ATTR_UID) {
1049 cFYI(1, (" CIFS - UID changed to %d", attrs->ia_uid));
1050 uid = attrs->ia_uid;
1051 /* entry->uid = cpu_to_le16(attr->ia_uid); */
1053 if (attrs->ia_valid & ATTR_GID) {
1054 cFYI(1, (" CIFS - GID changed to %d", attrs->ia_gid));
1055 gid = attrs->ia_gid;
1056 /* entry->gid = cpu_to_le16(attr->ia_gid); */
1059 time_buf.Attributes = 0;
1060 if (attrs->ia_valid & ATTR_MODE) {
1061 cFYI(1, (" CIFS - Mode changed to 0x%x", attrs->ia_mode));
1062 mode = attrs->ia_mode;
1063 /* entry->mode = cpu_to_le16(attr->ia_mode); */
1066 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
1067 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
1068 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
1069 0 /* dev_t */, cifs_sb->local_nls,
1070 cifs_sb->mnt_cifs_flags &
1071 CIFS_MOUNT_MAP_SPECIAL_CHR);
1072 else if (attrs->ia_valid & ATTR_MODE) {
1073 if ((mode & S_IWUGO) == 0) /* not writeable */ {
1074 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
1075 time_buf.Attributes =
1076 cpu_to_le32(cifsInode->cifsAttrs |
1078 } else if ((mode & S_IWUGO) == S_IWUGO) {
1079 if (cifsInode->cifsAttrs & ATTR_READONLY)
1080 time_buf.Attributes =
1081 cpu_to_le32(cifsInode->cifsAttrs &
1084 /* BB to be implemented -
1085 via Windows security descriptors or streams */
1086 /* CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, uid, gid,
1087 cifs_sb->local_nls); */
1090 if (attrs->ia_valid & ATTR_ATIME) {
1092 time_buf.LastAccessTime =
1093 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1095 time_buf.LastAccessTime = 0;
1097 if (attrs->ia_valid & ATTR_MTIME) {
1099 time_buf.LastWriteTime =
1100 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1102 time_buf.LastWriteTime = 0;
1104 if (attrs->ia_valid & ATTR_CTIME) {
1106 cFYI(1, (" CIFS - CTIME changed ")); /* BB probably no need */
1107 time_buf.ChangeTime =
1108 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1110 time_buf.ChangeTime = 0;
1112 if (set_time || time_buf.Attributes) {
1113 /* BB what if setting one attribute fails (such as size) but
1114 time setting works? */
1115 time_buf.CreationTime = 0; /* do not change */
1116 /* In the future we should experiment - try setting timestamps
1117 via Handle (SetFileInfo) instead of by path */
1118 if (!(pTcon->ses->flags & CIFS_SES_NT4))
1119 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
1121 cifs_sb->mnt_cifs_flags &
1122 CIFS_MOUNT_MAP_SPECIAL_CHR);
1126 if (rc == -EOPNOTSUPP) {
1130 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
1131 "times not supported by this server"));
1132 /* BB we could scan to see if we already have it open
1133 and pass in pid of opener to function */
1134 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1135 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1136 CREATE_NOT_DIR, &netfid, &oplock,
1137 NULL, cifs_sb->local_nls,
1138 cifs_sb->mnt_cifs_flags &
1139 CIFS_MOUNT_MAP_SPECIAL_CHR);
1141 rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
1143 CIFSSMBClose(xid, pTcon, netfid);
1145 /* BB For even older servers we could convert time_buf
1146 into old DOS style which uses two second
1149 /* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
1150 &time_buf, cifs_sb->local_nls); */
1155 /* do not need local check to inode_check_ok since the server does
1158 rc = inode_setattr(direntry->d_inode, attrs);
1164 void cifs_delete_inode(struct inode *inode)
1166 cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
1167 /* may have to add back in if and when safe distributed caching of
1168 directories added e.g. via FindNotify */