diff options
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index d83498282837..af53c02f473b 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -65,13 +65,18 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr) | |||
65 | 65 | ||
66 | int nfs_write_inode(struct inode *inode, int sync) | 66 | int nfs_write_inode(struct inode *inode, int sync) |
67 | { | 67 | { |
68 | int flags = sync ? FLUSH_SYNC : 0; | ||
69 | int ret; | 68 | int ret; |
70 | 69 | ||
71 | ret = nfs_commit_inode(inode, flags); | 70 | if (sync) { |
72 | if (ret < 0) | 71 | ret = filemap_fdatawait(inode->i_mapping); |
73 | return ret; | 72 | if (ret == 0) |
74 | return 0; | 73 | ret = nfs_commit_inode(inode, FLUSH_SYNC); |
74 | } else | ||
75 | ret = nfs_commit_inode(inode, 0); | ||
76 | if (ret >= 0) | ||
77 | return 0; | ||
78 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | ||
79 | return ret; | ||
75 | } | 80 | } |
76 | 81 | ||
77 | void nfs_clear_inode(struct inode *inode) | 82 | void nfs_clear_inode(struct inode *inode) |
@@ -235,6 +240,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
235 | 240 | ||
236 | if (inode->i_state & I_NEW) { | 241 | if (inode->i_state & I_NEW) { |
237 | struct nfs_inode *nfsi = NFS_I(inode); | 242 | struct nfs_inode *nfsi = NFS_I(inode); |
243 | unsigned long now = jiffies; | ||
238 | 244 | ||
239 | /* We set i_ino for the few things that still rely on it, | 245 | /* We set i_ino for the few things that still rely on it, |
240 | * such as stat(2) */ | 246 | * such as stat(2) */ |
@@ -271,7 +277,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
271 | init_special_inode(inode, inode->i_mode, fattr->rdev); | 277 | init_special_inode(inode, inode->i_mode, fattr->rdev); |
272 | 278 | ||
273 | nfsi->read_cache_jiffies = fattr->time_start; | 279 | nfsi->read_cache_jiffies = fattr->time_start; |
274 | nfsi->last_updated = jiffies; | 280 | nfsi->last_updated = now; |
281 | nfsi->cache_change_attribute = now; | ||
275 | inode->i_atime = fattr->atime; | 282 | inode->i_atime = fattr->atime; |
276 | inode->i_mtime = fattr->mtime; | 283 | inode->i_mtime = fattr->mtime; |
277 | inode->i_ctime = fattr->ctime; | 284 | inode->i_ctime = fattr->ctime; |
@@ -290,7 +297,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
290 | inode->i_blocks = fattr->du.nfs2.blocks; | 297 | inode->i_blocks = fattr->du.nfs2.blocks; |
291 | } | 298 | } |
292 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 299 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
293 | nfsi->attrtimeo_timestamp = jiffies; | 300 | nfsi->attrtimeo_timestamp = now; |
294 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | 301 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
295 | nfsi->access_cache = RB_ROOT; | 302 | nfsi->access_cache = RB_ROOT; |
296 | 303 | ||
@@ -783,20 +790,21 @@ void nfs_end_data_update(struct inode *inode) | |||
783 | static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 790 | static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
784 | { | 791 | { |
785 | struct nfs_inode *nfsi = NFS_I(inode); | 792 | struct nfs_inode *nfsi = NFS_I(inode); |
793 | unsigned long now = jiffies; | ||
786 | 794 | ||
787 | /* If we have atomic WCC data, we may update some attributes */ | 795 | /* If we have atomic WCC data, we may update some attributes */ |
788 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { | 796 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { |
789 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) { | 797 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) { |
790 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 798 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
791 | nfsi->cache_change_attribute = jiffies; | 799 | nfsi->cache_change_attribute = now; |
792 | } | 800 | } |
793 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | 801 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { |
794 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 802 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
795 | nfsi->cache_change_attribute = jiffies; | 803 | nfsi->cache_change_attribute = now; |
796 | } | 804 | } |
797 | if (inode->i_size == fattr->pre_size && nfsi->npages == 0) { | 805 | if (inode->i_size == fattr->pre_size && nfsi->npages == 0) { |
798 | inode->i_size = fattr->size; | 806 | inode->i_size = fattr->size; |
799 | nfsi->cache_change_attribute = jiffies; | 807 | nfsi->cache_change_attribute = now; |
800 | } | 808 | } |
801 | } | 809 | } |
802 | } | 810 | } |
@@ -934,6 +942,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
934 | struct nfs_inode *nfsi = NFS_I(inode); | 942 | struct nfs_inode *nfsi = NFS_I(inode); |
935 | loff_t cur_isize, new_isize; | 943 | loff_t cur_isize, new_isize; |
936 | unsigned int invalid = 0; | 944 | unsigned int invalid = 0; |
945 | unsigned long now = jiffies; | ||
937 | int data_stable; | 946 | int data_stable; |
938 | 947 | ||
939 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", | 948 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", |
@@ -959,7 +968,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
959 | * Update the read time so we don't revalidate too often. | 968 | * Update the read time so we don't revalidate too often. |
960 | */ | 969 | */ |
961 | nfsi->read_cache_jiffies = fattr->time_start; | 970 | nfsi->read_cache_jiffies = fattr->time_start; |
962 | nfsi->last_updated = jiffies; | 971 | nfsi->last_updated = now; |
972 | |||
973 | /* Fix a wraparound issue with nfsi->cache_change_attribute */ | ||
974 | if (time_before(now, nfsi->cache_change_attribute)) | ||
975 | nfsi->cache_change_attribute = now - 600*HZ; | ||
963 | 976 | ||
964 | /* Are we racing with known updates of the metadata on the server? */ | 977 | /* Are we racing with known updates of the metadata on the server? */ |
965 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); | 978 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); |
@@ -985,7 +998,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
985 | inode->i_size = new_isize; | 998 | inode->i_size = new_isize; |
986 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 999 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
987 | } | 1000 | } |
988 | nfsi->cache_change_attribute = jiffies; | 1001 | nfsi->cache_change_attribute = now; |
989 | dprintk("NFS: isize change on server for file %s/%ld\n", | 1002 | dprintk("NFS: isize change on server for file %s/%ld\n", |
990 | inode->i_sb->s_id, inode->i_ino); | 1003 | inode->i_sb->s_id, inode->i_ino); |
991 | } | 1004 | } |
@@ -996,14 +1009,14 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
996 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1009 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
997 | inode->i_sb->s_id, inode->i_ino); | 1010 | inode->i_sb->s_id, inode->i_ino); |
998 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1011 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
999 | nfsi->cache_change_attribute = jiffies; | 1012 | nfsi->cache_change_attribute = now; |
1000 | } | 1013 | } |
1001 | 1014 | ||
1002 | /* If ctime has changed we should definitely clear access+acl caches */ | 1015 | /* If ctime has changed we should definitely clear access+acl caches */ |
1003 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { | 1016 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { |
1004 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1017 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1005 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 1018 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
1006 | nfsi->cache_change_attribute = jiffies; | 1019 | nfsi->cache_change_attribute = now; |
1007 | } | 1020 | } |
1008 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); | 1021 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); |
1009 | 1022 | ||
@@ -1032,18 +1045,18 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1032 | inode->i_sb->s_id, inode->i_ino); | 1045 | inode->i_sb->s_id, inode->i_ino); |
1033 | nfsi->change_attr = fattr->change_attr; | 1046 | nfsi->change_attr = fattr->change_attr; |
1034 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1047 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1035 | nfsi->cache_change_attribute = jiffies; | 1048 | nfsi->cache_change_attribute = now; |
1036 | } | 1049 | } |
1037 | 1050 | ||
1038 | /* Update attrtimeo value if we're out of the unstable period */ | 1051 | /* Update attrtimeo value if we're out of the unstable period */ |
1039 | if (invalid & NFS_INO_INVALID_ATTR) { | 1052 | if (invalid & NFS_INO_INVALID_ATTR) { |
1040 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1053 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
1041 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1054 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
1042 | nfsi->attrtimeo_timestamp = jiffies; | 1055 | nfsi->attrtimeo_timestamp = now; |
1043 | } else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { | 1056 | } else if (time_after(now, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { |
1044 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) | 1057 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) |
1045 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | 1058 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); |
1046 | nfsi->attrtimeo_timestamp = jiffies; | 1059 | nfsi->attrtimeo_timestamp = now; |
1047 | } | 1060 | } |
1048 | /* Don't invalidate the data if we were to blame */ | 1061 | /* Don't invalidate the data if we were to blame */ |
1049 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1062 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
@@ -1122,7 +1135,6 @@ struct inode *nfs_alloc_inode(struct super_block *sb) | |||
1122 | return NULL; | 1135 | return NULL; |
1123 | nfsi->flags = 0UL; | 1136 | nfsi->flags = 0UL; |
1124 | nfsi->cache_validity = 0UL; | 1137 | nfsi->cache_validity = 0UL; |
1125 | nfsi->cache_change_attribute = jiffies; | ||
1126 | #ifdef CONFIG_NFS_V3_ACL | 1138 | #ifdef CONFIG_NFS_V3_ACL |
1127 | nfsi->acl_access = ERR_PTR(-EAGAIN); | 1139 | nfsi->acl_access = ERR_PTR(-EAGAIN); |
1128 | nfsi->acl_default = ERR_PTR(-EAGAIN); | 1140 | nfsi->acl_default = ERR_PTR(-EAGAIN); |