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 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
168 &cifs_file_direct_nobrl_ops;
170 inode->i_fop = &cifs_file_direct_ops;
171 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
172 inode->i_fop = &cifs_file_nobrl_ops;
173 else /* not direct, send byte range locks */
174 inode->i_fop = &cifs_file_ops;
176 inode->i_data.a_ops = &cifs_addr_ops;
177 /* check if server can support readpages */
178 if(pTcon->ses->server->maxBuf <
179 4096 + MAX_CIFS_HDR_SIZE)
180 inode->i_data.a_ops->readpages = NULL;
181 } else if (S_ISDIR(inode->i_mode)) {
182 cFYI(1, ("Directory inode"));
183 inode->i_op = &cifs_dir_inode_ops;
184 inode->i_fop = &cifs_dir_ops;
185 } else if (S_ISLNK(inode->i_mode)) {
186 cFYI(1, ("Symbolic Link inode"));
187 inode->i_op = &cifs_symlink_inode_ops;
188 /* tmp_inode->i_fop = */ /* do not need to set to anything */
190 cFYI(1, ("Init special inode"));
191 init_special_inode(inode, inode->i_mode,
198 int cifs_get_inode_info(struct inode **pinode,
199 const unsigned char *search_path, FILE_ALL_INFO *pfindData,
200 struct super_block *sb, int xid)
203 struct cifsTconInfo *pTcon;
205 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
209 pTcon = cifs_sb->tcon;
210 cFYI(1,("Getting info on %s ", search_path));
212 if ((pfindData == NULL) && (*pinode != NULL)) {
213 if (CIFS_I(*pinode)->clientCanCacheRead) {
214 cFYI(1,("No need to revalidate cached inode sizes"));
219 /* if file info not passed in then get it from server */
220 if (pfindData == NULL) {
221 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
224 pfindData = (FILE_ALL_INFO *)buf;
225 /* could do find first instead but this returns more info */
226 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
227 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
228 CIFS_MOUNT_MAP_SPECIAL_CHR);
229 /* BB optimize code so we do not make the above call
230 when server claims no NT SMB support and the above call
231 failed at least once - set flag in tcon or mount */
232 if((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
233 rc = SMBQueryInformation(xid, pTcon, search_path,
234 pfindData, cifs_sb->local_nls,
235 cifs_sb->mnt_cifs_flags &
236 CIFS_MOUNT_MAP_SPECIAL_CHR);
240 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
242 if (rc == -EREMOTE) {
247 strnlen(search_path, MAX_PATHCONF) + 1,
249 if (tmp_path == NULL) {
254 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
255 strncat(tmp_path, search_path, MAX_PATHCONF);
256 rc = connect_to_dfs_path(xid, pTcon->ses,
257 /* treename + */ tmp_path,
259 cifs_sb->mnt_cifs_flags &
260 CIFS_MOUNT_MAP_SPECIAL_CHR);
262 /* BB fix up inode etc. */
268 struct cifsInodeInfo *cifsInfo;
269 __u32 attr = le32_to_cpu(pfindData->Attributes);
272 if (*pinode == NULL) {
273 *pinode = new_inode(sb);
276 /* Is an i_ino of zero legal? Can we use that to check
277 if the server supports returning inode numbers? Are
278 there other sanity checks we can use to ensure that
279 the server is really filling in that field? */
281 /* We can not use the IndexNumber field by default from
282 Windows or Samba (in ALL_INFO buf) but we can request
283 it explicitly. It may not be unique presumably if
284 the server has multiple devices mounted under one
287 /* There may be higher info levels that work but are
288 there Windows server or network appliances for which
289 IndexNumber field is not guaranteed unique? */
291 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
295 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
296 search_path, &inode_num,
298 cifs_sb->mnt_cifs_flags &
299 CIFS_MOUNT_MAP_SPECIAL_CHR);
301 cFYI(1,("GetSrvInodeNum rc %d", rc1));
302 /* BB EOPNOSUPP disable SERVER_INUM? */
303 } else /* do we need cast or hash to ino? */
304 (*pinode)->i_ino = inode_num;
305 } /* else ino incremented to unique num in new_inode*/
306 insert_inode_hash(*pinode);
309 cifsInfo = CIFS_I(inode);
310 cifsInfo->cifsAttrs = attr;
311 cFYI(1, (" Old time %ld ", cifsInfo->time));
312 cifsInfo->time = jiffies;
313 cFYI(1, (" New time %ld ", cifsInfo->time));
315 /* blksize needs to be multiple of two. So safer to default to
316 blksize and blkbits set in superblock so 2**blkbits and blksize
317 will match rather than setting to:
318 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
320 /* Linux can not store file creation time unfortunately so we ignore it */
322 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
324 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
326 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
327 cFYI(0, (" Attributes came in as 0x%x ", attr));
329 /* set default mode. will override for dirs below */
330 if (atomic_read(&cifsInfo->inUse) == 0)
331 /* new inode, can safely set these fields */
332 inode->i_mode = cifs_sb->mnt_file_mode;
334 /* if (attr & ATTR_REPARSE) */
335 /* We no longer handle these as symlinks because we could not
336 follow them due to the absolute path with drive letter */
337 if (attr & ATTR_DIRECTORY) {
338 /* override default perms since we do not do byte range locking
340 inode->i_mode = cifs_sb->mnt_dir_mode;
341 inode->i_mode |= S_IFDIR;
342 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
343 (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
344 /* No need to le64 convert size of zero */
345 (pfindData->EndOfFile == 0)) {
346 inode->i_mode = cifs_sb->mnt_file_mode;
347 inode->i_mode |= S_IFIFO;
348 /* BB Finish for SFU style symlinks and devies */
349 /* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
350 (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */
353 inode->i_mode |= S_IFREG;
354 /* treat the dos attribute of read-only as read-only
356 if (cifsInfo->cifsAttrs & ATTR_READONLY)
357 inode->i_mode &= ~(S_IWUGO);
358 /* BB add code here -
359 validate if device or weird share or device type? */
361 if (is_size_safe_to_change(cifsInfo)) {
362 /* can not safely change the file size here if the
363 client is writing to it due to potential races */
364 i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
366 /* 512 bytes (2**9) is the fake blocksize that must be
367 used for this calculation */
368 inode->i_blocks = (512 - 1 + le64_to_cpu(
369 pfindData->AllocationSize)) >> 9;
372 inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
374 /* BB fill in uid and gid here? with help from winbind?
375 or retrieve from NTFS stream extended attribute */
376 if (atomic_read(&cifsInfo->inUse) == 0) {
377 inode->i_uid = cifs_sb->mnt_uid;
378 inode->i_gid = cifs_sb->mnt_gid;
379 /* set so we do not keep refreshing these fields with
380 bad data after user has changed them in memory */
381 atomic_set(&cifsInfo->inUse,1);
384 if (S_ISREG(inode->i_mode)) {
385 cFYI(1, (" File inode "));
386 inode->i_op = &cifs_file_inode_ops;
387 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
388 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
390 &cifs_file_direct_nobrl_ops;
392 inode->i_fop = &cifs_file_direct_ops;
393 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
394 inode->i_fop = &cifs_file_nobrl_ops;
395 else /* not direct, send byte range locks */
396 inode->i_fop = &cifs_file_ops;
398 inode->i_data.a_ops = &cifs_addr_ops;
399 if(pTcon->ses->server->maxBuf <
400 4096 + MAX_CIFS_HDR_SIZE)
401 inode->i_data.a_ops->readpages = NULL;
402 } else if (S_ISDIR(inode->i_mode)) {
403 cFYI(1, (" Directory inode "));
404 inode->i_op = &cifs_dir_inode_ops;
405 inode->i_fop = &cifs_dir_ops;
406 } else if (S_ISLNK(inode->i_mode)) {
407 cFYI(1, (" Symbolic Link inode "));
408 inode->i_op = &cifs_symlink_inode_ops;
410 init_special_inode(inode, inode->i_mode,
418 /* gets root inode */
419 void cifs_read_inode(struct inode *inode)
422 struct cifs_sb_info *cifs_sb;
424 cifs_sb = CIFS_SB(inode->i_sb);
426 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
427 cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
429 cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
430 /* can not call macro FreeXid here since in a void func */
434 int cifs_unlink(struct inode *inode, struct dentry *direntry)
438 struct cifs_sb_info *cifs_sb;
439 struct cifsTconInfo *pTcon;
440 char *full_path = NULL;
441 struct cifsInodeInfo *cifsInode;
442 FILE_BASIC_INFO *pinfo_buf;
444 cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
448 cifs_sb = CIFS_SB(inode->i_sb);
449 pTcon = cifs_sb->tcon;
451 /* Unlink can be called from rename so we can not grab the sem here
452 since we deadlock otherwise */
453 /* down(&direntry->d_sb->s_vfs_rename_sem);*/
454 full_path = build_path_from_dentry(direntry);
455 /* up(&direntry->d_sb->s_vfs_rename_sem);*/
456 if (full_path == NULL) {
460 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
461 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
464 if (direntry->d_inode)
465 direntry->d_inode->i_nlink--;
466 } else if (rc == -ENOENT) {
468 } else if (rc == -ETXTBSY) {
472 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
473 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
474 &netfid, &oplock, NULL, cifs_sb->local_nls,
475 cifs_sb->mnt_cifs_flags &
476 CIFS_MOUNT_MAP_SPECIAL_CHR);
478 CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
480 cifs_sb->mnt_cifs_flags &
481 CIFS_MOUNT_MAP_SPECIAL_CHR);
482 CIFSSMBClose(xid, pTcon, netfid);
483 if (direntry->d_inode)
484 direntry->d_inode->i_nlink--;
486 } else if (rc == -EACCES) {
487 /* try only if r/o attribute set in local lookup data? */
488 pinfo_buf = kmalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
490 memset(pinfo_buf, 0, sizeof(FILE_BASIC_INFO));
491 /* ATTRS set to normal clears r/o bit */
492 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
493 if (!(pTcon->ses->flags & CIFS_SES_NT4))
494 rc = CIFSSMBSetTimes(xid, pTcon, full_path,
497 cifs_sb->mnt_cifs_flags &
498 CIFS_MOUNT_MAP_SPECIAL_CHR);
502 if (rc == -EOPNOTSUPP) {
505 /* rc = CIFSSMBSetAttrLegacy(xid, pTcon,
509 For some strange reason it seems that NT4 eats the
510 old setattr call without actually setting the
511 attributes so on to the third attempted workaround
514 /* BB could scan to see if we already have it open
515 and pass in pid of opener to function */
516 rc = CIFSSMBOpen(xid, pTcon, full_path,
517 FILE_OPEN, SYNCHRONIZE |
518 FILE_WRITE_ATTRIBUTES, 0,
519 &netfid, &oplock, NULL,
521 cifs_sb->mnt_cifs_flags &
522 CIFS_MOUNT_MAP_SPECIAL_CHR);
524 rc = CIFSSMBSetFileTimes(xid, pTcon,
527 CIFSSMBClose(xid, pTcon, netfid);
533 rc = CIFSSMBDelFile(xid, pTcon, full_path,
535 cifs_sb->mnt_cifs_flags &
536 CIFS_MOUNT_MAP_SPECIAL_CHR);
538 if (direntry->d_inode)
539 direntry->d_inode->i_nlink--;
540 } else if (rc == -ETXTBSY) {
544 rc = CIFSSMBOpen(xid, pTcon, full_path,
547 CREATE_DELETE_ON_CLOSE,
548 &netfid, &oplock, NULL,
550 cifs_sb->mnt_cifs_flags &
551 CIFS_MOUNT_MAP_SPECIAL_CHR);
553 CIFSSMBRenameOpenFile(xid, pTcon,
556 cifs_sb->mnt_cifs_flags &
557 CIFS_MOUNT_MAP_SPECIAL_CHR);
558 CIFSSMBClose(xid, pTcon, netfid);
559 if (direntry->d_inode)
560 direntry->d_inode->i_nlink--;
562 /* BB if rc = -ETXTBUSY goto the rename logic BB */
566 if (direntry->d_inode) {
567 cifsInode = CIFS_I(direntry->d_inode);
568 cifsInode->time = 0; /* will force revalidate to get info
570 direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
572 inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
573 cifsInode = CIFS_I(inode);
574 cifsInode->time = 0; /* force revalidate of dir as well */
581 int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
585 struct cifs_sb_info *cifs_sb;
586 struct cifsTconInfo *pTcon;
587 char *full_path = NULL;
588 struct inode *newinode = NULL;
590 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
594 cifs_sb = CIFS_SB(inode->i_sb);
595 pTcon = cifs_sb->tcon;
597 down(&inode->i_sb->s_vfs_rename_sem);
598 full_path = build_path_from_dentry(direntry);
599 up(&inode->i_sb->s_vfs_rename_sem);
600 if (full_path == NULL) {
604 /* BB add setting the equivalent of mode via CreateX w/ACLs */
605 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
606 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
608 cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
612 if (pTcon->ses->capabilities & CAP_UNIX)
613 rc = cifs_get_inode_info_unix(&newinode, full_path,
616 rc = cifs_get_inode_info(&newinode, full_path, NULL,
620 direntry->d_op = &cifs_ci_dentry_ops;
622 direntry->d_op = &cifs_dentry_ops;
623 d_instantiate(direntry, newinode);
624 if (direntry->d_inode)
625 direntry->d_inode->i_nlink = 2;
626 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
627 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
628 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
630 (__u64)current->euid,
631 (__u64)current->egid,
634 cifs_sb->mnt_cifs_flags &
635 CIFS_MOUNT_MAP_SPECIAL_CHR);
637 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
639 (__u64)-1, 0 /* dev_t */,
641 cifs_sb->mnt_cifs_flags &
642 CIFS_MOUNT_MAP_SPECIAL_CHR);
645 /* BB to be implemented via Windows secrty descriptors
646 eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
647 -1, -1, local_nls); */
655 int cifs_rmdir(struct inode *inode, struct dentry *direntry)
659 struct cifs_sb_info *cifs_sb;
660 struct cifsTconInfo *pTcon;
661 char *full_path = NULL;
662 struct cifsInodeInfo *cifsInode;
664 cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
668 cifs_sb = CIFS_SB(inode->i_sb);
669 pTcon = cifs_sb->tcon;
671 down(&inode->i_sb->s_vfs_rename_sem);
672 full_path = build_path_from_dentry(direntry);
673 up(&inode->i_sb->s_vfs_rename_sem);
674 if (full_path == NULL) {
679 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
680 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
684 i_size_write(direntry->d_inode,0);
685 direntry->d_inode->i_nlink = 0;
688 cifsInode = CIFS_I(direntry->d_inode);
689 cifsInode->time = 0; /* force revalidate to go get info when
691 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
692 current_fs_time(inode->i_sb);
699 int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
700 struct inode *target_inode, struct dentry *target_direntry)
704 struct cifs_sb_info *cifs_sb_source;
705 struct cifs_sb_info *cifs_sb_target;
706 struct cifsTconInfo *pTcon;
712 cifs_sb_target = CIFS_SB(target_inode->i_sb);
713 cifs_sb_source = CIFS_SB(source_inode->i_sb);
714 pTcon = cifs_sb_source->tcon;
716 if (pTcon != cifs_sb_target->tcon) {
718 return -EXDEV; /* BB actually could be allowed if same server,
720 Might eventually add support for this */
723 /* we already have the rename sem so we do not need to grab it again
724 here to protect the path integrity */
725 fromName = build_path_from_dentry(source_direntry);
726 toName = build_path_from_dentry(target_direntry);
727 if ((fromName == NULL) || (toName == NULL)) {
729 goto cifs_rename_exit;
732 rc = CIFSSMBRename(xid, pTcon, fromName, toName,
733 cifs_sb_source->local_nls,
734 cifs_sb_source->mnt_cifs_flags &
735 CIFS_MOUNT_MAP_SPECIAL_CHR);
737 /* check if they are the same file because rename of hardlinked
739 FILE_UNIX_BASIC_INFO *info_buf_source;
740 FILE_UNIX_BASIC_INFO *info_buf_target;
743 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
744 if (info_buf_source != NULL) {
745 info_buf_target = info_buf_source + 1;
746 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
747 info_buf_source, cifs_sb_source->local_nls,
748 cifs_sb_source->mnt_cifs_flags &
749 CIFS_MOUNT_MAP_SPECIAL_CHR);
751 rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
753 cifs_sb_target->local_nls,
754 /* remap based on source sb */
755 cifs_sb_source->mnt_cifs_flags &
756 CIFS_MOUNT_MAP_SPECIAL_CHR);
759 (info_buf_source->UniqueId ==
760 info_buf_target->UniqueId)) {
761 /* do not rename since the files are hardlinked which
764 /* we either can not tell the files are hardlinked
765 (as with Windows servers) or files are not
766 hardlinked so delete the target manually before
767 renaming to follow POSIX rather than Windows
769 cifs_unlink(target_inode, target_direntry);
770 rc = CIFSSMBRename(xid, pTcon, fromName,
772 cifs_sb_source->local_nls,
773 cifs_sb_source->mnt_cifs_flags
774 & CIFS_MOUNT_MAP_SPECIAL_CHR);
776 kfree(info_buf_source);
777 } /* if we can not get memory just leave rc as EEXIST */
781 cFYI(1, ("rename rc %d", rc));
784 if ((rc == -EIO) || (rc == -EEXIST)) {
788 /* BB FIXME Is Generic Read correct for rename? */
789 /* if renaming directory - we should not say CREATE_NOT_DIR,
790 need to test renaming open directory, also GENERIC_READ
791 might not right be right access to request */
792 rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
793 CREATE_NOT_DIR, &netfid, &oplock, NULL,
794 cifs_sb_source->local_nls,
795 cifs_sb_source->mnt_cifs_flags &
796 CIFS_MOUNT_MAP_SPECIAL_CHR);
798 CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
799 cifs_sb_source->local_nls,
800 cifs_sb_source->mnt_cifs_flags &
801 CIFS_MOUNT_MAP_SPECIAL_CHR);
802 CIFSSMBClose(xid, pTcon, netfid);
813 int cifs_revalidate(struct dentry *direntry)
818 struct cifs_sb_info *cifs_sb;
819 struct cifsInodeInfo *cifsInode;
821 struct timespec local_mtime;
822 int invalidate_inode = FALSE;
824 if (direntry->d_inode == NULL)
827 cifsInode = CIFS_I(direntry->d_inode);
829 if (cifsInode == NULL)
832 /* no sense revalidating inode info on file that no one can write */
833 if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
838 cifs_sb = CIFS_SB(direntry->d_sb);
840 /* can not safely grab the rename sem here if rename calls revalidate
841 since that would deadlock */
842 full_path = build_path_from_dentry(direntry);
843 if (full_path == NULL) {
847 cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
848 "jiffies %ld", full_path, direntry->d_inode,
849 direntry->d_inode->i_count.counter, direntry,
850 direntry->d_time, jiffies));
852 if (cifsInode->time == 0) {
853 /* was set to zero previously to force revalidate */
854 } else if (time_before(jiffies, cifsInode->time + HZ) &&
855 lookupCacheEnabled) {
856 if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
857 (direntry->d_inode->i_nlink == 1)) {
862 cFYI(1, ("Have to revalidate file due to hardlinks"));
866 /* save mtime and size */
867 local_mtime = direntry->d_inode->i_mtime;
868 local_size = direntry->d_inode->i_size;
870 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
871 rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
874 cFYI(1, ("error on getting revalidate info %d", rc));
875 /* if (rc != -ENOENT)
876 rc = 0; */ /* BB should we cache info on
880 rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
883 cFYI(1, ("error on getting revalidate info %d", rc));
884 /* if (rc != -ENOENT)
885 rc = 0; */ /* BB should we cache info on
889 /* should we remap certain errors, access denied?, to zero */
891 /* if not oplocked, we invalidate inode pages if mtime or file size
892 had changed on server */
894 if (timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
895 (local_size == direntry->d_inode->i_size)) {
896 cFYI(1, ("cifs_revalidate - inode unchanged"));
898 /* file may have changed on server */
899 if (cifsInode->clientCanCacheRead) {
900 /* no need to invalidate inode pages since we were the
901 only ones who could have modified the file and the
902 server copy is staler than ours */
904 invalidate_inode = TRUE;
908 /* can not grab this sem since kernel filesys locking documentation
909 indicates i_sem may be taken by the kernel on lookup and rename
910 which could deadlock if we grab the i_sem here as well */
911 /* down(&direntry->d_inode->i_sem);*/
912 /* need to write out dirty pages here */
913 if (direntry->d_inode->i_mapping) {
914 /* do we need to lock inode until after invalidate completes
916 filemap_fdatawrite(direntry->d_inode->i_mapping);
918 if (invalidate_inode) {
919 if (direntry->d_inode->i_mapping)
920 filemap_fdatawait(direntry->d_inode->i_mapping);
921 /* may eventually have to do this for open files too */
922 if (list_empty(&(cifsInode->openFileList))) {
923 /* Has changed on server - flush read ahead pages */
924 cFYI(1, ("Invalidating read ahead data on "
926 invalidate_remote_inode(direntry->d_inode);
929 /* up(&direntry->d_inode->i_sem); */
936 int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
939 int err = cifs_revalidate(dentry);
941 generic_fillattr(dentry->d_inode, stat);
945 static int cifs_truncate_page(struct address_space *mapping, loff_t from)
947 pgoff_t index = from >> PAGE_CACHE_SHIFT;
948 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
953 page = grab_cache_page(mapping, index);
957 kaddr = kmap_atomic(page, KM_USER0);
958 memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
959 flush_dcache_page(page);
960 kunmap_atomic(kaddr, KM_USER0);
962 page_cache_release(page);
966 int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
969 struct cifs_sb_info *cifs_sb;
970 struct cifsTconInfo *pTcon;
971 char *full_path = NULL;
973 struct cifsFileInfo *open_file = NULL;
974 FILE_BASIC_INFO time_buf;
975 int set_time = FALSE;
976 __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
977 __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
978 __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
979 struct cifsInodeInfo *cifsInode;
983 cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
984 direntry->d_name.name, attrs->ia_valid));
985 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
986 pTcon = cifs_sb->tcon;
988 down(&direntry->d_sb->s_vfs_rename_sem);
989 full_path = build_path_from_dentry(direntry);
990 up(&direntry->d_sb->s_vfs_rename_sem);
991 if (full_path == NULL) {
995 cifsInode = CIFS_I(direntry->d_inode);
997 /* BB check if we need to refresh inode from server now ? BB */
999 /* need to flush data before changing file size on server */
1000 filemap_fdatawrite(direntry->d_inode->i_mapping);
1001 filemap_fdatawait(direntry->d_inode->i_mapping);
1003 if (attrs->ia_valid & ATTR_SIZE) {
1004 /* To avoid spurious oplock breaks from server, in the case of
1005 inodes that we already have open, avoid doing path based
1006 setting of file size if we can do it by handle.
1007 This keeps our caching token (oplock) and avoids timeouts
1008 when the local oplock break takes longer to flush
1009 writebehind data than the SMB timeout for the SetPathInfo
1010 request would allow */
1011 open_file = find_writable_file(cifsInode);
1013 __u16 nfid = open_file->netfid;
1014 __u32 npid = open_file->pid;
1015 rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
1017 atomic_dec(&open_file->wrtPending);
1018 cFYI(1,("SetFSize for attrs rc = %d", rc));
1021 rc = CIFSSMBWrite(xid, pTcon,
1022 nfid, 0, attrs->ia_size,
1023 &bytes_written, NULL, NULL,
1024 1 /* 45 seconds */);
1025 cFYI(1,("Wrt seteof rc %d", rc));
1029 /* Set file size by pathname rather than by handle
1030 either because no valid, writeable file handle for
1031 it was found or because there was an error setting
1033 rc = CIFSSMBSetEOF(xid, pTcon, full_path,
1034 attrs->ia_size, FALSE,
1036 cifs_sb->mnt_cifs_flags &
1037 CIFS_MOUNT_MAP_SPECIAL_CHR);
1038 cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
1043 rc = SMBLegacyOpen(xid, pTcon, full_path,
1045 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1046 CREATE_NOT_DIR, &netfid, &oplock,
1047 NULL, cifs_sb->local_nls,
1048 cifs_sb->mnt_cifs_flags &
1049 CIFS_MOUNT_MAP_SPECIAL_CHR);
1052 rc = CIFSSMBWrite(xid, pTcon,
1055 &bytes_written, NULL,
1056 NULL, 1 /* 45 sec */);
1057 cFYI(1,("wrt seteof rc %d",rc));
1058 CIFSSMBClose(xid, pTcon, netfid);
1064 /* Server is ok setting allocation size implicitly - no need
1066 CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE,
1067 cifs_sb->local_nls);
1071 rc = vmtruncate(direntry->d_inode, attrs->ia_size);
1072 cifs_truncate_page(direntry->d_inode->i_mapping,
1073 direntry->d_inode->i_size);
1075 goto cifs_setattr_exit;
1077 if (attrs->ia_valid & ATTR_UID) {
1078 cFYI(1, ("UID changed to %d", attrs->ia_uid));
1079 uid = attrs->ia_uid;
1081 if (attrs->ia_valid & ATTR_GID) {
1082 cFYI(1, ("GID changed to %d", attrs->ia_gid));
1083 gid = attrs->ia_gid;
1086 time_buf.Attributes = 0;
1087 if (attrs->ia_valid & ATTR_MODE) {
1088 cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode));
1089 mode = attrs->ia_mode;
1092 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
1093 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
1094 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
1095 0 /* dev_t */, cifs_sb->local_nls,
1096 cifs_sb->mnt_cifs_flags &
1097 CIFS_MOUNT_MAP_SPECIAL_CHR);
1098 else if (attrs->ia_valid & ATTR_MODE) {
1099 if ((mode & S_IWUGO) == 0) /* not writeable */ {
1100 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
1101 time_buf.Attributes =
1102 cpu_to_le32(cifsInode->cifsAttrs |
1104 } else if ((mode & S_IWUGO) == S_IWUGO) {
1105 if (cifsInode->cifsAttrs & ATTR_READONLY)
1106 time_buf.Attributes =
1107 cpu_to_le32(cifsInode->cifsAttrs &
1110 /* BB to be implemented -
1111 via Windows security descriptors or streams */
1112 /* CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, uid, gid,
1113 cifs_sb->local_nls); */
1116 if (attrs->ia_valid & ATTR_ATIME) {
1118 time_buf.LastAccessTime =
1119 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1121 time_buf.LastAccessTime = 0;
1123 if (attrs->ia_valid & ATTR_MTIME) {
1125 time_buf.LastWriteTime =
1126 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1128 time_buf.LastWriteTime = 0;
1129 /* Do not set ctime explicitly unless other time
1130 stamps are changed explicitly (i.e. by utime()
1131 since we would then have a mix of client and
1134 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
1136 /* Although Samba throws this field away
1137 it may be useful to Windows - but we do
1138 not want to set ctime unless some other
1139 timestamp is changing */
1140 cFYI(1, ("CIFS - CTIME changed "));
1141 time_buf.ChangeTime =
1142 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1144 time_buf.ChangeTime = 0;
1146 if (set_time || time_buf.Attributes) {
1147 time_buf.CreationTime = 0; /* do not change */
1148 /* In the future we should experiment - try setting timestamps
1149 via Handle (SetFileInfo) instead of by path */
1150 if (!(pTcon->ses->flags & CIFS_SES_NT4))
1151 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
1153 cifs_sb->mnt_cifs_flags &
1154 CIFS_MOUNT_MAP_SPECIAL_CHR);
1158 if (rc == -EOPNOTSUPP) {
1162 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
1163 "times not supported by this server"));
1164 /* BB we could scan to see if we already have it open
1165 and pass in pid of opener to function */
1166 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1167 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1168 CREATE_NOT_DIR, &netfid, &oplock,
1169 NULL, cifs_sb->local_nls,
1170 cifs_sb->mnt_cifs_flags &
1171 CIFS_MOUNT_MAP_SPECIAL_CHR);
1173 rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
1175 CIFSSMBClose(xid, pTcon, netfid);
1177 /* BB For even older servers we could convert time_buf
1178 into old DOS style which uses two second
1181 /* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
1182 &time_buf, cifs_sb->local_nls); */
1185 /* Even if error on time set, no sense failing the call if
1186 the server would set the time to a reasonable value anyway,
1187 and this check ensures that we are not being called from
1188 sys_utimes in which case we ought to fail the call back to
1189 the user when the server rejects the call */
1190 if((rc) && (attrs->ia_valid &&
1191 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
1195 /* do not need local check to inode_check_ok since the server does
1198 rc = inode_setattr(direntry->d_inode, attrs);
1205 void cifs_delete_inode(struct inode *inode)
1207 cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
1208 /* may have to add back in if and when safe distributed caching of
1209 directories added e.g. via FindNotify */