diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 282 |
1 files changed, 246 insertions, 36 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index f414526e476a..3e87dad3367c 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * fs/cifs/inode.c | 2 | * fs/cifs/inode.c |
3 | * | 3 | * |
4 | * Copyright (C) International Business Machines Corp., 2002,2005 | 4 | * Copyright (C) International Business Machines Corp., 2002,2007 |
5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
6 | * | 6 | * |
7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
@@ -90,7 +90,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
90 | (*pinode)->i_ino = | 90 | (*pinode)->i_ino = |
91 | (unsigned long)findData.UniqueId; | 91 | (unsigned long)findData.UniqueId; |
92 | } /* note ino incremented to unique num in new_inode */ | 92 | } /* note ino incremented to unique num in new_inode */ |
93 | if(sb->s_flags & MS_NOATIME) | 93 | if (sb->s_flags & MS_NOATIME) |
94 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; | 94 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; |
95 | 95 | ||
96 | insert_inode_hash(*pinode); | 96 | insert_inode_hash(*pinode); |
@@ -139,8 +139,17 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
139 | inode->i_mode |= S_IFREG; | 139 | inode->i_mode |= S_IFREG; |
140 | cFYI(1,("unknown type %d",type)); | 140 | cFYI(1,("unknown type %d",type)); |
141 | } | 141 | } |
142 | inode->i_uid = le64_to_cpu(findData.Uid); | 142 | |
143 | inode->i_gid = le64_to_cpu(findData.Gid); | 143 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) |
144 | inode->i_uid = cifs_sb->mnt_uid; | ||
145 | else | ||
146 | inode->i_uid = le64_to_cpu(findData.Uid); | ||
147 | |||
148 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) | ||
149 | inode->i_gid = cifs_sb->mnt_gid; | ||
150 | else | ||
151 | inode->i_gid = le64_to_cpu(findData.Gid); | ||
152 | |||
144 | inode->i_nlink = le64_to_cpu(findData.Nlinks); | 153 | inode->i_nlink = le64_to_cpu(findData.Nlinks); |
145 | 154 | ||
146 | spin_lock(&inode->i_lock); | 155 | spin_lock(&inode->i_lock); |
@@ -178,13 +187,13 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
178 | &cifs_file_direct_nobrl_ops; | 187 | &cifs_file_direct_nobrl_ops; |
179 | else | 188 | else |
180 | inode->i_fop = &cifs_file_direct_ops; | 189 | inode->i_fop = &cifs_file_direct_ops; |
181 | } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | 190 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) |
182 | inode->i_fop = &cifs_file_nobrl_ops; | 191 | inode->i_fop = &cifs_file_nobrl_ops; |
183 | else /* not direct, send byte range locks */ | 192 | else /* not direct, send byte range locks */ |
184 | inode->i_fop = &cifs_file_ops; | 193 | inode->i_fop = &cifs_file_ops; |
185 | 194 | ||
186 | /* check if server can support readpages */ | 195 | /* check if server can support readpages */ |
187 | if(pTcon->ses->server->maxBuf < | 196 | if (pTcon->ses->server->maxBuf < |
188 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) | 197 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) |
189 | inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | 198 | inode->i_data.a_ops = &cifs_addr_ops_smallbuf; |
190 | else | 199 | else |
@@ -220,7 +229,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size, | |||
220 | 229 | ||
221 | pbuf = buf; | 230 | pbuf = buf; |
222 | 231 | ||
223 | if(size == 0) { | 232 | if (size == 0) { |
224 | inode->i_mode |= S_IFIFO; | 233 | inode->i_mode |= S_IFIFO; |
225 | return 0; | 234 | return 0; |
226 | } else if (size < 8) { | 235 | } else if (size < 8) { |
@@ -239,11 +248,11 @@ static int decode_sfu_inode(struct inode * inode, __u64 size, | |||
239 | netfid, | 248 | netfid, |
240 | 24 /* length */, 0 /* offset */, | 249 | 24 /* length */, 0 /* offset */, |
241 | &bytes_read, &pbuf, &buf_type); | 250 | &bytes_read, &pbuf, &buf_type); |
242 | if((rc == 0) && (bytes_read >= 8)) { | 251 | if ((rc == 0) && (bytes_read >= 8)) { |
243 | if(memcmp("IntxBLK", pbuf, 8) == 0) { | 252 | if (memcmp("IntxBLK", pbuf, 8) == 0) { |
244 | cFYI(1,("Block device")); | 253 | cFYI(1,("Block device")); |
245 | inode->i_mode |= S_IFBLK; | 254 | inode->i_mode |= S_IFBLK; |
246 | if(bytes_read == 24) { | 255 | if (bytes_read == 24) { |
247 | /* we have enough to decode dev num */ | 256 | /* we have enough to decode dev num */ |
248 | __u64 mjr; /* major */ | 257 | __u64 mjr; /* major */ |
249 | __u64 mnr; /* minor */ | 258 | __u64 mnr; /* minor */ |
@@ -251,10 +260,10 @@ static int decode_sfu_inode(struct inode * inode, __u64 size, | |||
251 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 260 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
252 | inode->i_rdev = MKDEV(mjr, mnr); | 261 | inode->i_rdev = MKDEV(mjr, mnr); |
253 | } | 262 | } |
254 | } else if(memcmp("IntxCHR", pbuf, 8) == 0) { | 263 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { |
255 | cFYI(1,("Char device")); | 264 | cFYI(1,("Char device")); |
256 | inode->i_mode |= S_IFCHR; | 265 | inode->i_mode |= S_IFCHR; |
257 | if(bytes_read == 24) { | 266 | if (bytes_read == 24) { |
258 | /* we have enough to decode dev num */ | 267 | /* we have enough to decode dev num */ |
259 | __u64 mjr; /* major */ | 268 | __u64 mjr; /* major */ |
260 | __u64 mnr; /* minor */ | 269 | __u64 mnr; /* minor */ |
@@ -262,7 +271,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size, | |||
262 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); | 271 | mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); |
263 | inode->i_rdev = MKDEV(mjr, mnr); | 272 | inode->i_rdev = MKDEV(mjr, mnr); |
264 | } | 273 | } |
265 | } else if(memcmp("IntxLNK", pbuf, 7) == 0) { | 274 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { |
266 | cFYI(1,("Symlink")); | 275 | cFYI(1,("Symlink")); |
267 | inode->i_mode |= S_IFLNK; | 276 | inode->i_mode |= S_IFLNK; |
268 | } else { | 277 | } else { |
@@ -293,7 +302,7 @@ static int get_sfu_uid_mode(struct inode * inode, | |||
293 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", | 302 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", |
294 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | 303 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, |
295 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 304 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
296 | if(rc < 0) | 305 | if (rc < 0) |
297 | return (int)rc; | 306 | return (int)rc; |
298 | else if (rc > 3) { | 307 | else if (rc > 3) { |
299 | mode = le32_to_cpu(*((__le32 *)ea_value)); | 308 | mode = le32_to_cpu(*((__le32 *)ea_value)); |
@@ -348,7 +357,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
348 | /* BB optimize code so we do not make the above call | 357 | /* BB optimize code so we do not make the above call |
349 | when server claims no NT SMB support and the above call | 358 | when server claims no NT SMB support and the above call |
350 | failed at least once - set flag in tcon or mount */ | 359 | failed at least once - set flag in tcon or mount */ |
351 | if((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { | 360 | if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { |
352 | rc = SMBQueryInformation(xid, pTcon, search_path, | 361 | rc = SMBQueryInformation(xid, pTcon, search_path, |
353 | pfindData, cifs_sb->local_nls, | 362 | pfindData, cifs_sb->local_nls, |
354 | cifs_sb->mnt_cifs_flags & | 363 | cifs_sb->mnt_cifs_flags & |
@@ -425,7 +434,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
425 | } else /* do we need cast or hash to ino? */ | 434 | } else /* do we need cast or hash to ino? */ |
426 | (*pinode)->i_ino = inode_num; | 435 | (*pinode)->i_ino = inode_num; |
427 | } /* else ino incremented to unique num in new_inode*/ | 436 | } /* else ino incremented to unique num in new_inode*/ |
428 | if(sb->s_flags & MS_NOATIME) | 437 | if (sb->s_flags & MS_NOATIME) |
429 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; | 438 | (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME; |
430 | insert_inode_hash(*pinode); | 439 | insert_inode_hash(*pinode); |
431 | } | 440 | } |
@@ -442,7 +451,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
442 | (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ | 451 | (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/ |
443 | 452 | ||
444 | /* Linux can not store file creation time so ignore it */ | 453 | /* Linux can not store file creation time so ignore it */ |
445 | if(pfindData->LastAccessTime) | 454 | if (pfindData->LastAccessTime) |
446 | inode->i_atime = cifs_NTtimeToUnix | 455 | inode->i_atime = cifs_NTtimeToUnix |
447 | (le64_to_cpu(pfindData->LastAccessTime)); | 456 | (le64_to_cpu(pfindData->LastAccessTime)); |
448 | else /* do not need to use current_fs_time - time not stored */ | 457 | else /* do not need to use current_fs_time - time not stored */ |
@@ -452,7 +461,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
452 | inode->i_ctime = | 461 | inode->i_ctime = |
453 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); | 462 | cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); |
454 | cFYI(0, ("Attributes came in as 0x%x", attr)); | 463 | cFYI(0, ("Attributes came in as 0x%x", attr)); |
455 | if(adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { | 464 | if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) { |
456 | inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; | 465 | inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj; |
457 | inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; | 466 | inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; |
458 | } | 467 | } |
@@ -521,8 +530,10 @@ int cifs_get_inode_info(struct inode **pinode, | |||
521 | 530 | ||
522 | /* BB fill in uid and gid here? with help from winbind? | 531 | /* BB fill in uid and gid here? with help from winbind? |
523 | or retrieve from NTFS stream extended attribute */ | 532 | or retrieve from NTFS stream extended attribute */ |
524 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | 533 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
525 | /* fill in uid, gid, mode from server ACL */ | 534 | /* fill in uid, gid, mode from server ACL */ |
535 | /* BB FIXME this should also take into account the | ||
536 | * default uid specified on mount if present */ | ||
526 | get_sfu_uid_mode(inode, search_path, cifs_sb, xid); | 537 | get_sfu_uid_mode(inode, search_path, cifs_sb, xid); |
527 | } else if (atomic_read(&cifsInfo->inUse) == 0) { | 538 | } else if (atomic_read(&cifsInfo->inUse) == 0) { |
528 | inode->i_uid = cifs_sb->mnt_uid; | 539 | inode->i_uid = cifs_sb->mnt_uid; |
@@ -541,12 +552,12 @@ int cifs_get_inode_info(struct inode **pinode, | |||
541 | &cifs_file_direct_nobrl_ops; | 552 | &cifs_file_direct_nobrl_ops; |
542 | else | 553 | else |
543 | inode->i_fop = &cifs_file_direct_ops; | 554 | inode->i_fop = &cifs_file_direct_ops; |
544 | } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | 555 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) |
545 | inode->i_fop = &cifs_file_nobrl_ops; | 556 | inode->i_fop = &cifs_file_nobrl_ops; |
546 | else /* not direct, send byte range locks */ | 557 | else /* not direct, send byte range locks */ |
547 | inode->i_fop = &cifs_file_ops; | 558 | inode->i_fop = &cifs_file_ops; |
548 | 559 | ||
549 | if(pTcon->ses->server->maxBuf < | 560 | if (pTcon->ses->server->maxBuf < |
550 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) | 561 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) |
551 | inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | 562 | inode->i_data.a_ops = &cifs_addr_ops_smallbuf; |
552 | else | 563 | else |
@@ -597,7 +608,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
597 | 608 | ||
598 | xid = GetXid(); | 609 | xid = GetXid(); |
599 | 610 | ||
600 | if(inode) | 611 | if (inode) |
601 | cifs_sb = CIFS_SB(inode->i_sb); | 612 | cifs_sb = CIFS_SB(inode->i_sb); |
602 | else | 613 | else |
603 | cifs_sb = CIFS_SB(direntry->d_sb); | 614 | cifs_sb = CIFS_SB(direntry->d_sb); |
@@ -723,7 +734,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
723 | when needed */ | 734 | when needed */ |
724 | direntry->d_inode->i_ctime = current_fs_time(inode->i_sb); | 735 | direntry->d_inode->i_ctime = current_fs_time(inode->i_sb); |
725 | } | 736 | } |
726 | if(inode) { | 737 | if (inode) { |
727 | inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); | 738 | inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); |
728 | cifsInode = CIFS_I(inode); | 739 | cifsInode = CIFS_I(inode); |
729 | cifsInode->time = 0; /* force revalidate of dir as well */ | 740 | cifsInode->time = 0; /* force revalidate of dir as well */ |
@@ -734,6 +745,136 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) | |||
734 | return rc; | 745 | return rc; |
735 | } | 746 | } |
736 | 747 | ||
748 | static void posix_fill_in_inode(struct inode *tmp_inode, | ||
749 | FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode) | ||
750 | { | ||
751 | loff_t local_size; | ||
752 | struct timespec local_mtime; | ||
753 | |||
754 | struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); | ||
755 | struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); | ||
756 | |||
757 | __u32 type = le32_to_cpu(pData->Type); | ||
758 | __u64 num_of_bytes = le64_to_cpu(pData->NumOfBytes); | ||
759 | __u64 end_of_file = le64_to_cpu(pData->EndOfFile); | ||
760 | cifsInfo->time = jiffies; | ||
761 | atomic_inc(&cifsInfo->inUse); | ||
762 | |||
763 | /* save mtime and size */ | ||
764 | local_mtime = tmp_inode->i_mtime; | ||
765 | local_size = tmp_inode->i_size; | ||
766 | |||
767 | tmp_inode->i_atime = | ||
768 | cifs_NTtimeToUnix(le64_to_cpu(pData->LastAccessTime)); | ||
769 | tmp_inode->i_mtime = | ||
770 | cifs_NTtimeToUnix(le64_to_cpu(pData->LastModificationTime)); | ||
771 | tmp_inode->i_ctime = | ||
772 | cifs_NTtimeToUnix(le64_to_cpu(pData->LastStatusChange)); | ||
773 | |||
774 | tmp_inode->i_mode = le64_to_cpu(pData->Permissions); | ||
775 | /* since we set the inode type below we need to mask off type | ||
776 | to avoid strange results if bits above were corrupt */ | ||
777 | tmp_inode->i_mode &= ~S_IFMT; | ||
778 | if (type == UNIX_FILE) { | ||
779 | *pobject_type = DT_REG; | ||
780 | tmp_inode->i_mode |= S_IFREG; | ||
781 | } else if (type == UNIX_SYMLINK) { | ||
782 | *pobject_type = DT_LNK; | ||
783 | tmp_inode->i_mode |= S_IFLNK; | ||
784 | } else if (type == UNIX_DIR) { | ||
785 | *pobject_type = DT_DIR; | ||
786 | tmp_inode->i_mode |= S_IFDIR; | ||
787 | } else if (type == UNIX_CHARDEV) { | ||
788 | *pobject_type = DT_CHR; | ||
789 | tmp_inode->i_mode |= S_IFCHR; | ||
790 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor), | ||
791 | le64_to_cpu(pData->DevMinor) & MINORMASK); | ||
792 | } else if (type == UNIX_BLOCKDEV) { | ||
793 | *pobject_type = DT_BLK; | ||
794 | tmp_inode->i_mode |= S_IFBLK; | ||
795 | tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor), | ||
796 | le64_to_cpu(pData->DevMinor) & MINORMASK); | ||
797 | } else if (type == UNIX_FIFO) { | ||
798 | *pobject_type = DT_FIFO; | ||
799 | tmp_inode->i_mode |= S_IFIFO; | ||
800 | } else if (type == UNIX_SOCKET) { | ||
801 | *pobject_type = DT_SOCK; | ||
802 | tmp_inode->i_mode |= S_IFSOCK; | ||
803 | } else { | ||
804 | /* safest to just call it a file */ | ||
805 | *pobject_type = DT_REG; | ||
806 | tmp_inode->i_mode |= S_IFREG; | ||
807 | cFYI(1,("unknown inode type %d",type)); | ||
808 | } | ||
809 | |||
810 | #ifdef CONFIG_CIFS_DEBUG2 | ||
811 | cFYI(1,("object type: %d", type)); | ||
812 | #endif | ||
813 | tmp_inode->i_uid = le64_to_cpu(pData->Uid); | ||
814 | tmp_inode->i_gid = le64_to_cpu(pData->Gid); | ||
815 | tmp_inode->i_nlink = le64_to_cpu(pData->Nlinks); | ||
816 | |||
817 | spin_lock(&tmp_inode->i_lock); | ||
818 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | ||
819 | /* can not safely change the file size here if the | ||
820 | client is writing to it due to potential races */ | ||
821 | i_size_write(tmp_inode, end_of_file); | ||
822 | |||
823 | /* 512 bytes (2**9) is the fake blocksize that must be used */ | ||
824 | /* for this calculation, not the real blocksize */ | ||
825 | tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | ||
826 | } | ||
827 | spin_unlock(&tmp_inode->i_lock); | ||
828 | |||
829 | if (S_ISREG(tmp_inode->i_mode)) { | ||
830 | cFYI(1, ("File inode")); | ||
831 | tmp_inode->i_op = &cifs_file_inode_ops; | ||
832 | |||
833 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { | ||
834 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
835 | tmp_inode->i_fop = &cifs_file_direct_nobrl_ops; | ||
836 | else | ||
837 | tmp_inode->i_fop = &cifs_file_direct_ops; | ||
838 | |||
839 | } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
840 | tmp_inode->i_fop = &cifs_file_nobrl_ops; | ||
841 | else | ||
842 | tmp_inode->i_fop = &cifs_file_ops; | ||
843 | |||
844 | if((cifs_sb->tcon) && (cifs_sb->tcon->ses) && | ||
845 | (cifs_sb->tcon->ses->server->maxBuf < | ||
846 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)) | ||
847 | tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf; | ||
848 | else | ||
849 | tmp_inode->i_data.a_ops = &cifs_addr_ops; | ||
850 | |||
851 | if(isNewInode) | ||
852 | return; /* No sense invalidating pages for new inode since we | ||
853 | have not started caching readahead file data yet */ | ||
854 | |||
855 | if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && | ||
856 | (local_size == tmp_inode->i_size)) { | ||
857 | cFYI(1, ("inode exists but unchanged")); | ||
858 | } else { | ||
859 | /* file may have changed on server */ | ||
860 | cFYI(1, ("invalidate inode, readdir detected change")); | ||
861 | invalidate_remote_inode(tmp_inode); | ||
862 | } | ||
863 | } else if (S_ISDIR(tmp_inode->i_mode)) { | ||
864 | cFYI(1, ("Directory inode")); | ||
865 | tmp_inode->i_op = &cifs_dir_inode_ops; | ||
866 | tmp_inode->i_fop = &cifs_dir_ops; | ||
867 | } else if (S_ISLNK(tmp_inode->i_mode)) { | ||
868 | cFYI(1, ("Symbolic Link inode")); | ||
869 | tmp_inode->i_op = &cifs_symlink_inode_ops; | ||
870 | /* tmp_inode->i_fop = *//* do not need to set to anything */ | ||
871 | } else { | ||
872 | cFYI(1, ("Special inode")); | ||
873 | init_special_inode(tmp_inode, tmp_inode->i_mode, | ||
874 | tmp_inode->i_rdev); | ||
875 | } | ||
876 | } | ||
877 | |||
737 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | 878 | int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) |
738 | { | 879 | { |
739 | int rc = 0; | 880 | int rc = 0; |
@@ -755,6 +896,71 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
755 | FreeXid(xid); | 896 | FreeXid(xid); |
756 | return -ENOMEM; | 897 | return -ENOMEM; |
757 | } | 898 | } |
899 | |||
900 | if((pTcon->ses->capabilities & CAP_UNIX) && | ||
901 | (CIFS_UNIX_POSIX_PATH_OPS_CAP & | ||
902 | le64_to_cpu(pTcon->fsUnixInfo.Capability))) { | ||
903 | u32 oplock = 0; | ||
904 | FILE_UNIX_BASIC_INFO * pInfo = | ||
905 | kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); | ||
906 | if(pInfo == NULL) { | ||
907 | rc = -ENOMEM; | ||
908 | goto mkdir_out; | ||
909 | } | ||
910 | |||
911 | rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, | ||
912 | mode, NULL /* netfid */, pInfo, &oplock, | ||
913 | full_path, cifs_sb->local_nls, | ||
914 | cifs_sb->mnt_cifs_flags & | ||
915 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
916 | if (rc) { | ||
917 | cFYI(1, ("posix mkdir returned 0x%x", rc)); | ||
918 | d_drop(direntry); | ||
919 | } else { | ||
920 | int obj_type; | ||
921 | if (pInfo->Type == -1) /* no return info - go query */ | ||
922 | goto mkdir_get_info; | ||
923 | /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need to set uid/gid */ | ||
924 | inc_nlink(inode); | ||
925 | if (pTcon->nocase) | ||
926 | direntry->d_op = &cifs_ci_dentry_ops; | ||
927 | else | ||
928 | direntry->d_op = &cifs_dentry_ops; | ||
929 | |||
930 | newinode = new_inode(inode->i_sb); | ||
931 | if (newinode == NULL) | ||
932 | goto mkdir_get_info; | ||
933 | /* Is an i_ino of zero legal? */ | ||
934 | /* Are there sanity checks we can use to ensure that | ||
935 | the server is really filling in that field? */ | ||
936 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { | ||
937 | newinode->i_ino = | ||
938 | (unsigned long)pInfo->UniqueId; | ||
939 | } /* note ino incremented to unique num in new_inode */ | ||
940 | if(inode->i_sb->s_flags & MS_NOATIME) | ||
941 | newinode->i_flags |= S_NOATIME | S_NOCMTIME; | ||
942 | newinode->i_nlink = 2; | ||
943 | |||
944 | insert_inode_hash(newinode); | ||
945 | d_instantiate(direntry, newinode); | ||
946 | |||
947 | /* we already checked in POSIXCreate whether | ||
948 | frame was long enough */ | ||
949 | posix_fill_in_inode(direntry->d_inode, | ||
950 | pInfo, &obj_type, 1 /* NewInode */); | ||
951 | #ifdef CONFIG_CIFS_DEBUG2 | ||
952 | cFYI(1,("instantiated dentry %p %s to inode %p", | ||
953 | direntry, direntry->d_name.name, newinode)); | ||
954 | |||
955 | if(newinode->i_nlink != 2) | ||
956 | cFYI(1,("unexpected number of links %d", | ||
957 | newinode->i_nlink)); | ||
958 | #endif | ||
959 | } | ||
960 | kfree(pInfo); | ||
961 | goto mkdir_out; | ||
962 | } | ||
963 | |||
758 | /* BB add setting the equivalent of mode via CreateX w/ACLs */ | 964 | /* BB add setting the equivalent of mode via CreateX w/ACLs */ |
759 | rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, | 965 | rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, |
760 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 966 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
@@ -762,6 +968,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
762 | cFYI(1, ("cifs_mkdir returned 0x%x", rc)); | 968 | cFYI(1, ("cifs_mkdir returned 0x%x", rc)); |
763 | d_drop(direntry); | 969 | d_drop(direntry); |
764 | } else { | 970 | } else { |
971 | mkdir_get_info: | ||
765 | inc_nlink(inode); | 972 | inc_nlink(inode); |
766 | if (pTcon->ses->capabilities & CAP_UNIX) | 973 | if (pTcon->ses->capabilities & CAP_UNIX) |
767 | rc = cifs_get_inode_info_unix(&newinode, full_path, | 974 | rc = cifs_get_inode_info_unix(&newinode, full_path, |
@@ -775,8 +982,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
775 | else | 982 | else |
776 | direntry->d_op = &cifs_dentry_ops; | 983 | direntry->d_op = &cifs_dentry_ops; |
777 | d_instantiate(direntry, newinode); | 984 | d_instantiate(direntry, newinode); |
778 | if (direntry->d_inode) | 985 | /* setting nlink not necessary except in cases where we |
779 | direntry->d_inode->i_nlink = 2; | 986 | * failed to get it from the server or was set bogus */ |
987 | if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) | ||
988 | direntry->d_inode->i_nlink = 2; | ||
780 | if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) | 989 | if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) |
781 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { | 990 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { |
782 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, | 991 | CIFSSMBUnixSetPerms(xid, pTcon, full_path, |
@@ -812,6 +1021,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
812 | } | 1021 | } |
813 | } | 1022 | } |
814 | } | 1023 | } |
1024 | mkdir_out: | ||
815 | kfree(full_path); | 1025 | kfree(full_path); |
816 | FreeXid(xid); | 1026 | FreeXid(xid); |
817 | return rc; | 1027 | return rc; |
@@ -1339,17 +1549,17 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1339 | cpu_to_le32(cifsInode->cifsAttrs | | 1549 | cpu_to_le32(cifsInode->cifsAttrs | |
1340 | ATTR_READONLY); | 1550 | ATTR_READONLY); |
1341 | } | 1551 | } |
1342 | } else if ((mode & S_IWUGO) == S_IWUGO) { | 1552 | } else if (cifsInode->cifsAttrs & ATTR_READONLY) { |
1343 | if (cifsInode->cifsAttrs & ATTR_READONLY) { | 1553 | /* If file is readonly on server, we would |
1344 | set_dosattr = TRUE; | 1554 | not be able to write to it - so if any write |
1345 | time_buf.Attributes = | 1555 | bit is enabled for user or group or other we |
1346 | cpu_to_le32(cifsInode->cifsAttrs & | 1556 | need to at least try to remove r/o dos attr */ |
1347 | (~ATTR_READONLY)); | 1557 | set_dosattr = TRUE; |
1348 | /* Windows ignores set to zero */ | 1558 | time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs & |
1349 | if(time_buf.Attributes == 0) | 1559 | (~ATTR_READONLY)); |
1350 | time_buf.Attributes |= | 1560 | /* Windows ignores set to zero */ |
1351 | cpu_to_le32(ATTR_NORMAL); | 1561 | if(time_buf.Attributes == 0) |
1352 | } | 1562 | time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); |
1353 | } | 1563 | } |
1354 | /* BB to be implemented - | 1564 | /* BB to be implemented - |
1355 | via Windows security descriptors or streams */ | 1565 | via Windows security descriptors or streams */ |