aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/inode.c243
-rw-r--r--fs/nfs/nfs2xdr.c2
-rw-r--r--fs/nfs/nfs3xdr.c6
-rw-r--r--fs/nfs/nfs4xdr.c6
-rw-r--r--include/linux/nfs_xdr.h48
5 files changed, 202 insertions, 103 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
891static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr) 916static 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
896static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) 923static 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 }
1048out_noforce: 1088out_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) {
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 28bab67d1519..bea99992c302 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -136,7 +136,7 @@ xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
136 p = xdr_decode_time(p, &fattr->atime); 136 p = xdr_decode_time(p, &fattr->atime);
137 p = xdr_decode_time(p, &fattr->mtime); 137 p = xdr_decode_time(p, &fattr->mtime);
138 p = xdr_decode_time(p, &fattr->ctime); 138 p = xdr_decode_time(p, &fattr->ctime);
139 fattr->valid |= NFS_ATTR_FATTR; 139 fattr->valid |= NFS_ATTR_FATTR_V2;
140 fattr->rdev = new_decode_dev(rdev); 140 fattr->rdev = new_decode_dev(rdev);
141 if (fattr->type == NFCHR && rdev == NFS2_FIFO_DEV) { 141 if (fattr->type == NFCHR && rdev == NFS2_FIFO_DEV) {
142 fattr->type = NFFIFO; 142 fattr->type = NFFIFO;
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 6cdeacffde46..c0f7d02aced9 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -177,7 +177,7 @@ xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
177 p = xdr_decode_time3(p, &fattr->ctime); 177 p = xdr_decode_time3(p, &fattr->ctime);
178 178
179 /* Update the mode bits */ 179 /* Update the mode bits */
180 fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3); 180 fattr->valid |= NFS_ATTR_FATTR_V3;
181 return p; 181 return p;
182} 182}
183 183
@@ -233,7 +233,9 @@ xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
233 p = xdr_decode_hyper(p, &fattr->pre_size); 233 p = xdr_decode_hyper(p, &fattr->pre_size);
234 p = xdr_decode_time3(p, &fattr->pre_mtime); 234 p = xdr_decode_time3(p, &fattr->pre_mtime);
235 p = xdr_decode_time3(p, &fattr->pre_ctime); 235 p = xdr_decode_time3(p, &fattr->pre_ctime);
236 fattr->valid |= NFS_ATTR_WCC; 236 fattr->valid |= NFS_ATTR_FATTR_PRESIZE
237 | NFS_ATTR_FATTR_PREMTIME
238 | NFS_ATTR_FATTR_PRECTIME;
237 return p; 239 return p;
238} 240}
239 241
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 5f0ee3e2bd84..7d220da3db36 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -3012,7 +3012,7 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
3012 if ((status = decode_attr_type(xdr, bitmap, &type)) != 0) 3012 if ((status = decode_attr_type(xdr, bitmap, &type)) != 0)
3013 goto xdr_error; 3013 goto xdr_error;
3014 fattr->type = nfs_type2fmt[type].nfs2type; 3014 fattr->type = nfs_type2fmt[type].nfs2type;
3015 fmode = nfs_type2fmt[type].mode; 3015 fattr->mode = nfs_type2fmt[type].mode;
3016 3016
3017 if ((status = decode_attr_change(xdr, bitmap, &fattr->change_attr)) != 0) 3017 if ((status = decode_attr_change(xdr, bitmap, &fattr->change_attr)) != 0)
3018 goto xdr_error; 3018 goto xdr_error;
@@ -3026,7 +3026,7 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
3026 struct nfs4_fs_locations, 3026 struct nfs4_fs_locations,
3027 fattr))) != 0) 3027 fattr))) != 0)
3028 goto xdr_error; 3028 goto xdr_error;
3029 if ((status = decode_attr_mode(xdr, bitmap, &fattr->mode)) != 0) 3029 if ((status = decode_attr_mode(xdr, bitmap, &fmode)) != 0)
3030 goto xdr_error; 3030 goto xdr_error;
3031 fattr->mode |= fmode; 3031 fattr->mode |= fmode;
3032 if ((status = decode_attr_nlink(xdr, bitmap, &fattr->nlink)) != 0) 3032 if ((status = decode_attr_nlink(xdr, bitmap, &fattr->nlink)) != 0)
@@ -3050,7 +3050,7 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons
3050 if (fattr->fileid == 0 && fileid != 0) 3050 if (fattr->fileid == 0 && fileid != 0)
3051 fattr->fileid = fileid; 3051 fattr->fileid = fileid;
3052 if ((status = verify_attr_len(xdr, savep, attrlen)) == 0) 3052 if ((status = verify_attr_len(xdr, savep, attrlen)) == 0)
3053 fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4; 3053 fattr->valid = NFS_ATTR_FATTR_V4;
3054xdr_error: 3054xdr_error:
3055 dprintk("%s: xdr returned %d\n", __func__, -status); 3055 dprintk("%s: xdr returned %d\n", __func__, -status);
3056 return status; 3056 return status;
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 2e5f00066afd..b99295e07cdf 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -27,7 +27,7 @@ static inline int nfs_fsid_equal(const struct nfs_fsid *a, const struct nfs_fsid
27} 27}
28 28
29struct nfs_fattr { 29struct nfs_fattr {
30 unsigned short valid; /* which fields are valid */ 30 unsigned int valid; /* which fields are valid */
31 __u64 pre_size; /* pre_op_attr.size */ 31 __u64 pre_size; /* pre_op_attr.size */
32 struct timespec pre_mtime; /* pre_op_attr.mtime */ 32 struct timespec pre_mtime; /* pre_op_attr.mtime */
33 struct timespec pre_ctime; /* pre_op_attr.ctime */ 33 struct timespec pre_ctime; /* pre_op_attr.ctime */
@@ -59,12 +59,46 @@ struct nfs_fattr {
59 unsigned long gencount; 59 unsigned long gencount;
60}; 60};
61 61
62#define NFS_ATTR_WCC 0x0001 /* pre-op WCC data */ 62#define NFS_ATTR_FATTR_TYPE (1U << 0)
63#define NFS_ATTR_FATTR 0x0002 /* post-op attributes */ 63#define NFS_ATTR_FATTR_MODE (1U << 1)
64#define NFS_ATTR_FATTR_V3 0x0004 /* NFSv3 attributes */ 64#define NFS_ATTR_FATTR_NLINK (1U << 2)
65#define NFS_ATTR_FATTR_V4 0x0008 /* NFSv4 change attribute */ 65#define NFS_ATTR_FATTR_OWNER (1U << 3)
66#define NFS_ATTR_WCC_V4 0x0010 /* pre-op change attribute */ 66#define NFS_ATTR_FATTR_GROUP (1U << 4)
67#define NFS_ATTR_FATTR_V4_REFERRAL 0x0020 /* NFSv4 referral */ 67#define NFS_ATTR_FATTR_RDEV (1U << 5)
68#define NFS_ATTR_FATTR_SIZE (1U << 6)
69#define NFS_ATTR_FATTR_PRESIZE (1U << 7)
70#define NFS_ATTR_FATTR_BLOCKS_USED (1U << 8)
71#define NFS_ATTR_FATTR_SPACE_USED (1U << 9)
72#define NFS_ATTR_FATTR_FSID (1U << 10)
73#define NFS_ATTR_FATTR_FILEID (1U << 11)
74#define NFS_ATTR_FATTR_ATIME (1U << 12)
75#define NFS_ATTR_FATTR_MTIME (1U << 13)
76#define NFS_ATTR_FATTR_CTIME (1U << 14)
77#define NFS_ATTR_FATTR_PREMTIME (1U << 15)
78#define NFS_ATTR_FATTR_PRECTIME (1U << 16)
79#define NFS_ATTR_FATTR_CHANGE (1U << 17)
80#define NFS_ATTR_FATTR_PRECHANGE (1U << 18)
81#define NFS_ATTR_FATTR_V4_REFERRAL (1U << 19) /* NFSv4 referral */
82
83#define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \
84 | NFS_ATTR_FATTR_MODE \
85 | NFS_ATTR_FATTR_NLINK \
86 | NFS_ATTR_FATTR_OWNER \
87 | NFS_ATTR_FATTR_GROUP \
88 | NFS_ATTR_FATTR_RDEV \
89 | NFS_ATTR_FATTR_SIZE \
90 | NFS_ATTR_FATTR_FSID \
91 | NFS_ATTR_FATTR_FILEID \
92 | NFS_ATTR_FATTR_ATIME \
93 | NFS_ATTR_FATTR_MTIME \
94 | NFS_ATTR_FATTR_CTIME)
95#define NFS_ATTR_FATTR_V2 (NFS_ATTR_FATTR \
96 | NFS_ATTR_FATTR_BLOCKS_USED)
97#define NFS_ATTR_FATTR_V3 (NFS_ATTR_FATTR \
98 | NFS_ATTR_FATTR_SPACE_USED)
99#define NFS_ATTR_FATTR_V4 (NFS_ATTR_FATTR \
100 | NFS_ATTR_FATTR_SPACE_USED \
101 | NFS_ATTR_FATTR_CHANGE)
68 102
69/* 103/*
70 * Info on the file system 104 * Info on the file system