diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-03-11 14:10:24 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-03-11 14:10:24 -0400 |
commit | 9e6e70f8d8b6698e0017c56b86525aabe9c7cd4c (patch) | |
tree | 3364c61dc3fdb1cc69b18e0cf16947abc49c0be5 /fs/nfs | |
parent | 78f945f88ef83dcc7c962614a080e0a9a2db5889 (diff) |
NFSv4: Support NFSv4 optional attributes in the struct nfs_fattr
Currently, filling struct nfs_fattr is more or less an all or nothing
operation, since NFSv2 and NFSv3 have only mandatory attributes.
In NFSv4, some attributes are optional, and so we may simply not be able to
fill in those fields. Furthermore, NFSv4 allows you to specify which
attributes you are interested in retrieving, thus permitting you to
optimise away retrieval of attributes that you know will no change...
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/inode.c | 243 | ||||
-rw-r--r-- | fs/nfs/nfs2xdr.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs3xdr.c | 6 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 6 |
4 files changed, 161 insertions, 96 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) { |
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; |
3054 | xdr_error: | 3054 | xdr_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; |