diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 273 |
1 files changed, 174 insertions, 99 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 35ec11716213..4bc47e5b5f29 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,2008 | 4 | * Copyright (C) International Business Machines Corp., 2002,2010 |
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 |
@@ -29,6 +29,7 @@ | |||
29 | #include "cifsproto.h" | 29 | #include "cifsproto.h" |
30 | #include "cifs_debug.h" | 30 | #include "cifs_debug.h" |
31 | #include "cifs_fs_sb.h" | 31 | #include "cifs_fs_sb.h" |
32 | #include "fscache.h" | ||
32 | 33 | ||
33 | 34 | ||
34 | static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | 35 | static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) |
@@ -86,30 +87,30 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr) | |||
86 | { | 87 | { |
87 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | 88 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); |
88 | 89 | ||
89 | cFYI(1, ("%s: revalidating inode %llu", __func__, cifs_i->uniqueid)); | 90 | cFYI(1, "%s: revalidating inode %llu", __func__, cifs_i->uniqueid); |
90 | 91 | ||
91 | if (inode->i_state & I_NEW) { | 92 | if (inode->i_state & I_NEW) { |
92 | cFYI(1, ("%s: inode %llu is new", __func__, cifs_i->uniqueid)); | 93 | cFYI(1, "%s: inode %llu is new", __func__, cifs_i->uniqueid); |
93 | return; | 94 | return; |
94 | } | 95 | } |
95 | 96 | ||
96 | /* don't bother with revalidation if we have an oplock */ | 97 | /* don't bother with revalidation if we have an oplock */ |
97 | if (cifs_i->clientCanCacheRead) { | 98 | if (cifs_i->clientCanCacheRead) { |
98 | cFYI(1, ("%s: inode %llu is oplocked", __func__, | 99 | cFYI(1, "%s: inode %llu is oplocked", __func__, |
99 | cifs_i->uniqueid)); | 100 | cifs_i->uniqueid); |
100 | return; | 101 | return; |
101 | } | 102 | } |
102 | 103 | ||
103 | /* revalidate if mtime or size have changed */ | 104 | /* revalidate if mtime or size have changed */ |
104 | if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) && | 105 | if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) && |
105 | cifs_i->server_eof == fattr->cf_eof) { | 106 | cifs_i->server_eof == fattr->cf_eof) { |
106 | cFYI(1, ("%s: inode %llu is unchanged", __func__, | 107 | cFYI(1, "%s: inode %llu is unchanged", __func__, |
107 | cifs_i->uniqueid)); | 108 | cifs_i->uniqueid); |
108 | return; | 109 | return; |
109 | } | 110 | } |
110 | 111 | ||
111 | cFYI(1, ("%s: invalidating inode %llu mapping", __func__, | 112 | cFYI(1, "%s: invalidating inode %llu mapping", __func__, |
112 | cifs_i->uniqueid)); | 113 | cifs_i->uniqueid); |
113 | cifs_i->invalid_mapping = true; | 114 | cifs_i->invalid_mapping = true; |
114 | } | 115 | } |
115 | 116 | ||
@@ -137,15 +138,14 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |||
137 | inode->i_mode = fattr->cf_mode; | 138 | inode->i_mode = fattr->cf_mode; |
138 | 139 | ||
139 | cifs_i->cifsAttrs = fattr->cf_cifsattrs; | 140 | cifs_i->cifsAttrs = fattr->cf_cifsattrs; |
140 | cifs_i->uniqueid = fattr->cf_uniqueid; | ||
141 | 141 | ||
142 | if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) | 142 | if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) |
143 | cifs_i->time = 0; | 143 | cifs_i->time = 0; |
144 | else | 144 | else |
145 | cifs_i->time = jiffies; | 145 | cifs_i->time = jiffies; |
146 | 146 | ||
147 | cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, | 147 | cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode, |
148 | oldtime, cifs_i->time)); | 148 | oldtime, cifs_i->time); |
149 | 149 | ||
150 | cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; | 150 | cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; |
151 | 151 | ||
@@ -170,6 +170,17 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |||
170 | cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL); | 170 | cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL); |
171 | } | 171 | } |
172 | 172 | ||
173 | void | ||
174 | cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr) | ||
175 | { | ||
176 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | ||
177 | |||
178 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) | ||
179 | return; | ||
180 | |||
181 | fattr->cf_uniqueid = iunique(sb, ROOT_I); | ||
182 | } | ||
183 | |||
173 | /* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */ | 184 | /* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */ |
174 | void | 185 | void |
175 | cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, | 186 | cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, |
@@ -227,7 +238,7 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, | |||
227 | /* safest to call it a file if we do not know */ | 238 | /* safest to call it a file if we do not know */ |
228 | fattr->cf_mode |= S_IFREG; | 239 | fattr->cf_mode |= S_IFREG; |
229 | fattr->cf_dtype = DT_REG; | 240 | fattr->cf_dtype = DT_REG; |
230 | cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); | 241 | cFYI(1, "unknown type %d", le32_to_cpu(info->Type)); |
231 | break; | 242 | break; |
232 | } | 243 | } |
233 | 244 | ||
@@ -256,7 +267,7 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) | |||
256 | { | 267 | { |
257 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 268 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
258 | 269 | ||
259 | cFYI(1, ("creating fake fattr for DFS referral")); | 270 | cFYI(1, "creating fake fattr for DFS referral"); |
260 | 271 | ||
261 | memset(fattr, 0, sizeof(*fattr)); | 272 | memset(fattr, 0, sizeof(*fattr)); |
262 | fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; | 273 | fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; |
@@ -278,7 +289,7 @@ int cifs_get_file_info_unix(struct file *filp) | |||
278 | struct inode *inode = filp->f_path.dentry->d_inode; | 289 | struct inode *inode = filp->f_path.dentry->d_inode; |
279 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 290 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
280 | struct cifsTconInfo *tcon = cifs_sb->tcon; | 291 | struct cifsTconInfo *tcon = cifs_sb->tcon; |
281 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; | 292 | struct cifsFileInfo *cfile = filp->private_data; |
282 | 293 | ||
283 | xid = GetXid(); | 294 | xid = GetXid(); |
284 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); | 295 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); |
@@ -305,7 +316,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
305 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 316 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
306 | 317 | ||
307 | tcon = cifs_sb->tcon; | 318 | tcon = cifs_sb->tcon; |
308 | cFYI(1, ("Getting info on %s", full_path)); | 319 | cFYI(1, "Getting info on %s", full_path); |
309 | 320 | ||
310 | /* could have done a find first instead but this returns more info */ | 321 | /* could have done a find first instead but this returns more info */ |
311 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, | 322 | rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, |
@@ -323,6 +334,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
323 | 334 | ||
324 | if (*pinode == NULL) { | 335 | if (*pinode == NULL) { |
325 | /* get new inode */ | 336 | /* get new inode */ |
337 | cifs_fill_uniqueid(sb, &fattr); | ||
326 | *pinode = cifs_iget(sb, &fattr); | 338 | *pinode = cifs_iget(sb, &fattr); |
327 | if (!*pinode) | 339 | if (!*pinode) |
328 | rc = -ENOMEM; | 340 | rc = -ENOMEM; |
@@ -373,7 +385,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
373 | &bytes_read, &pbuf, &buf_type); | 385 | &bytes_read, &pbuf, &buf_type); |
374 | if ((rc == 0) && (bytes_read >= 8)) { | 386 | if ((rc == 0) && (bytes_read >= 8)) { |
375 | if (memcmp("IntxBLK", pbuf, 8) == 0) { | 387 | if (memcmp("IntxBLK", pbuf, 8) == 0) { |
376 | cFYI(1, ("Block device")); | 388 | cFYI(1, "Block device"); |
377 | fattr->cf_mode |= S_IFBLK; | 389 | fattr->cf_mode |= S_IFBLK; |
378 | fattr->cf_dtype = DT_BLK; | 390 | fattr->cf_dtype = DT_BLK; |
379 | if (bytes_read == 24) { | 391 | if (bytes_read == 24) { |
@@ -385,7 +397,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
385 | fattr->cf_rdev = MKDEV(mjr, mnr); | 397 | fattr->cf_rdev = MKDEV(mjr, mnr); |
386 | } | 398 | } |
387 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { | 399 | } else if (memcmp("IntxCHR", pbuf, 8) == 0) { |
388 | cFYI(1, ("Char device")); | 400 | cFYI(1, "Char device"); |
389 | fattr->cf_mode |= S_IFCHR; | 401 | fattr->cf_mode |= S_IFCHR; |
390 | fattr->cf_dtype = DT_CHR; | 402 | fattr->cf_dtype = DT_CHR; |
391 | if (bytes_read == 24) { | 403 | if (bytes_read == 24) { |
@@ -397,7 +409,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, | |||
397 | fattr->cf_rdev = MKDEV(mjr, mnr); | 409 | fattr->cf_rdev = MKDEV(mjr, mnr); |
398 | } | 410 | } |
399 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { | 411 | } else if (memcmp("IntxLNK", pbuf, 7) == 0) { |
400 | cFYI(1, ("Symlink")); | 412 | cFYI(1, "Symlink"); |
401 | fattr->cf_mode |= S_IFLNK; | 413 | fattr->cf_mode |= S_IFLNK; |
402 | fattr->cf_dtype = DT_LNK; | 414 | fattr->cf_dtype = DT_LNK; |
403 | } else { | 415 | } else { |
@@ -439,10 +451,10 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | |||
439 | else if (rc > 3) { | 451 | else if (rc > 3) { |
440 | mode = le32_to_cpu(*((__le32 *)ea_value)); | 452 | mode = le32_to_cpu(*((__le32 *)ea_value)); |
441 | fattr->cf_mode &= ~SFBITS_MASK; | 453 | fattr->cf_mode &= ~SFBITS_MASK; |
442 | cFYI(1, ("special bits 0%o org mode 0%o", mode, | 454 | cFYI(1, "special bits 0%o org mode 0%o", mode, |
443 | fattr->cf_mode)); | 455 | fattr->cf_mode); |
444 | fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode; | 456 | fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode; |
445 | cFYI(1, ("special mode bits 0%o", mode)); | 457 | cFYI(1, "special mode bits 0%o", mode); |
446 | } | 458 | } |
447 | 459 | ||
448 | return 0; | 460 | return 0; |
@@ -504,7 +516,7 @@ int cifs_get_file_info(struct file *filp) | |||
504 | struct inode *inode = filp->f_path.dentry->d_inode; | 516 | struct inode *inode = filp->f_path.dentry->d_inode; |
505 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 517 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
506 | struct cifsTconInfo *tcon = cifs_sb->tcon; | 518 | struct cifsTconInfo *tcon = cifs_sb->tcon; |
507 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; | 519 | struct cifsFileInfo *cfile = filp->private_data; |
508 | 520 | ||
509 | xid = GetXid(); | 521 | xid = GetXid(); |
510 | rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); | 522 | rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); |
@@ -548,11 +560,11 @@ int cifs_get_inode_info(struct inode **pinode, | |||
548 | struct cifs_fattr fattr; | 560 | struct cifs_fattr fattr; |
549 | 561 | ||
550 | pTcon = cifs_sb->tcon; | 562 | pTcon = cifs_sb->tcon; |
551 | cFYI(1, ("Getting info on %s", full_path)); | 563 | cFYI(1, "Getting info on %s", full_path); |
552 | 564 | ||
553 | if ((pfindData == NULL) && (*pinode != NULL)) { | 565 | if ((pfindData == NULL) && (*pinode != NULL)) { |
554 | if (CIFS_I(*pinode)->clientCanCacheRead) { | 566 | if (CIFS_I(*pinode)->clientCanCacheRead) { |
555 | cFYI(1, ("No need to revalidate cached inode sizes")); | 567 | cFYI(1, "No need to revalidate cached inode sizes"); |
556 | return rc; | 568 | return rc; |
557 | } | 569 | } |
558 | } | 570 | } |
@@ -618,7 +630,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
618 | cifs_sb->mnt_cifs_flags & | 630 | cifs_sb->mnt_cifs_flags & |
619 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 631 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
620 | if (rc1 || !fattr.cf_uniqueid) { | 632 | if (rc1 || !fattr.cf_uniqueid) { |
621 | cFYI(1, ("GetSrvInodeNum rc %d", rc1)); | 633 | cFYI(1, "GetSrvInodeNum rc %d", rc1); |
622 | fattr.cf_uniqueid = iunique(sb, ROOT_I); | 634 | fattr.cf_uniqueid = iunique(sb, ROOT_I); |
623 | cifs_autodisable_serverino(cifs_sb); | 635 | cifs_autodisable_serverino(cifs_sb); |
624 | } | 636 | } |
@@ -634,13 +646,13 @@ int cifs_get_inode_info(struct inode **pinode, | |||
634 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { | 646 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { |
635 | tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid); | 647 | tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid); |
636 | if (tmprc) | 648 | if (tmprc) |
637 | cFYI(1, ("cifs_sfu_type failed: %d", tmprc)); | 649 | cFYI(1, "cifs_sfu_type failed: %d", tmprc); |
638 | } | 650 | } |
639 | 651 | ||
640 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 652 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
641 | /* fill in 0777 bits from ACL */ | 653 | /* fill in 0777 bits from ACL */ |
642 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 654 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
643 | cFYI(1, ("Getting mode bits from ACL")); | 655 | cFYI(1, "Getting mode bits from ACL"); |
644 | cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); | 656 | cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); |
645 | } | 657 | } |
646 | #endif | 658 | #endif |
@@ -712,9 +724,18 @@ cifs_find_inode(struct inode *inode, void *opaque) | |||
712 | { | 724 | { |
713 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | 725 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; |
714 | 726 | ||
727 | /* don't match inode with different uniqueid */ | ||
715 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) | 728 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) |
716 | return 0; | 729 | return 0; |
717 | 730 | ||
731 | /* don't match inode of different type */ | ||
732 | if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT)) | ||
733 | return 0; | ||
734 | |||
735 | /* if it's not a directory or has no dentries, then flag it */ | ||
736 | if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) | ||
737 | fattr->cf_flags |= CIFS_FATTR_INO_COLLISION; | ||
738 | |||
718 | return 1; | 739 | return 1; |
719 | } | 740 | } |
720 | 741 | ||
@@ -727,6 +748,27 @@ cifs_init_inode(struct inode *inode, void *opaque) | |||
727 | return 0; | 748 | return 0; |
728 | } | 749 | } |
729 | 750 | ||
751 | /* | ||
752 | * walk dentry list for an inode and report whether it has aliases that | ||
753 | * are hashed. We use this to determine if a directory inode can actually | ||
754 | * be used. | ||
755 | */ | ||
756 | static bool | ||
757 | inode_has_hashed_dentries(struct inode *inode) | ||
758 | { | ||
759 | struct dentry *dentry; | ||
760 | |||
761 | spin_lock(&dcache_lock); | ||
762 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { | ||
763 | if (!d_unhashed(dentry) || IS_ROOT(dentry)) { | ||
764 | spin_unlock(&dcache_lock); | ||
765 | return true; | ||
766 | } | ||
767 | } | ||
768 | spin_unlock(&dcache_lock); | ||
769 | return false; | ||
770 | } | ||
771 | |||
730 | /* Given fattrs, get a corresponding inode */ | 772 | /* Given fattrs, get a corresponding inode */ |
731 | struct inode * | 773 | struct inode * |
732 | cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) | 774 | cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) |
@@ -734,20 +776,35 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) | |||
734 | unsigned long hash; | 776 | unsigned long hash; |
735 | struct inode *inode; | 777 | struct inode *inode; |
736 | 778 | ||
737 | cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); | 779 | retry_iget5_locked: |
780 | cFYI(1, "looking for uniqueid=%llu", fattr->cf_uniqueid); | ||
738 | 781 | ||
739 | /* hash down to 32-bits on 32-bit arch */ | 782 | /* hash down to 32-bits on 32-bit arch */ |
740 | hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); | 783 | hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); |
741 | 784 | ||
742 | inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); | 785 | inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); |
743 | |||
744 | /* we have fattrs in hand, update the inode */ | ||
745 | if (inode) { | 786 | if (inode) { |
787 | /* was there a potentially problematic inode collision? */ | ||
788 | if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) { | ||
789 | fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION; | ||
790 | |||
791 | if (inode_has_hashed_dentries(inode)) { | ||
792 | cifs_autodisable_serverino(CIFS_SB(sb)); | ||
793 | iput(inode); | ||
794 | fattr->cf_uniqueid = iunique(sb, ROOT_I); | ||
795 | goto retry_iget5_locked; | ||
796 | } | ||
797 | } | ||
798 | |||
746 | cifs_fattr_to_inode(inode, fattr); | 799 | cifs_fattr_to_inode(inode, fattr); |
747 | if (sb->s_flags & MS_NOATIME) | 800 | if (sb->s_flags & MS_NOATIME) |
748 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | 801 | inode->i_flags |= S_NOATIME | S_NOCMTIME; |
749 | if (inode->i_state & I_NEW) { | 802 | if (inode->i_state & I_NEW) { |
750 | inode->i_ino = hash; | 803 | inode->i_ino = hash; |
804 | #ifdef CONFIG_CIFS_FSCACHE | ||
805 | /* initialize per-inode cache cookie pointer */ | ||
806 | CIFS_I(inode)->fscache = NULL; | ||
807 | #endif | ||
751 | unlock_new_inode(inode); | 808 | unlock_new_inode(inode); |
752 | } | 809 | } |
753 | } | 810 | } |
@@ -779,8 +836,13 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
779 | if (!inode) | 836 | if (!inode) |
780 | return ERR_PTR(-ENOMEM); | 837 | return ERR_PTR(-ENOMEM); |
781 | 838 | ||
839 | #ifdef CONFIG_CIFS_FSCACHE | ||
840 | /* populate tcon->resource_id */ | ||
841 | cifs_sb->tcon->resource_id = CIFS_I(inode)->uniqueid; | ||
842 | #endif | ||
843 | |||
782 | if (rc && cifs_sb->tcon->ipc) { | 844 | if (rc && cifs_sb->tcon->ipc) { |
783 | cFYI(1, ("ipc connection - fake read inode")); | 845 | cFYI(1, "ipc connection - fake read inode"); |
784 | inode->i_mode |= S_IFDIR; | 846 | inode->i_mode |= S_IFDIR; |
785 | inode->i_nlink = 2; | 847 | inode->i_nlink = 2; |
786 | inode->i_op = &cifs_ipc_inode_ops; | 848 | inode->i_op = &cifs_ipc_inode_ops; |
@@ -842,7 +904,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, | |||
842 | * server times. | 904 | * server times. |
843 | */ | 905 | */ |
844 | if (set_time && (attrs->ia_valid & ATTR_CTIME)) { | 906 | if (set_time && (attrs->ia_valid & ATTR_CTIME)) { |
845 | cFYI(1, ("CIFS - CTIME changed")); | 907 | cFYI(1, "CIFS - CTIME changed"); |
846 | info_buf.ChangeTime = | 908 | info_buf.ChangeTime = |
847 | cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); | 909 | cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); |
848 | } else | 910 | } else |
@@ -877,8 +939,8 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, | |||
877 | goto out; | 939 | goto out; |
878 | } | 940 | } |
879 | 941 | ||
880 | cFYI(1, ("calling SetFileInfo since SetPathInfo for " | 942 | cFYI(1, "calling SetFileInfo since SetPathInfo for " |
881 | "times not supported by this server")); | 943 | "times not supported by this server"); |
882 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, | 944 | rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, |
883 | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, | 945 | SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, |
884 | CREATE_NOT_DIR, &netfid, &oplock, | 946 | CREATE_NOT_DIR, &netfid, &oplock, |
@@ -1036,7 +1098,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
1036 | struct iattr *attrs = NULL; | 1098 | struct iattr *attrs = NULL; |
1037 | __u32 dosattr = 0, origattr = 0; | 1099 | __u32 dosattr = 0, origattr = 0; |
1038 | 1100 | ||
1039 | cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry)); | 1101 | cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry); |
1040 | 1102 | ||
1041 | xid = GetXid(); | 1103 | xid = GetXid(); |
1042 | 1104 | ||
@@ -1055,7 +1117,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
1055 | rc = CIFSPOSIXDelFile(xid, tcon, full_path, | 1117 | rc = CIFSPOSIXDelFile(xid, tcon, full_path, |
1056 | SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls, | 1118 | SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls, |
1057 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1119 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
1058 | cFYI(1, ("posix del rc %d", rc)); | 1120 | cFYI(1, "posix del rc %d", rc); |
1059 | if ((rc == 0) || (rc == -ENOENT)) | 1121 | if ((rc == 0) || (rc == -ENOENT)) |
1060 | goto psx_del_no_retry; | 1122 | goto psx_del_no_retry; |
1061 | } | 1123 | } |
@@ -1129,7 +1191,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1129 | struct inode *newinode = NULL; | 1191 | struct inode *newinode = NULL; |
1130 | struct cifs_fattr fattr; | 1192 | struct cifs_fattr fattr; |
1131 | 1193 | ||
1132 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); | 1194 | cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode); |
1133 | 1195 | ||
1134 | xid = GetXid(); | 1196 | xid = GetXid(); |
1135 | 1197 | ||
@@ -1164,7 +1226,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1164 | kfree(pInfo); | 1226 | kfree(pInfo); |
1165 | goto mkdir_retry_old; | 1227 | goto mkdir_retry_old; |
1166 | } else if (rc) { | 1228 | } else if (rc) { |
1167 | cFYI(1, ("posix mkdir returned 0x%x", rc)); | 1229 | cFYI(1, "posix mkdir returned 0x%x", rc); |
1168 | d_drop(direntry); | 1230 | d_drop(direntry); |
1169 | } else { | 1231 | } else { |
1170 | if (pInfo->Type == cpu_to_le32(-1)) { | 1232 | if (pInfo->Type == cpu_to_le32(-1)) { |
@@ -1181,6 +1243,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1181 | direntry->d_op = &cifs_dentry_ops; | 1243 | direntry->d_op = &cifs_dentry_ops; |
1182 | 1244 | ||
1183 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); | 1245 | cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); |
1246 | cifs_fill_uniqueid(inode->i_sb, &fattr); | ||
1184 | newinode = cifs_iget(inode->i_sb, &fattr); | 1247 | newinode = cifs_iget(inode->i_sb, &fattr); |
1185 | if (!newinode) { | 1248 | if (!newinode) { |
1186 | kfree(pInfo); | 1249 | kfree(pInfo); |
@@ -1190,12 +1253,12 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1190 | d_instantiate(direntry, newinode); | 1253 | d_instantiate(direntry, newinode); |
1191 | 1254 | ||
1192 | #ifdef CONFIG_CIFS_DEBUG2 | 1255 | #ifdef CONFIG_CIFS_DEBUG2 |
1193 | cFYI(1, ("instantiated dentry %p %s to inode %p", | 1256 | cFYI(1, "instantiated dentry %p %s to inode %p", |
1194 | direntry, direntry->d_name.name, newinode)); | 1257 | direntry, direntry->d_name.name, newinode); |
1195 | 1258 | ||
1196 | if (newinode->i_nlink != 2) | 1259 | if (newinode->i_nlink != 2) |
1197 | cFYI(1, ("unexpected number of links %d", | 1260 | cFYI(1, "unexpected number of links %d", |
1198 | newinode->i_nlink)); | 1261 | newinode->i_nlink); |
1199 | #endif | 1262 | #endif |
1200 | } | 1263 | } |
1201 | kfree(pInfo); | 1264 | kfree(pInfo); |
@@ -1206,7 +1269,7 @@ mkdir_retry_old: | |||
1206 | rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, | 1269 | rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, |
1207 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 1270 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
1208 | if (rc) { | 1271 | if (rc) { |
1209 | cFYI(1, ("cifs_mkdir returned 0x%x", rc)); | 1272 | cFYI(1, "cifs_mkdir returned 0x%x", rc); |
1210 | d_drop(direntry); | 1273 | d_drop(direntry); |
1211 | } else { | 1274 | } else { |
1212 | mkdir_get_info: | 1275 | mkdir_get_info: |
@@ -1309,7 +1372,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
1309 | char *full_path = NULL; | 1372 | char *full_path = NULL; |
1310 | struct cifsInodeInfo *cifsInode; | 1373 | struct cifsInodeInfo *cifsInode; |
1311 | 1374 | ||
1312 | cFYI(1, ("cifs_rmdir, inode = 0x%p", inode)); | 1375 | cFYI(1, "cifs_rmdir, inode = 0x%p", inode); |
1313 | 1376 | ||
1314 | xid = GetXid(); | 1377 | xid = GetXid(); |
1315 | 1378 | ||
@@ -1372,6 +1435,10 @@ cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath, | |||
1372 | if (rc == 0 || rc != -ETXTBSY) | 1435 | if (rc == 0 || rc != -ETXTBSY) |
1373 | return rc; | 1436 | return rc; |
1374 | 1437 | ||
1438 | /* open-file renames don't work across directories */ | ||
1439 | if (to_dentry->d_parent != from_dentry->d_parent) | ||
1440 | return rc; | ||
1441 | |||
1375 | /* open the file to be renamed -- we need DELETE perms */ | 1442 | /* open the file to be renamed -- we need DELETE perms */ |
1376 | rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, | 1443 | rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE, |
1377 | CREATE_NOT_DIR, &srcfid, &oplock, NULL, | 1444 | CREATE_NOT_DIR, &srcfid, &oplock, NULL, |
@@ -1511,6 +1578,11 @@ cifs_inode_needs_reval(struct inode *inode) | |||
1511 | if (time_after_eq(jiffies, cifs_i->time + HZ)) | 1578 | if (time_after_eq(jiffies, cifs_i->time + HZ)) |
1512 | return true; | 1579 | return true; |
1513 | 1580 | ||
1581 | /* hardlinked files w/ noserverino get "special" treatment */ | ||
1582 | if (!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) && | ||
1583 | S_ISREG(inode->i_mode) && inode->i_nlink != 1) | ||
1584 | return true; | ||
1585 | |||
1514 | return false; | 1586 | return false; |
1515 | } | 1587 | } |
1516 | 1588 | ||
@@ -1530,6 +1602,7 @@ cifs_invalidate_mapping(struct inode *inode) | |||
1530 | cifs_i->write_behind_rc = rc; | 1602 | cifs_i->write_behind_rc = rc; |
1531 | } | 1603 | } |
1532 | invalidate_remote_inode(inode); | 1604 | invalidate_remote_inode(inode); |
1605 | cifs_fscache_reset_inode_cookie(inode); | ||
1533 | } | 1606 | } |
1534 | 1607 | ||
1535 | int cifs_revalidate_file(struct file *filp) | 1608 | int cifs_revalidate_file(struct file *filp) |
@@ -1577,9 +1650,9 @@ int cifs_revalidate_dentry(struct dentry *dentry) | |||
1577 | goto check_inval; | 1650 | goto check_inval; |
1578 | } | 1651 | } |
1579 | 1652 | ||
1580 | cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " | 1653 | cFYI(1, "Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " |
1581 | "jiffies %ld", full_path, inode, inode->i_count.counter, | 1654 | "jiffies %ld", full_path, inode, inode->i_count.counter, |
1582 | dentry, dentry->d_time, jiffies)); | 1655 | dentry, dentry->d_time, jiffies); |
1583 | 1656 | ||
1584 | if (CIFS_SB(sb)->tcon->unix_ext) | 1657 | if (CIFS_SB(sb)->tcon->unix_ext) |
1585 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); | 1658 | rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); |
@@ -1625,26 +1698,16 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from) | |||
1625 | return rc; | 1698 | return rc; |
1626 | } | 1699 | } |
1627 | 1700 | ||
1628 | static int cifs_vmtruncate(struct inode *inode, loff_t offset) | 1701 | static void cifs_setsize(struct inode *inode, loff_t offset) |
1629 | { | 1702 | { |
1630 | loff_t oldsize; | 1703 | loff_t oldsize; |
1631 | int err; | ||
1632 | 1704 | ||
1633 | spin_lock(&inode->i_lock); | 1705 | spin_lock(&inode->i_lock); |
1634 | err = inode_newsize_ok(inode, offset); | ||
1635 | if (err) { | ||
1636 | spin_unlock(&inode->i_lock); | ||
1637 | goto out; | ||
1638 | } | ||
1639 | |||
1640 | oldsize = inode->i_size; | 1706 | oldsize = inode->i_size; |
1641 | i_size_write(inode, offset); | 1707 | i_size_write(inode, offset); |
1642 | spin_unlock(&inode->i_lock); | 1708 | spin_unlock(&inode->i_lock); |
1709 | |||
1643 | truncate_pagecache(inode, oldsize, offset); | 1710 | truncate_pagecache(inode, oldsize, offset); |
1644 | if (inode->i_op->truncate) | ||
1645 | inode->i_op->truncate(inode); | ||
1646 | out: | ||
1647 | return err; | ||
1648 | } | 1711 | } |
1649 | 1712 | ||
1650 | static int | 1713 | static int |
@@ -1673,12 +1736,12 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1673 | rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, | 1736 | rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, |
1674 | npid, false); | 1737 | npid, false); |
1675 | cifsFileInfo_put(open_file); | 1738 | cifsFileInfo_put(open_file); |
1676 | cFYI(1, ("SetFSize for attrs rc = %d", rc)); | 1739 | cFYI(1, "SetFSize for attrs rc = %d", rc); |
1677 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 1740 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
1678 | unsigned int bytes_written; | 1741 | unsigned int bytes_written; |
1679 | rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, | 1742 | rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, |
1680 | &bytes_written, NULL, NULL, 1); | 1743 | &bytes_written, NULL, NULL, 1); |
1681 | cFYI(1, ("Wrt seteof rc %d", rc)); | 1744 | cFYI(1, "Wrt seteof rc %d", rc); |
1682 | } | 1745 | } |
1683 | } else | 1746 | } else |
1684 | rc = -EINVAL; | 1747 | rc = -EINVAL; |
@@ -1692,7 +1755,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1692 | false, cifs_sb->local_nls, | 1755 | false, cifs_sb->local_nls, |
1693 | cifs_sb->mnt_cifs_flags & | 1756 | cifs_sb->mnt_cifs_flags & |
1694 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1757 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1695 | cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); | 1758 | cFYI(1, "SetEOF by path (setattrs) rc = %d", rc); |
1696 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 1759 | if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
1697 | __u16 netfid; | 1760 | __u16 netfid; |
1698 | int oplock = 0; | 1761 | int oplock = 0; |
@@ -1709,7 +1772,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1709 | attrs->ia_size, | 1772 | attrs->ia_size, |
1710 | &bytes_written, NULL, | 1773 | &bytes_written, NULL, |
1711 | NULL, 1); | 1774 | NULL, 1); |
1712 | cFYI(1, ("wrt seteof rc %d", rc)); | 1775 | cFYI(1, "wrt seteof rc %d", rc); |
1713 | CIFSSMBClose(xid, pTcon, netfid); | 1776 | CIFSSMBClose(xid, pTcon, netfid); |
1714 | } | 1777 | } |
1715 | } | 1778 | } |
@@ -1717,7 +1780,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1717 | 1780 | ||
1718 | if (rc == 0) { | 1781 | if (rc == 0) { |
1719 | cifsInode->server_eof = attrs->ia_size; | 1782 | cifsInode->server_eof = attrs->ia_size; |
1720 | rc = cifs_vmtruncate(inode, attrs->ia_size); | 1783 | cifs_setsize(inode, attrs->ia_size); |
1721 | cifs_truncate_page(inode->i_mapping, inode->i_size); | 1784 | cifs_truncate_page(inode->i_mapping, inode->i_size); |
1722 | } | 1785 | } |
1723 | 1786 | ||
@@ -1737,19 +1800,17 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1737 | struct cifs_unix_set_info_args *args = NULL; | 1800 | struct cifs_unix_set_info_args *args = NULL; |
1738 | struct cifsFileInfo *open_file; | 1801 | struct cifsFileInfo *open_file; |
1739 | 1802 | ||
1740 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", | 1803 | cFYI(1, "setattr_unix on file %s attrs->ia_valid=0x%x", |
1741 | direntry->d_name.name, attrs->ia_valid)); | 1804 | direntry->d_name.name, attrs->ia_valid); |
1742 | 1805 | ||
1743 | xid = GetXid(); | 1806 | xid = GetXid(); |
1744 | 1807 | ||
1745 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { | 1808 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) |
1746 | /* check if we have permission to change attrs */ | 1809 | attrs->ia_valid |= ATTR_FORCE; |
1747 | rc = inode_change_ok(inode, attrs); | 1810 | |
1748 | if (rc < 0) | 1811 | rc = inode_change_ok(inode, attrs); |
1749 | goto out; | 1812 | if (rc < 0) |
1750 | else | 1813 | goto out; |
1751 | rc = 0; | ||
1752 | } | ||
1753 | 1814 | ||
1754 | full_path = build_path_from_dentry(direntry); | 1815 | full_path = build_path_from_dentry(direntry); |
1755 | if (full_path == NULL) { | 1816 | if (full_path == NULL) { |
@@ -1835,18 +1896,24 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1835 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1896 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1836 | } | 1897 | } |
1837 | 1898 | ||
1838 | if (!rc) { | 1899 | if (rc) |
1839 | rc = inode_setattr(inode, attrs); | 1900 | goto out; |
1840 | 1901 | ||
1841 | /* force revalidate when any of these times are set since some | 1902 | if ((attrs->ia_valid & ATTR_SIZE) && |
1842 | of the fs types (eg ext3, fat) do not have fine enough | 1903 | attrs->ia_size != i_size_read(inode)) |
1843 | time granularity to match protocol, and we do not have a | 1904 | truncate_setsize(inode, attrs->ia_size); |
1844 | a way (yet) to query the server fs's time granularity (and | 1905 | |
1845 | whether it rounds times down). | 1906 | setattr_copy(inode, attrs); |
1846 | */ | 1907 | mark_inode_dirty(inode); |
1847 | if (!rc && (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME))) | 1908 | |
1848 | cifsInode->time = 0; | 1909 | /* force revalidate when any of these times are set since some |
1849 | } | 1910 | of the fs types (eg ext3, fat) do not have fine enough |
1911 | time granularity to match protocol, and we do not have a | ||
1912 | a way (yet) to query the server fs's time granularity (and | ||
1913 | whether it rounds times down). | ||
1914 | */ | ||
1915 | if (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME)) | ||
1916 | cifsInode->time = 0; | ||
1850 | out: | 1917 | out: |
1851 | kfree(args); | 1918 | kfree(args); |
1852 | kfree(full_path); | 1919 | kfree(full_path); |
@@ -1868,17 +1935,16 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
1868 | 1935 | ||
1869 | xid = GetXid(); | 1936 | xid = GetXid(); |
1870 | 1937 | ||
1871 | cFYI(1, ("setattr on file %s attrs->iavalid 0x%x", | 1938 | cFYI(1, "setattr on file %s attrs->iavalid 0x%x", |
1872 | direntry->d_name.name, attrs->ia_valid)); | 1939 | direntry->d_name.name, attrs->ia_valid); |
1873 | 1940 | ||
1874 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { | 1941 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) |
1875 | /* check if we have permission to change attrs */ | 1942 | attrs->ia_valid |= ATTR_FORCE; |
1876 | rc = inode_change_ok(inode, attrs); | 1943 | |
1877 | if (rc < 0) { | 1944 | rc = inode_change_ok(inode, attrs); |
1878 | FreeXid(xid); | 1945 | if (rc < 0) { |
1879 | return rc; | 1946 | FreeXid(xid); |
1880 | } else | 1947 | return rc; |
1881 | rc = 0; | ||
1882 | } | 1948 | } |
1883 | 1949 | ||
1884 | full_path = build_path_from_dentry(direntry); | 1950 | full_path = build_path_from_dentry(direntry); |
@@ -1926,7 +1992,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
1926 | attrs->ia_valid &= ~ATTR_MODE; | 1992 | attrs->ia_valid &= ~ATTR_MODE; |
1927 | 1993 | ||
1928 | if (attrs->ia_valid & ATTR_MODE) { | 1994 | if (attrs->ia_valid & ATTR_MODE) { |
1929 | cFYI(1, ("Mode changed to 0%o", attrs->ia_mode)); | 1995 | cFYI(1, "Mode changed to 0%o", attrs->ia_mode); |
1930 | mode = attrs->ia_mode; | 1996 | mode = attrs->ia_mode; |
1931 | } | 1997 | } |
1932 | 1998 | ||
@@ -1986,8 +2052,17 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
1986 | 2052 | ||
1987 | /* do not need local check to inode_check_ok since the server does | 2053 | /* do not need local check to inode_check_ok since the server does |
1988 | that */ | 2054 | that */ |
1989 | if (!rc) | 2055 | if (rc) |
1990 | rc = inode_setattr(inode, attrs); | 2056 | goto cifs_setattr_exit; |
2057 | |||
2058 | if ((attrs->ia_valid & ATTR_SIZE) && | ||
2059 | attrs->ia_size != i_size_read(inode)) | ||
2060 | truncate_setsize(inode, attrs->ia_size); | ||
2061 | |||
2062 | setattr_copy(inode, attrs); | ||
2063 | mark_inode_dirty(inode); | ||
2064 | return 0; | ||
2065 | |||
1991 | cifs_setattr_exit: | 2066 | cifs_setattr_exit: |
1992 | kfree(full_path); | 2067 | kfree(full_path); |
1993 | FreeXid(xid); | 2068 | FreeXid(xid); |
@@ -2012,7 +2087,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
2012 | #if 0 | 2087 | #if 0 |
2013 | void cifs_delete_inode(struct inode *inode) | 2088 | void cifs_delete_inode(struct inode *inode) |
2014 | { | 2089 | { |
2015 | cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode)); | 2090 | cFYI(1, "In cifs_delete_inode, inode = 0x%p", inode); |
2016 | /* may have to add back in if and when safe distributed caching of | 2091 | /* may have to add back in if and when safe distributed caching of |
2017 | directories added e.g. via FindNotify */ | 2092 | directories added e.g. via FindNotify */ |
2018 | } | 2093 | } |