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/stat.h>
23 #include <linux/pagemap.h>
24 #include <asm/div64.h>
28 #include "cifsproto.h"
29 #include "cifs_debug.h"
30 #include "cifs_fs_sb.h"
32 int cifs_get_inode_info_unix(struct inode **pinode,
33 const unsigned char *search_path, struct super_block *sb, int xid)
36 FILE_UNIX_BASIC_INFO findData;
37 struct cifsTconInfo *pTcon;
39 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
42 pTcon = cifs_sb->tcon;
43 cFYI(1, ("Getting info on %s", search_path));
44 /* could have done a find first instead but this returns more info */
45 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
46 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
47 CIFS_MOUNT_MAP_SPECIAL_CHR);
48 /* dump_mem("\nUnixQPathInfo return data", &findData,
53 kmalloc(strnlen(pTcon->treeName,
55 strnlen(search_path, MAX_PATHCONF) + 1,
57 if (tmp_path == NULL) {
60 /* have to skip first of the double backslash of
62 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
63 strncat(tmp_path, search_path, MAX_PATHCONF);
64 rc = connect_to_dfs_path(xid, pTcon->ses,
65 /* treename + */ tmp_path,
67 cifs_sb->mnt_cifs_flags &
68 CIFS_MOUNT_MAP_SPECIAL_CHR);
71 /* BB fix up inode etc. */
76 struct cifsInodeInfo *cifsInfo;
77 __u32 type = le32_to_cpu(findData.Type);
78 __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
79 __u64 end_of_file = le64_to_cpu(findData.EndOfFile);
82 if (*pinode == NULL) {
83 *pinode = new_inode(sb);
86 /* Is an i_ino of zero legal? */
87 /* Are there sanity checks we can use to ensure that
88 the server is really filling in that field? */
89 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
91 (unsigned long)findData.UniqueId;
92 } /* note ino incremented to unique num in new_inode */
93 insert_inode_hash(*pinode);
97 cifsInfo = CIFS_I(inode);
99 cFYI(1, ("Old time %ld", cifsInfo->time));
100 cifsInfo->time = jiffies;
101 cFYI(1, ("New time %ld", cifsInfo->time));
102 /* this is ok to set on every inode revalidate */
103 atomic_set(&cifsInfo->inUse,1);
106 cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
108 cifs_NTtimeToUnix(le64_to_cpu
109 (findData.LastModificationTime));
111 cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
112 inode->i_mode = le64_to_cpu(findData.Permissions);
113 /* since we set the inode type below we need to mask off
114 to avoid strange results if bits set above */
115 inode->i_mode &= ~S_IFMT;
116 if (type == UNIX_FILE) {
117 inode->i_mode |= S_IFREG;
118 } else if (type == UNIX_SYMLINK) {
119 inode->i_mode |= S_IFLNK;
120 } else if (type == UNIX_DIR) {
121 inode->i_mode |= S_IFDIR;
122 } else if (type == UNIX_CHARDEV) {
123 inode->i_mode |= S_IFCHR;
124 inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
125 le64_to_cpu(findData.DevMinor) & MINORMASK);
126 } else if (type == UNIX_BLOCKDEV) {
127 inode->i_mode |= S_IFBLK;
128 inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
129 le64_to_cpu(findData.DevMinor) & MINORMASK);
130 } else if (type == UNIX_FIFO) {
131 inode->i_mode |= S_IFIFO;
132 } else if (type == UNIX_SOCKET) {
133 inode->i_mode |= S_IFSOCK;
135 /* safest to call it a file if we do not know */
136 inode->i_mode |= S_IFREG;
137 cFYI(1,("unknown type %d",type));
139 inode->i_uid = le64_to_cpu(findData.Uid);
140 inode->i_gid = le64_to_cpu(findData.Gid);
141 inode->i_nlink = le64_to_cpu(findData.Nlinks);
143 if (is_size_safe_to_change(cifsInfo)) {
144 /* can not safely change the file size here if the
145 client is writing to it due to potential races */
147 i_size_write(inode, end_of_file);
149 /* blksize needs to be multiple of two. So safer to default to
150 blksize and blkbits set in superblock so 2**blkbits and blksize
151 will match rather than setting to:
152 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
154 /* This seems incredibly stupid but it turns out that i_blocks
155 is not related to (i_size / i_blksize), instead 512 byte size
156 is required for calculating num blocks */
158 /* 512 bytes (2**9) is the fake blocksize that must be used */
159 /* for this calculation */
160 inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
163 if (num_of_bytes < end_of_file)
164 cFYI(1, ("allocation size less than end of file"));
165 cFYI(1, ("Size %ld and blocks %llu",
166 (unsigned long) inode->i_size,
167 (unsigned long long)inode->i_blocks));
168 if (S_ISREG(inode->i_mode)) {
169 cFYI(1, ("File inode"));
170 inode->i_op = &cifs_file_inode_ops;
171 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
172 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
174 &cifs_file_direct_nobrl_ops;
176 inode->i_fop = &cifs_file_direct_ops;
177 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
178 inode->i_fop = &cifs_file_nobrl_ops;
179 else /* not direct, send byte range locks */
180 inode->i_fop = &cifs_file_ops;
182 /* check if server can support readpages */
183 if(pTcon->ses->server->maxBuf <
184 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
185 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
187 inode->i_data.a_ops = &cifs_addr_ops;
188 } else if (S_ISDIR(inode->i_mode)) {
189 cFYI(1, ("Directory inode"));
190 inode->i_op = &cifs_dir_inode_ops;
191 inode->i_fop = &cifs_dir_ops;
192 } else if (S_ISLNK(inode->i_mode)) {
193 cFYI(1, ("Symbolic Link inode"));
194 inode->i_op = &cifs_symlink_inode_ops;
195 /* tmp_inode->i_fop = */ /* do not need to set to anything */
197 cFYI(1, ("Init special inode"));
198 init_special_inode(inode, inode->i_mode,
205 static int decode_sfu_inode(struct inode * inode, __u64 size,
206 const unsigned char *path,
207 struct cifs_sb_info *cifs_sb, int xid)
212 struct cifsTconInfo *pTcon = cifs_sb->tcon;
214 unsigned int bytes_read;
220 inode->i_mode |= S_IFIFO;
222 } else if (size < 8) {
223 return -EINVAL; /* EOPNOTSUPP? */
226 rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
227 CREATE_NOT_DIR, &netfid, &oplock, NULL,
229 cifs_sb->mnt_cifs_flags &
230 CIFS_MOUNT_MAP_SPECIAL_CHR);
232 int buf_type = CIFS_NO_BUFFER;
234 rc = CIFSSMBRead(xid, pTcon,
236 24 /* length */, 0 /* offset */,
237 &bytes_read, &pbuf, &buf_type);
238 if((rc == 0) && (bytes_read >= 8)) {
239 if(memcmp("IntxBLK", pbuf, 8) == 0) {
240 cFYI(1,("Block device"));
241 inode->i_mode |= S_IFBLK;
242 if(bytes_read == 24) {
243 /* we have enough to decode dev num */
244 __u64 mjr; /* major */
245 __u64 mnr; /* minor */
246 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
247 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
248 inode->i_rdev = MKDEV(mjr, mnr);
250 } else if(memcmp("IntxCHR", pbuf, 8) == 0) {
251 cFYI(1,("Char device"));
252 inode->i_mode |= S_IFCHR;
253 if(bytes_read == 24) {
254 /* we have enough to decode dev num */
255 __u64 mjr; /* major */
256 __u64 mnr; /* minor */
257 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
258 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
259 inode->i_rdev = MKDEV(mjr, mnr);
261 } else if(memcmp("IntxLNK", pbuf, 7) == 0) {
263 inode->i_mode |= S_IFLNK;
265 inode->i_mode |= S_IFREG; /* file? */
269 inode->i_mode |= S_IFREG; /* then it is a file */
270 rc = -EOPNOTSUPP; /* or some unknown SFU type */
272 CIFSSMBClose(xid, pTcon, netfid);
278 #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
280 static int get_sfu_uid_mode(struct inode * inode,
281 const unsigned char *path,
282 struct cifs_sb_info *cifs_sb, int xid)
284 #ifdef CONFIG_CIFS_XATTR
289 rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
290 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
291 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
295 mode = le32_to_cpu(*((__le32 *)ea_value));
296 inode->i_mode &= ~SFBITS_MASK;
297 cFYI(1,("special bits 0%o org mode 0%o", mode, inode->i_mode));
298 inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode;
299 cFYI(1,("special mode bits 0%o", mode));
311 int cifs_get_inode_info(struct inode **pinode,
312 const unsigned char *search_path, FILE_ALL_INFO *pfindData,
313 struct super_block *sb, int xid)
316 struct cifsTconInfo *pTcon;
318 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
321 int adjustTZ = FALSE;
323 pTcon = cifs_sb->tcon;
324 cFYI(1,("Getting info on %s", search_path));
326 if ((pfindData == NULL) && (*pinode != NULL)) {
327 if (CIFS_I(*pinode)->clientCanCacheRead) {
328 cFYI(1,("No need to revalidate cached inode sizes"));
333 /* if file info not passed in then get it from server */
334 if (pfindData == NULL) {
335 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
338 pfindData = (FILE_ALL_INFO *)buf;
339 /* could do find first instead but this returns more info */
340 rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
342 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
343 CIFS_MOUNT_MAP_SPECIAL_CHR);
344 /* BB optimize code so we do not make the above call
345 when server claims no NT SMB support and the above call
346 failed at least once - set flag in tcon or mount */
347 if((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
348 rc = SMBQueryInformation(xid, pTcon, search_path,
349 pfindData, cifs_sb->local_nls,
350 cifs_sb->mnt_cifs_flags &
351 CIFS_MOUNT_MAP_SPECIAL_CHR);
356 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
358 if (rc == -EREMOTE) {
363 strnlen(search_path, MAX_PATHCONF) + 1,
365 if (tmp_path == NULL) {
370 strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
371 strncat(tmp_path, search_path, MAX_PATHCONF);
372 rc = connect_to_dfs_path(xid, pTcon->ses,
373 /* treename + */ tmp_path,
375 cifs_sb->mnt_cifs_flags &
376 CIFS_MOUNT_MAP_SPECIAL_CHR);
378 /* BB fix up inode etc. */
384 struct cifsInodeInfo *cifsInfo;
385 __u32 attr = le32_to_cpu(pfindData->Attributes);
388 if (*pinode == NULL) {
389 *pinode = new_inode(sb);
390 if (*pinode == NULL) {
394 /* Is an i_ino of zero legal? Can we use that to check
395 if the server supports returning inode numbers? Are
396 there other sanity checks we can use to ensure that
397 the server is really filling in that field? */
399 /* We can not use the IndexNumber field by default from
400 Windows or Samba (in ALL_INFO buf) but we can request
401 it explicitly. It may not be unique presumably if
402 the server has multiple devices mounted under one
405 /* There may be higher info levels that work but are
406 there Windows server or network appliances for which
407 IndexNumber field is not guaranteed unique? */
409 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
413 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
414 search_path, &inode_num,
416 cifs_sb->mnt_cifs_flags &
417 CIFS_MOUNT_MAP_SPECIAL_CHR);
419 cFYI(1,("GetSrvInodeNum rc %d", rc1));
420 /* BB EOPNOSUPP disable SERVER_INUM? */
421 } else /* do we need cast or hash to ino? */
422 (*pinode)->i_ino = inode_num;
423 } /* else ino incremented to unique num in new_inode*/
424 insert_inode_hash(*pinode);
427 cifsInfo = CIFS_I(inode);
428 cifsInfo->cifsAttrs = attr;
429 cFYI(1, ("Old time %ld", cifsInfo->time));
430 cifsInfo->time = jiffies;
431 cFYI(1, ("New time %ld", cifsInfo->time));
433 /* blksize needs to be multiple of two. So safer to default to
434 blksize and blkbits set in superblock so 2**blkbits and blksize
435 will match rather than setting to:
436 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
438 /* Linux can not store file creation time so ignore it */
439 if(pfindData->LastAccessTime)
440 inode->i_atime = cifs_NTtimeToUnix
441 (le64_to_cpu(pfindData->LastAccessTime));
442 else /* do not need to use current_fs_time - time not stored */
443 inode->i_atime = CURRENT_TIME;
445 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
447 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
448 cFYI(0, ("Attributes came in as 0x%x", attr));
449 if(adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
450 inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
451 inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
454 /* set default mode. will override for dirs below */
455 if (atomic_read(&cifsInfo->inUse) == 0)
456 /* new inode, can safely set these fields */
457 inode->i_mode = cifs_sb->mnt_file_mode;
458 else /* since we set the inode type below we need to mask off
459 to avoid strange results if type changes and both get orred in */
460 inode->i_mode &= ~S_IFMT;
461 /* if (attr & ATTR_REPARSE) */
462 /* We no longer handle these as symlinks because we could not
463 follow them due to the absolute path with drive letter */
464 if (attr & ATTR_DIRECTORY) {
465 /* override default perms since we do not do byte range locking
467 inode->i_mode = cifs_sb->mnt_dir_mode;
468 inode->i_mode |= S_IFDIR;
469 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
470 (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
471 /* No need to le64 convert size of zero */
472 (pfindData->EndOfFile == 0)) {
473 inode->i_mode = cifs_sb->mnt_file_mode;
474 inode->i_mode |= S_IFIFO;
475 /* BB Finish for SFU style symlinks and devices */
476 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
477 (cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
478 if (decode_sfu_inode(inode,
479 le64_to_cpu(pfindData->EndOfFile),
482 cFYI(1,("Unrecognized sfu inode type"));
484 cFYI(1,("sfu mode 0%o",inode->i_mode));
486 inode->i_mode |= S_IFREG;
487 /* treat the dos attribute of read-only as read-only
489 if (cifsInfo->cifsAttrs & ATTR_READONLY)
490 inode->i_mode &= ~(S_IWUGO);
491 else if ((inode->i_mode & S_IWUGO) == 0)
492 /* the ATTR_READONLY flag may have been */
493 /* changed on server -- set any w bits */
494 /* allowed by mnt_file_mode */
495 inode->i_mode |= (S_IWUGO &
496 cifs_sb->mnt_file_mode);
497 /* BB add code here -
498 validate if device or weird share or device type? */
500 if (is_size_safe_to_change(cifsInfo)) {
501 /* can not safely change the file size here if the
502 client is writing to it due to potential races */
503 i_size_write(inode,le64_to_cpu(pfindData->EndOfFile));
505 /* 512 bytes (2**9) is the fake blocksize that must be
506 used for this calculation */
507 inode->i_blocks = (512 - 1 + le64_to_cpu(
508 pfindData->AllocationSize)) >> 9;
511 inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
513 /* BB fill in uid and gid here? with help from winbind?
514 or retrieve from NTFS stream extended attribute */
515 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
516 /* fill in uid, gid, mode from server ACL */
517 get_sfu_uid_mode(inode, search_path, cifs_sb, xid);
518 } else if (atomic_read(&cifsInfo->inUse) == 0) {
519 inode->i_uid = cifs_sb->mnt_uid;
520 inode->i_gid = cifs_sb->mnt_gid;
521 /* set so we do not keep refreshing these fields with
522 bad data after user has changed them in memory */
523 atomic_set(&cifsInfo->inUse,1);
526 if (S_ISREG(inode->i_mode)) {
527 cFYI(1, ("File inode"));
528 inode->i_op = &cifs_file_inode_ops;
529 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
530 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
532 &cifs_file_direct_nobrl_ops;
534 inode->i_fop = &cifs_file_direct_ops;
535 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
536 inode->i_fop = &cifs_file_nobrl_ops;
537 else /* not direct, send byte range locks */
538 inode->i_fop = &cifs_file_ops;
540 if(pTcon->ses->server->maxBuf <
541 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
542 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
544 inode->i_data.a_ops = &cifs_addr_ops;
545 } else if (S_ISDIR(inode->i_mode)) {
546 cFYI(1, ("Directory inode"));
547 inode->i_op = &cifs_dir_inode_ops;
548 inode->i_fop = &cifs_dir_ops;
549 } else if (S_ISLNK(inode->i_mode)) {
550 cFYI(1, ("Symbolic Link inode"));
551 inode->i_op = &cifs_symlink_inode_ops;
553 init_special_inode(inode, inode->i_mode,
561 /* gets root inode */
562 void cifs_read_inode(struct inode *inode)
565 struct cifs_sb_info *cifs_sb;
567 cifs_sb = CIFS_SB(inode->i_sb);
569 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
570 cifs_get_inode_info_unix(&inode, "", inode->i_sb,xid);
572 cifs_get_inode_info(&inode, "", NULL, inode->i_sb,xid);
573 /* can not call macro FreeXid here since in a void func */
577 int cifs_unlink(struct inode *inode, struct dentry *direntry)
581 struct cifs_sb_info *cifs_sb;
582 struct cifsTconInfo *pTcon;
583 char *full_path = NULL;
584 struct cifsInodeInfo *cifsInode;
585 FILE_BASIC_INFO *pinfo_buf;
587 cFYI(1, ("cifs_unlink, inode = 0x%p", inode));
592 cifs_sb = CIFS_SB(inode->i_sb);
594 cifs_sb = CIFS_SB(direntry->d_sb);
595 pTcon = cifs_sb->tcon;
597 /* Unlink can be called from rename so we can not grab the sem here
598 since we deadlock otherwise */
599 /* mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);*/
600 full_path = build_path_from_dentry(direntry);
601 /* mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);*/
602 if (full_path == NULL) {
606 rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
607 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
610 if (direntry->d_inode)
611 drop_nlink(direntry->d_inode);
612 } else if (rc == -ENOENT) {
614 } else if (rc == -ETXTBSY) {
618 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
619 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
620 &netfid, &oplock, NULL, cifs_sb->local_nls,
621 cifs_sb->mnt_cifs_flags &
622 CIFS_MOUNT_MAP_SPECIAL_CHR);
624 CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
626 cifs_sb->mnt_cifs_flags &
627 CIFS_MOUNT_MAP_SPECIAL_CHR);
628 CIFSSMBClose(xid, pTcon, netfid);
629 if (direntry->d_inode)
630 drop_nlink(direntry->d_inode);
632 } else if (rc == -EACCES) {
633 /* try only if r/o attribute set in local lookup data? */
634 pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
636 /* ATTRS set to normal clears r/o bit */
637 pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
638 if (!(pTcon->ses->flags & CIFS_SES_NT4))
639 rc = CIFSSMBSetTimes(xid, pTcon, full_path,
642 cifs_sb->mnt_cifs_flags &
643 CIFS_MOUNT_MAP_SPECIAL_CHR);
647 if (rc == -EOPNOTSUPP) {
650 /* rc = CIFSSMBSetAttrLegacy(xid, pTcon,
654 For some strange reason it seems that NT4 eats the
655 old setattr call without actually setting the
656 attributes so on to the third attempted workaround
659 /* BB could scan to see if we already have it open
660 and pass in pid of opener to function */
661 rc = CIFSSMBOpen(xid, pTcon, full_path,
662 FILE_OPEN, SYNCHRONIZE |
663 FILE_WRITE_ATTRIBUTES, 0,
664 &netfid, &oplock, NULL,
666 cifs_sb->mnt_cifs_flags &
667 CIFS_MOUNT_MAP_SPECIAL_CHR);
669 rc = CIFSSMBSetFileTimes(xid, pTcon,
672 CIFSSMBClose(xid, pTcon, netfid);
678 rc = CIFSSMBDelFile(xid, pTcon, full_path,
680 cifs_sb->mnt_cifs_flags &
681 CIFS_MOUNT_MAP_SPECIAL_CHR);
683 if (direntry->d_inode)
684 drop_nlink(direntry->d_inode);
685 } else if (rc == -ETXTBSY) {
689 rc = CIFSSMBOpen(xid, pTcon, full_path,
692 CREATE_DELETE_ON_CLOSE,
693 &netfid, &oplock, NULL,
695 cifs_sb->mnt_cifs_flags &
696 CIFS_MOUNT_MAP_SPECIAL_CHR);
698 CIFSSMBRenameOpenFile(xid, pTcon,
701 cifs_sb->mnt_cifs_flags &
702 CIFS_MOUNT_MAP_SPECIAL_CHR);
703 CIFSSMBClose(xid, pTcon, netfid);
704 if (direntry->d_inode)
705 drop_nlink(direntry->d_inode);
707 /* BB if rc = -ETXTBUSY goto the rename logic BB */
711 if (direntry->d_inode) {
712 cifsInode = CIFS_I(direntry->d_inode);
713 cifsInode->time = 0; /* will force revalidate to get info
715 direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
718 inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
719 cifsInode = CIFS_I(inode);
720 cifsInode->time = 0; /* force revalidate of dir as well */
728 int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
732 struct cifs_sb_info *cifs_sb;
733 struct cifsTconInfo *pTcon;
734 char *full_path = NULL;
735 struct inode *newinode = NULL;
737 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
741 cifs_sb = CIFS_SB(inode->i_sb);
742 pTcon = cifs_sb->tcon;
744 full_path = build_path_from_dentry(direntry);
745 if (full_path == NULL) {
749 /* BB add setting the equivalent of mode via CreateX w/ACLs */
750 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
751 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
753 cFYI(1, ("cifs_mkdir returned 0x%x", rc));
757 if (pTcon->ses->capabilities & CAP_UNIX)
758 rc = cifs_get_inode_info_unix(&newinode, full_path,
761 rc = cifs_get_inode_info(&newinode, full_path, NULL,
765 direntry->d_op = &cifs_ci_dentry_ops;
767 direntry->d_op = &cifs_dentry_ops;
768 d_instantiate(direntry, newinode);
769 if (direntry->d_inode)
770 direntry->d_inode->i_nlink = 2;
771 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
772 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
773 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
775 (__u64)current->fsuid,
776 (__u64)current->fsgid,
779 cifs_sb->mnt_cifs_flags &
780 CIFS_MOUNT_MAP_SPECIAL_CHR);
782 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
784 (__u64)-1, 0 /* dev_t */,
786 cifs_sb->mnt_cifs_flags &
787 CIFS_MOUNT_MAP_SPECIAL_CHR);
790 /* BB to be implemented via Windows secrty descriptors
791 eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
792 -1, -1, local_nls); */
793 if(direntry->d_inode) {
794 direntry->d_inode->i_mode = mode;
795 direntry->d_inode->i_mode |= S_IFDIR;
796 if(cifs_sb->mnt_cifs_flags &
797 CIFS_MOUNT_SET_UID) {
798 direntry->d_inode->i_uid =
800 direntry->d_inode->i_gid =
811 int cifs_rmdir(struct inode *inode, struct dentry *direntry)
815 struct cifs_sb_info *cifs_sb;
816 struct cifsTconInfo *pTcon;
817 char *full_path = NULL;
818 struct cifsInodeInfo *cifsInode;
820 cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));
824 cifs_sb = CIFS_SB(inode->i_sb);
825 pTcon = cifs_sb->tcon;
827 full_path = build_path_from_dentry(direntry);
828 if (full_path == NULL) {
833 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
834 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
838 i_size_write(direntry->d_inode,0);
839 clear_nlink(direntry->d_inode);
842 cifsInode = CIFS_I(direntry->d_inode);
843 cifsInode->time = 0; /* force revalidate to go get info when
845 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
846 current_fs_time(inode->i_sb);
853 int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
854 struct inode *target_inode, struct dentry *target_direntry)
858 struct cifs_sb_info *cifs_sb_source;
859 struct cifs_sb_info *cifs_sb_target;
860 struct cifsTconInfo *pTcon;
866 cifs_sb_target = CIFS_SB(target_inode->i_sb);
867 cifs_sb_source = CIFS_SB(source_inode->i_sb);
868 pTcon = cifs_sb_source->tcon;
870 if (pTcon != cifs_sb_target->tcon) {
872 return -EXDEV; /* BB actually could be allowed if same server,
874 Might eventually add support for this */
877 /* we already have the rename sem so we do not need to grab it again
878 here to protect the path integrity */
879 fromName = build_path_from_dentry(source_direntry);
880 toName = build_path_from_dentry(target_direntry);
881 if ((fromName == NULL) || (toName == NULL)) {
883 goto cifs_rename_exit;
886 rc = CIFSSMBRename(xid, pTcon, fromName, toName,
887 cifs_sb_source->local_nls,
888 cifs_sb_source->mnt_cifs_flags &
889 CIFS_MOUNT_MAP_SPECIAL_CHR);
891 /* check if they are the same file because rename of hardlinked
893 FILE_UNIX_BASIC_INFO *info_buf_source;
894 FILE_UNIX_BASIC_INFO *info_buf_target;
897 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
898 if (info_buf_source != NULL) {
899 info_buf_target = info_buf_source + 1;
900 if (pTcon->ses->capabilities & CAP_UNIX)
901 rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
903 cifs_sb_source->local_nls,
904 cifs_sb_source->mnt_cifs_flags &
905 CIFS_MOUNT_MAP_SPECIAL_CHR);
906 /* else rc is still EEXIST so will fall through to
907 unlink the target and retry rename */
909 rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
911 cifs_sb_target->local_nls,
912 /* remap based on source sb */
913 cifs_sb_source->mnt_cifs_flags &
914 CIFS_MOUNT_MAP_SPECIAL_CHR);
917 (info_buf_source->UniqueId ==
918 info_buf_target->UniqueId)) {
919 /* do not rename since the files are hardlinked which
922 /* we either can not tell the files are hardlinked
923 (as with Windows servers) or files are not
924 hardlinked so delete the target manually before
925 renaming to follow POSIX rather than Windows
927 cifs_unlink(target_inode, target_direntry);
928 rc = CIFSSMBRename(xid, pTcon, fromName,
930 cifs_sb_source->local_nls,
931 cifs_sb_source->mnt_cifs_flags
932 & CIFS_MOUNT_MAP_SPECIAL_CHR);
934 kfree(info_buf_source);
935 } /* if we can not get memory just leave rc as EEXIST */
939 cFYI(1, ("rename rc %d", rc));
942 if ((rc == -EIO) || (rc == -EEXIST)) {
946 /* BB FIXME Is Generic Read correct for rename? */
947 /* if renaming directory - we should not say CREATE_NOT_DIR,
948 need to test renaming open directory, also GENERIC_READ
949 might not right be right access to request */
950 rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
951 CREATE_NOT_DIR, &netfid, &oplock, NULL,
952 cifs_sb_source->local_nls,
953 cifs_sb_source->mnt_cifs_flags &
954 CIFS_MOUNT_MAP_SPECIAL_CHR);
956 rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
957 cifs_sb_source->local_nls,
958 cifs_sb_source->mnt_cifs_flags &
959 CIFS_MOUNT_MAP_SPECIAL_CHR);
960 CIFSSMBClose(xid, pTcon, netfid);
971 int cifs_revalidate(struct dentry *direntry)
976 struct cifs_sb_info *cifs_sb;
977 struct cifsInodeInfo *cifsInode;
979 struct timespec local_mtime;
980 int invalidate_inode = FALSE;
982 if (direntry->d_inode == NULL)
985 cifsInode = CIFS_I(direntry->d_inode);
987 if (cifsInode == NULL)
990 /* no sense revalidating inode info on file that no one can write */
991 if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
996 cifs_sb = CIFS_SB(direntry->d_sb);
998 /* can not safely grab the rename sem here if rename calls revalidate
999 since that would deadlock */
1000 full_path = build_path_from_dentry(direntry);
1001 if (full_path == NULL) {
1005 cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
1006 "jiffies %ld", full_path, direntry->d_inode,
1007 direntry->d_inode->i_count.counter, direntry,
1008 direntry->d_time, jiffies));
1010 if (cifsInode->time == 0) {
1011 /* was set to zero previously to force revalidate */
1012 } else if (time_before(jiffies, cifsInode->time + HZ) &&
1013 lookupCacheEnabled) {
1014 if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
1015 (direntry->d_inode->i_nlink == 1)) {
1020 cFYI(1, ("Have to revalidate file due to hardlinks"));
1024 /* save mtime and size */
1025 local_mtime = direntry->d_inode->i_mtime;
1026 local_size = direntry->d_inode->i_size;
1028 if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
1029 rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
1030 direntry->d_sb,xid);
1032 cFYI(1, ("error on getting revalidate info %d", rc));
1033 /* if (rc != -ENOENT)
1034 rc = 0; */ /* BB should we cache info on
1038 rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
1039 direntry->d_sb,xid);
1041 cFYI(1, ("error on getting revalidate info %d", rc));
1042 /* if (rc != -ENOENT)
1043 rc = 0; */ /* BB should we cache info on
1047 /* should we remap certain errors, access denied?, to zero */
1049 /* if not oplocked, we invalidate inode pages if mtime or file size
1050 had changed on server */
1052 if (timespec_equal(&local_mtime,&direntry->d_inode->i_mtime) &&
1053 (local_size == direntry->d_inode->i_size)) {
1054 cFYI(1, ("cifs_revalidate - inode unchanged"));
1056 /* file may have changed on server */
1057 if (cifsInode->clientCanCacheRead) {
1058 /* no need to invalidate inode pages since we were the
1059 only ones who could have modified the file and the
1060 server copy is staler than ours */
1062 invalidate_inode = TRUE;
1066 /* can not grab this sem since kernel filesys locking documentation
1067 indicates i_mutex may be taken by the kernel on lookup and rename
1068 which could deadlock if we grab the i_mutex here as well */
1069 /* mutex_lock(&direntry->d_inode->i_mutex);*/
1070 /* need to write out dirty pages here */
1071 if (direntry->d_inode->i_mapping) {
1072 /* do we need to lock inode until after invalidate completes
1074 filemap_fdatawrite(direntry->d_inode->i_mapping);
1076 if (invalidate_inode) {
1077 /* shrink_dcache not necessary now that cifs dentry ops
1078 are exported for negative dentries */
1079 /* if(S_ISDIR(direntry->d_inode->i_mode))
1080 shrink_dcache_parent(direntry); */
1081 if (S_ISREG(direntry->d_inode->i_mode)) {
1082 if (direntry->d_inode->i_mapping)
1083 filemap_fdatawait(direntry->d_inode->i_mapping);
1084 /* may eventually have to do this for open files too */
1085 if (list_empty(&(cifsInode->openFileList))) {
1086 /* changed on server - flush read ahead pages */
1087 cFYI(1, ("Invalidating read ahead data on "
1089 invalidate_remote_inode(direntry->d_inode);
1093 /* mutex_unlock(&direntry->d_inode->i_mutex); */
1100 int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1103 int err = cifs_revalidate(dentry);
1105 generic_fillattr(dentry->d_inode, stat);
1106 stat->blksize = CIFS_MAX_MSGSIZE;
1111 static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1113 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1114 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1119 page = grab_cache_page(mapping, index);
1123 kaddr = kmap_atomic(page, KM_USER0);
1124 memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
1125 flush_dcache_page(page);
1126 kunmap_atomic(kaddr, KM_USER0);
1128 page_cache_release(page);
1132 int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1135 struct cifs_sb_info *cifs_sb;
1136 struct cifsTconInfo *pTcon;
1137 char *full_path = NULL;
1139 struct cifsFileInfo *open_file = NULL;
1140 FILE_BASIC_INFO time_buf;
1141 int set_time = FALSE;
1142 int set_dosattr = FALSE;
1143 __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
1144 __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
1145 __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
1146 struct cifsInodeInfo *cifsInode;
1150 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
1151 direntry->d_name.name, attrs->ia_valid));
1153 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
1154 pTcon = cifs_sb->tcon;
1156 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1157 /* check if we have permission to change attrs */
1158 rc = inode_change_ok(direntry->d_inode, attrs);
1166 full_path = build_path_from_dentry(direntry);
1167 if (full_path == NULL) {
1171 cifsInode = CIFS_I(direntry->d_inode);
1173 /* BB check if we need to refresh inode from server now ? BB */
1175 /* need to flush data before changing file size on server */
1176 filemap_write_and_wait(direntry->d_inode->i_mapping);
1178 if (attrs->ia_valid & ATTR_SIZE) {
1179 /* To avoid spurious oplock breaks from server, in the case of
1180 inodes that we already have open, avoid doing path based
1181 setting of file size if we can do it by handle.
1182 This keeps our caching token (oplock) and avoids timeouts
1183 when the local oplock break takes longer to flush
1184 writebehind data than the SMB timeout for the SetPathInfo
1185 request would allow */
1187 open_file = find_writable_file(cifsInode);
1189 __u16 nfid = open_file->netfid;
1190 __u32 npid = open_file->pid;
1191 rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
1193 atomic_dec(&open_file->wrtPending);
1194 cFYI(1,("SetFSize for attrs rc = %d", rc));
1195 if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1197 rc = CIFSSMBWrite(xid, pTcon,
1198 nfid, 0, attrs->ia_size,
1199 &bytes_written, NULL, NULL,
1200 1 /* 45 seconds */);
1201 cFYI(1,("Wrt seteof rc %d", rc));
1207 /* Set file size by pathname rather than by handle
1208 either because no valid, writeable file handle for
1209 it was found or because there was an error setting
1211 rc = CIFSSMBSetEOF(xid, pTcon, full_path,
1212 attrs->ia_size, FALSE,
1214 cifs_sb->mnt_cifs_flags &
1215 CIFS_MOUNT_MAP_SPECIAL_CHR);
1216 cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
1217 if((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1221 rc = SMBLegacyOpen(xid, pTcon, full_path,
1223 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1224 CREATE_NOT_DIR, &netfid, &oplock,
1225 NULL, cifs_sb->local_nls,
1226 cifs_sb->mnt_cifs_flags &
1227 CIFS_MOUNT_MAP_SPECIAL_CHR);
1230 rc = CIFSSMBWrite(xid, pTcon,
1233 &bytes_written, NULL,
1234 NULL, 1 /* 45 sec */);
1235 cFYI(1,("wrt seteof rc %d",rc));
1236 CIFSSMBClose(xid, pTcon, netfid);
1242 /* Server is ok setting allocation size implicitly - no need
1244 CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE,
1245 cifs_sb->local_nls);
1249 rc = vmtruncate(direntry->d_inode, attrs->ia_size);
1250 cifs_truncate_page(direntry->d_inode->i_mapping,
1251 direntry->d_inode->i_size);
1253 goto cifs_setattr_exit;
1255 if (attrs->ia_valid & ATTR_UID) {
1256 cFYI(1, ("UID changed to %d", attrs->ia_uid));
1257 uid = attrs->ia_uid;
1259 if (attrs->ia_valid & ATTR_GID) {
1260 cFYI(1, ("GID changed to %d", attrs->ia_gid));
1261 gid = attrs->ia_gid;
1264 time_buf.Attributes = 0;
1265 if (attrs->ia_valid & ATTR_MODE) {
1266 cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode));
1267 mode = attrs->ia_mode;
1270 if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX)
1271 && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
1272 rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
1273 0 /* dev_t */, cifs_sb->local_nls,
1274 cifs_sb->mnt_cifs_flags &
1275 CIFS_MOUNT_MAP_SPECIAL_CHR);
1276 else if (attrs->ia_valid & ATTR_MODE) {
1278 if ((mode & S_IWUGO) == 0) /* not writeable */ {
1279 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
1281 time_buf.Attributes =
1282 cpu_to_le32(cifsInode->cifsAttrs |
1285 } else if ((mode & S_IWUGO) == S_IWUGO) {
1286 if (cifsInode->cifsAttrs & ATTR_READONLY) {
1288 time_buf.Attributes =
1289 cpu_to_le32(cifsInode->cifsAttrs &
1291 /* Windows ignores set to zero */
1292 if(time_buf.Attributes == 0)
1293 time_buf.Attributes |=
1294 cpu_to_le32(ATTR_NORMAL);
1297 /* BB to be implemented -
1298 via Windows security descriptors or streams */
1299 /* CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, uid, gid,
1300 cifs_sb->local_nls); */
1303 if (attrs->ia_valid & ATTR_ATIME) {
1305 time_buf.LastAccessTime =
1306 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1308 time_buf.LastAccessTime = 0;
1310 if (attrs->ia_valid & ATTR_MTIME) {
1312 time_buf.LastWriteTime =
1313 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1315 time_buf.LastWriteTime = 0;
1316 /* Do not set ctime explicitly unless other time
1317 stamps are changed explicitly (i.e. by utime()
1318 since we would then have a mix of client and
1321 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
1323 /* Although Samba throws this field away
1324 it may be useful to Windows - but we do
1325 not want to set ctime unless some other
1326 timestamp is changing */
1327 cFYI(1, ("CIFS - CTIME changed"));
1328 time_buf.ChangeTime =
1329 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1331 time_buf.ChangeTime = 0;
1333 if (set_time || set_dosattr) {
1334 time_buf.CreationTime = 0; /* do not change */
1335 /* In the future we should experiment - try setting timestamps
1336 via Handle (SetFileInfo) instead of by path */
1337 if (!(pTcon->ses->flags & CIFS_SES_NT4))
1338 rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
1340 cifs_sb->mnt_cifs_flags &
1341 CIFS_MOUNT_MAP_SPECIAL_CHR);
1345 if (rc == -EOPNOTSUPP) {
1349 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
1350 "times not supported by this server"));
1351 /* BB we could scan to see if we already have it open
1352 and pass in pid of opener to function */
1353 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1354 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1355 CREATE_NOT_DIR, &netfid, &oplock,
1356 NULL, cifs_sb->local_nls,
1357 cifs_sb->mnt_cifs_flags &
1358 CIFS_MOUNT_MAP_SPECIAL_CHR);
1360 rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
1362 CIFSSMBClose(xid, pTcon, netfid);
1364 /* BB For even older servers we could convert time_buf
1365 into old DOS style which uses two second
1368 /* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
1369 &time_buf, cifs_sb->local_nls); */
1372 /* Even if error on time set, no sense failing the call if
1373 the server would set the time to a reasonable value anyway,
1374 and this check ensures that we are not being called from
1375 sys_utimes in which case we ought to fail the call back to
1376 the user when the server rejects the call */
1377 if((rc) && (attrs->ia_valid &&
1378 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
1382 /* do not need local check to inode_check_ok since the server does
1385 rc = inode_setattr(direntry->d_inode, attrs);
1392 void cifs_delete_inode(struct inode *inode)
1394 cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
1395 /* may have to add back in if and when safe distributed caching of
1396 directories added e.g. via FindNotify */