diff options
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 243 |
1 files changed, 153 insertions, 90 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 268ce3a46220..b7656bd3706f 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -249,13 +249,10 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
249 | struct inode *inode = ERR_PTR(-ENOENT); | 249 | struct inode *inode = ERR_PTR(-ENOENT); |
250 | unsigned long hash; | 250 | unsigned long hash; |
251 | 251 | ||
252 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 252 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) |
253 | goto out_no_inode; | 253 | goto out_no_inode; |
254 | 254 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0) | |
255 | if (!fattr->nlink) { | ||
256 | printk("NFS: Buggy server - nlink == 0!\n"); | ||
257 | goto out_no_inode; | 255 | goto out_no_inode; |
258 | } | ||
259 | 256 | ||
260 | hash = nfs_fattr_to_ino_t(fattr); | 257 | hash = nfs_fattr_to_ino_t(fattr); |
261 | 258 | ||
@@ -291,7 +288,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
291 | && fattr->size <= NFS_LIMIT_READDIRPLUS) | 288 | && fattr->size <= NFS_LIMIT_READDIRPLUS) |
292 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); | 289 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
293 | /* Deal with crossing mountpoints */ | 290 | /* Deal with crossing mountpoints */ |
294 | if (!nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { | 291 | if ((fattr->valid & NFS_ATTR_FATTR_FSID) |
292 | && !nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { | ||
295 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) | 293 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) |
296 | inode->i_op = &nfs_referral_inode_operations; | 294 | inode->i_op = &nfs_referral_inode_operations; |
297 | else | 295 | else |
@@ -304,28 +302,45 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
304 | else | 302 | else |
305 | init_special_inode(inode, inode->i_mode, fattr->rdev); | 303 | init_special_inode(inode, inode->i_mode, fattr->rdev); |
306 | 304 | ||
305 | memset(&inode->i_atime, 0, sizeof(inode->i_atime)); | ||
306 | memset(&inode->i_mtime, 0, sizeof(inode->i_mtime)); | ||
307 | memset(&inode->i_ctime, 0, sizeof(inode->i_ctime)); | ||
308 | nfsi->change_attr = 0; | ||
309 | inode->i_size = 0; | ||
310 | inode->i_nlink = 0; | ||
311 | inode->i_uid = -2; | ||
312 | inode->i_gid = -2; | ||
313 | inode->i_blocks = 0; | ||
314 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | ||
315 | |||
307 | nfsi->read_cache_jiffies = fattr->time_start; | 316 | nfsi->read_cache_jiffies = fattr->time_start; |
308 | nfsi->attr_gencount = fattr->gencount; | 317 | nfsi->attr_gencount = fattr->gencount; |
309 | inode->i_atime = fattr->atime; | 318 | if (fattr->valid & NFS_ATTR_FATTR_ATIME) |
310 | inode->i_mtime = fattr->mtime; | 319 | inode->i_atime = fattr->atime; |
311 | inode->i_ctime = fattr->ctime; | 320 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) |
312 | if (fattr->valid & NFS_ATTR_FATTR_V4) | 321 | inode->i_mtime = fattr->mtime; |
322 | if (fattr->valid & NFS_ATTR_FATTR_CTIME) | ||
323 | inode->i_ctime = fattr->ctime; | ||
324 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) | ||
313 | nfsi->change_attr = fattr->change_attr; | 325 | nfsi->change_attr = fattr->change_attr; |
314 | inode->i_size = nfs_size_to_loff_t(fattr->size); | 326 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) |
315 | inode->i_nlink = fattr->nlink; | 327 | inode->i_size = nfs_size_to_loff_t(fattr->size); |
316 | inode->i_uid = fattr->uid; | 328 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) |
317 | inode->i_gid = fattr->gid; | 329 | inode->i_nlink = fattr->nlink; |
318 | if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) { | 330 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) |
331 | inode->i_uid = fattr->uid; | ||
332 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) | ||
333 | inode->i_gid = fattr->gid; | ||
334 | if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) | ||
335 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
336 | if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { | ||
319 | /* | 337 | /* |
320 | * report the blocks in 512byte units | 338 | * report the blocks in 512byte units |
321 | */ | 339 | */ |
322 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 340 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
323 | } else { | ||
324 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
325 | } | 341 | } |
326 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 342 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
327 | nfsi->attrtimeo_timestamp = now; | 343 | nfsi->attrtimeo_timestamp = now; |
328 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | ||
329 | nfsi->access_cache = RB_ROOT; | 344 | nfsi->access_cache = RB_ROOT; |
330 | 345 | ||
331 | unlock_new_inode(inode); | 346 | unlock_new_inode(inode); |
@@ -812,25 +827,31 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
812 | { | 827 | { |
813 | struct nfs_inode *nfsi = NFS_I(inode); | 828 | struct nfs_inode *nfsi = NFS_I(inode); |
814 | 829 | ||
815 | if ((fattr->valid & NFS_ATTR_WCC_V4) != 0 && | 830 | if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE) |
816 | nfsi->change_attr == fattr->pre_change_attr) { | 831 | && (fattr->valid & NFS_ATTR_FATTR_CHANGE) |
832 | && nfsi->change_attr == fattr->pre_change_attr) { | ||
817 | nfsi->change_attr = fattr->change_attr; | 833 | nfsi->change_attr = fattr->change_attr; |
818 | if (S_ISDIR(inode->i_mode)) | 834 | if (S_ISDIR(inode->i_mode)) |
819 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 835 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
820 | } | 836 | } |
821 | /* If we have atomic WCC data, we may update some attributes */ | 837 | /* If we have atomic WCC data, we may update some attributes */ |
822 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { | 838 | if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME) |
823 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) | 839 | && (fattr->valid & NFS_ATTR_FATTR_CTIME) |
840 | && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) | ||
824 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 841 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
825 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | 842 | |
843 | if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME) | ||
844 | && (fattr->valid & NFS_ATTR_FATTR_MTIME) | ||
845 | && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | ||
826 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 846 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
827 | if (S_ISDIR(inode->i_mode)) | 847 | if (S_ISDIR(inode->i_mode)) |
828 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 848 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
829 | } | ||
830 | if (i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) && | ||
831 | nfsi->npages == 0) | ||
832 | i_size_write(inode, nfs_size_to_loff_t(fattr->size)); | ||
833 | } | 849 | } |
850 | if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE) | ||
851 | && (fattr->valid & NFS_ATTR_FATTR_SIZE) | ||
852 | && i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size) | ||
853 | && nfsi->npages == 0) | ||
854 | i_size_write(inode, nfs_size_to_loff_t(fattr->size)); | ||
834 | } | 855 | } |
835 | 856 | ||
836 | /** | 857 | /** |
@@ -850,35 +871,39 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
850 | 871 | ||
851 | 872 | ||
852 | /* Has the inode gone and changed behind our back? */ | 873 | /* Has the inode gone and changed behind our back? */ |
853 | if (nfsi->fileid != fattr->fileid | 874 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) |
854 | || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { | 875 | return -EIO; |
876 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | ||
855 | return -EIO; | 877 | return -EIO; |
856 | } | ||
857 | 878 | ||
858 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 879 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && |
859 | nfsi->change_attr != fattr->change_attr) | 880 | nfsi->change_attr != fattr->change_attr) |
860 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 881 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
861 | 882 | ||
862 | /* Verify a few of the more important attributes */ | 883 | /* Verify a few of the more important attributes */ |
863 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) | 884 | if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&inode->i_mtime, &fattr->mtime)) |
864 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 885 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
865 | 886 | ||
866 | cur_size = i_size_read(inode); | 887 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { |
867 | new_isize = nfs_size_to_loff_t(fattr->size); | 888 | cur_size = i_size_read(inode); |
868 | if (cur_size != new_isize && nfsi->npages == 0) | 889 | new_isize = nfs_size_to_loff_t(fattr->size); |
869 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 890 | if (cur_size != new_isize && nfsi->npages == 0) |
891 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | ||
892 | } | ||
870 | 893 | ||
871 | /* Have any file permissions changed? */ | 894 | /* Have any file permissions changed? */ |
872 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) | 895 | if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) |
873 | || inode->i_uid != fattr->uid | 896 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; |
874 | || inode->i_gid != fattr->gid) | 897 | if ((fattr->valid & NFS_ATTR_FATTR_OWNER) && inode->i_uid != fattr->uid) |
898 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | ||
899 | if ((fattr->valid & NFS_ATTR_FATTR_GROUP) && inode->i_gid != fattr->gid) | ||
875 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | 900 | invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; |
876 | 901 | ||
877 | /* Has the link count changed? */ | 902 | /* Has the link count changed? */ |
878 | if (inode->i_nlink != fattr->nlink) | 903 | if ((fattr->valid & NFS_ATTR_FATTR_NLINK) && inode->i_nlink != fattr->nlink) |
879 | invalid |= NFS_INO_INVALID_ATTR; | 904 | invalid |= NFS_INO_INVALID_ATTR; |
880 | 905 | ||
881 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) | 906 | if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&inode->i_atime, &fattr->atime)) |
882 | invalid |= NFS_INO_INVALID_ATIME; | 907 | invalid |= NFS_INO_INVALID_ATIME; |
883 | 908 | ||
884 | if (invalid != 0) | 909 | if (invalid != 0) |
@@ -890,11 +915,15 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
890 | 915 | ||
891 | static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | 916 | static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr) |
892 | { | 917 | { |
918 | if (!(fattr->valid & NFS_ATTR_FATTR_CTIME)) | ||
919 | return 0; | ||
893 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; | 920 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; |
894 | } | 921 | } |
895 | 922 | ||
896 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | 923 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) |
897 | { | 924 | { |
925 | if (!(fattr->valid & NFS_ATTR_FATTR_SIZE)) | ||
926 | return 0; | ||
898 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); | 927 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); |
899 | } | 928 | } |
900 | 929 | ||
@@ -1030,20 +1059,31 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa | |||
1030 | /* Don't do a WCC update if these attributes are already stale */ | 1059 | /* Don't do a WCC update if these attributes are already stale */ |
1031 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || | 1060 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || |
1032 | !nfs_inode_attrs_need_update(inode, fattr)) { | 1061 | !nfs_inode_attrs_need_update(inode, fattr)) { |
1033 | fattr->valid &= ~(NFS_ATTR_WCC_V4|NFS_ATTR_WCC); | 1062 | fattr->valid &= ~(NFS_ATTR_FATTR_PRECHANGE |
1063 | | NFS_ATTR_FATTR_PRESIZE | ||
1064 | | NFS_ATTR_FATTR_PREMTIME | ||
1065 | | NFS_ATTR_FATTR_PRECTIME); | ||
1034 | goto out_noforce; | 1066 | goto out_noforce; |
1035 | } | 1067 | } |
1036 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 1068 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && |
1037 | (fattr->valid & NFS_ATTR_WCC_V4) == 0) { | 1069 | (fattr->valid & NFS_ATTR_FATTR_PRECHANGE) == 0) { |
1038 | fattr->pre_change_attr = NFS_I(inode)->change_attr; | 1070 | fattr->pre_change_attr = NFS_I(inode)->change_attr; |
1039 | fattr->valid |= NFS_ATTR_WCC_V4; | 1071 | fattr->valid |= NFS_ATTR_FATTR_PRECHANGE; |
1040 | } | 1072 | } |
1041 | if ((fattr->valid & NFS_ATTR_FATTR) != 0 && | 1073 | if ((fattr->valid & NFS_ATTR_FATTR_CTIME) != 0 && |
1042 | (fattr->valid & NFS_ATTR_WCC) == 0) { | 1074 | (fattr->valid & NFS_ATTR_FATTR_PRECTIME) == 0) { |
1043 | memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime)); | 1075 | memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime)); |
1076 | fattr->valid |= NFS_ATTR_FATTR_PRECTIME; | ||
1077 | } | ||
1078 | if ((fattr->valid & NFS_ATTR_FATTR_MTIME) != 0 && | ||
1079 | (fattr->valid & NFS_ATTR_FATTR_PREMTIME) == 0) { | ||
1044 | memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime)); | 1080 | memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime)); |
1081 | fattr->valid |= NFS_ATTR_FATTR_PREMTIME; | ||
1082 | } | ||
1083 | if ((fattr->valid & NFS_ATTR_FATTR_SIZE) != 0 && | ||
1084 | (fattr->valid & NFS_ATTR_FATTR_PRESIZE) == 0) { | ||
1045 | fattr->pre_size = i_size_read(inode); | 1085 | fattr->pre_size = i_size_read(inode); |
1046 | fattr->valid |= NFS_ATTR_WCC; | 1086 | fattr->valid |= NFS_ATTR_FATTR_PRESIZE; |
1047 | } | 1087 | } |
1048 | out_noforce: | 1088 | out_noforce: |
1049 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1089 | status = nfs_post_op_update_inode_locked(inode, fattr); |
@@ -1075,18 +1115,18 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1075 | __func__, inode->i_sb->s_id, inode->i_ino, | 1115 | __func__, inode->i_sb->s_id, inode->i_ino, |
1076 | atomic_read(&inode->i_count), fattr->valid); | 1116 | atomic_read(&inode->i_count), fattr->valid); |
1077 | 1117 | ||
1078 | if (nfsi->fileid != fattr->fileid) | 1118 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid) |
1079 | goto out_fileid; | 1119 | goto out_fileid; |
1080 | 1120 | ||
1081 | /* | 1121 | /* |
1082 | * Make sure the inode's type hasn't changed. | 1122 | * Make sure the inode's type hasn't changed. |
1083 | */ | 1123 | */ |
1084 | if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | 1124 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) |
1085 | goto out_changed; | 1125 | goto out_changed; |
1086 | 1126 | ||
1087 | server = NFS_SERVER(inode); | 1127 | server = NFS_SERVER(inode); |
1088 | /* Update the fsid? */ | 1128 | /* Update the fsid? */ |
1089 | if (S_ISDIR(inode->i_mode) && | 1129 | if (S_ISDIR(inode->i_mode) && (fattr->valid & NFS_ATTR_FATTR_FSID) && |
1090 | !nfs_fsid_equal(&server->fsid, &fattr->fsid) && | 1130 | !nfs_fsid_equal(&server->fsid, &fattr->fsid) && |
1091 | !test_bit(NFS_INO_MOUNTPOINT, &nfsi->flags)) | 1131 | !test_bit(NFS_INO_MOUNTPOINT, &nfsi->flags)) |
1092 | server->fsid = fattr->fsid; | 1132 | server->fsid = fattr->fsid; |
@@ -1096,14 +1136,27 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1096 | */ | 1136 | */ |
1097 | nfsi->read_cache_jiffies = fattr->time_start; | 1137 | nfsi->read_cache_jiffies = fattr->time_start; |
1098 | 1138 | ||
1099 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ATIME | 1139 | if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) || (fattr->valid & (NFS_ATTR_FATTR_MTIME|NFS_ATTR_FATTR_CTIME))) |
1100 | | NFS_INO_REVAL_PAGECACHE); | 1140 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR |
1141 | | NFS_INO_INVALID_ATIME | ||
1142 | | NFS_INO_REVAL_PAGECACHE); | ||
1101 | 1143 | ||
1102 | /* Do atomic weak cache consistency updates */ | 1144 | /* Do atomic weak cache consistency updates */ |
1103 | nfs_wcc_update_inode(inode, fattr); | 1145 | nfs_wcc_update_inode(inode, fattr); |
1104 | 1146 | ||
1105 | /* More cache consistency checks */ | 1147 | /* More cache consistency checks */ |
1106 | if (!(fattr->valid & NFS_ATTR_FATTR_V4)) { | 1148 | if (fattr->valid & NFS_ATTR_FATTR_CHANGE) { |
1149 | if (nfsi->change_attr != fattr->change_attr) { | ||
1150 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | ||
1151 | inode->i_sb->s_id, inode->i_ino); | ||
1152 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1153 | if (S_ISDIR(inode->i_mode)) | ||
1154 | nfs_force_lookup_revalidate(inode); | ||
1155 | nfsi->change_attr = fattr->change_attr; | ||
1156 | } | ||
1157 | } | ||
1158 | |||
1159 | if (fattr->valid & NFS_ATTR_FATTR_MTIME) { | ||
1107 | /* NFSv2/v3: Check if the mtime agrees */ | 1160 | /* NFSv2/v3: Check if the mtime agrees */ |
1108 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | 1161 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { |
1109 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1162 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
@@ -1111,7 +1164,10 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1111 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1164 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1112 | if (S_ISDIR(inode->i_mode)) | 1165 | if (S_ISDIR(inode->i_mode)) |
1113 | nfs_force_lookup_revalidate(inode); | 1166 | nfs_force_lookup_revalidate(inode); |
1167 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | ||
1114 | } | 1168 | } |
1169 | } | ||
1170 | if (fattr->valid & NFS_ATTR_FATTR_CTIME) { | ||
1115 | /* If ctime has changed we should definitely clear access+acl caches */ | 1171 | /* If ctime has changed we should definitely clear access+acl caches */ |
1116 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { | 1172 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { |
1117 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1173 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
@@ -1122,59 +1178,66 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1122 | invalid |= NFS_INO_INVALID_DATA; | 1178 | invalid |= NFS_INO_INVALID_DATA; |
1123 | nfs_force_lookup_revalidate(inode); | 1179 | nfs_force_lookup_revalidate(inode); |
1124 | } | 1180 | } |
1181 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | ||
1125 | } | 1182 | } |
1126 | } else if (nfsi->change_attr != fattr->change_attr) { | ||
1127 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | ||
1128 | inode->i_sb->s_id, inode->i_ino); | ||
1129 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1130 | if (S_ISDIR(inode->i_mode)) | ||
1131 | nfs_force_lookup_revalidate(inode); | ||
1132 | } | 1183 | } |
1133 | 1184 | ||
1134 | /* Check if our cached file size is stale */ | 1185 | /* Check if our cached file size is stale */ |
1135 | new_isize = nfs_size_to_loff_t(fattr->size); | 1186 | if (fattr->valid & NFS_ATTR_FATTR_SIZE) { |
1136 | cur_isize = i_size_read(inode); | 1187 | new_isize = nfs_size_to_loff_t(fattr->size); |
1137 | if (new_isize != cur_isize) { | 1188 | cur_isize = i_size_read(inode); |
1138 | /* Do we perhaps have any outstanding writes, or has | 1189 | if (new_isize != cur_isize) { |
1139 | * the file grown beyond our last write? */ | 1190 | /* Do we perhaps have any outstanding writes, or has |
1140 | if (nfsi->npages == 0 || new_isize > cur_isize) { | 1191 | * the file grown beyond our last write? */ |
1141 | i_size_write(inode, new_isize); | 1192 | if (nfsi->npages == 0 || new_isize > cur_isize) { |
1142 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1193 | i_size_write(inode, new_isize); |
1194 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | ||
1195 | } | ||
1196 | dprintk("NFS: isize change on server for file %s/%ld\n", | ||
1197 | inode->i_sb->s_id, inode->i_ino); | ||
1143 | } | 1198 | } |
1144 | dprintk("NFS: isize change on server for file %s/%ld\n", | ||
1145 | inode->i_sb->s_id, inode->i_ino); | ||
1146 | } | 1199 | } |
1147 | 1200 | ||
1148 | 1201 | ||
1149 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 1202 | if (fattr->valid & NFS_ATTR_FATTR_ATIME) |
1150 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 1203 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); |
1151 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); | ||
1152 | nfsi->change_attr = fattr->change_attr; | ||
1153 | 1204 | ||
1154 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || | 1205 | if (fattr->valid & NFS_ATTR_FATTR_MODE) { |
1155 | inode->i_uid != fattr->uid || | 1206 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) { |
1156 | inode->i_gid != fattr->gid) | 1207 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1157 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1208 | inode->i_mode = fattr->mode; |
1158 | 1209 | } | |
1159 | if (inode->i_nlink != fattr->nlink) { | 1210 | } |
1160 | invalid |= NFS_INO_INVALID_ATTR; | 1211 | if (fattr->valid & NFS_ATTR_FATTR_OWNER) { |
1161 | if (S_ISDIR(inode->i_mode)) | 1212 | if (inode->i_uid != fattr->uid) { |
1162 | invalid |= NFS_INO_INVALID_DATA; | 1213 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1214 | inode->i_uid = fattr->uid; | ||
1215 | } | ||
1216 | } | ||
1217 | if (fattr->valid & NFS_ATTR_FATTR_GROUP) { | ||
1218 | if (inode->i_gid != fattr->gid) { | ||
1219 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1220 | inode->i_gid = fattr->gid; | ||
1221 | } | ||
1163 | } | 1222 | } |
1164 | 1223 | ||
1165 | inode->i_mode = fattr->mode; | 1224 | if (fattr->valid & NFS_ATTR_FATTR_NLINK) { |
1166 | inode->i_nlink = fattr->nlink; | 1225 | if (inode->i_nlink != fattr->nlink) { |
1167 | inode->i_uid = fattr->uid; | 1226 | invalid |= NFS_INO_INVALID_ATTR; |
1168 | inode->i_gid = fattr->gid; | 1227 | if (S_ISDIR(inode->i_mode)) |
1228 | invalid |= NFS_INO_INVALID_DATA; | ||
1229 | inode->i_nlink = fattr->nlink; | ||
1230 | } | ||
1231 | } | ||
1169 | 1232 | ||
1170 | if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) { | 1233 | if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) { |
1171 | /* | 1234 | /* |
1172 | * report the blocks in 512byte units | 1235 | * report the blocks in 512byte units |
1173 | */ | 1236 | */ |
1174 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 1237 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
1175 | } else { | ||
1176 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
1177 | } | 1238 | } |
1239 | if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) | ||
1240 | inode->i_blocks = fattr->du.nfs2.blocks; | ||
1178 | 1241 | ||
1179 | /* Update attrtimeo value if we're out of the unstable period */ | 1242 | /* Update attrtimeo value if we're out of the unstable period */ |
1180 | if (invalid & NFS_INO_INVALID_ATTR) { | 1243 | if (invalid & NFS_INO_INVALID_ATTR) { |