diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-02-05 17:26:28 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-02-13 01:40:22 -0500 |
commit | 3e7d950a528454ad749a264feef3c8bad3faa108 (patch) | |
tree | f78795bde4128ca1da658e6cc3f4216f5c999276 /fs/nfs/inode.c | |
parent | ebf4d8ec02d8a13e1cbbda6fe746f80f3a4ca773 (diff) |
NFS: Fix a wraparound issue with nfsi->cache_change_attribute
Fix wraparound issue with nfsi->cache_change_attribute. If it is found
to lie in the future, then update it to lie in the past. Patch based on
a suggestion by Neil Brown.
..and minor micro-optimisation: avoid reading 'jiffies' more than once in
nfs_update_inode().
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r-- | fs/nfs/inode.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 4ef454763886..93269c3dd0f3 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -939,6 +939,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
939 | struct nfs_inode *nfsi = NFS_I(inode); | 939 | struct nfs_inode *nfsi = NFS_I(inode); |
940 | loff_t cur_isize, new_isize; | 940 | loff_t cur_isize, new_isize; |
941 | unsigned int invalid = 0; | 941 | unsigned int invalid = 0; |
942 | unsigned long now = jiffies; | ||
942 | int data_stable; | 943 | int data_stable; |
943 | 944 | ||
944 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", | 945 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", |
@@ -964,7 +965,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
964 | * Update the read time so we don't revalidate too often. | 965 | * Update the read time so we don't revalidate too often. |
965 | */ | 966 | */ |
966 | nfsi->read_cache_jiffies = fattr->time_start; | 967 | nfsi->read_cache_jiffies = fattr->time_start; |
967 | nfsi->last_updated = jiffies; | 968 | nfsi->last_updated = now; |
969 | |||
970 | /* Fix a wraparound issue with nfsi->cache_change_attribute */ | ||
971 | if (time_before(now, nfsi->cache_change_attribute)) | ||
972 | nfsi->cache_change_attribute = now - 600*HZ; | ||
968 | 973 | ||
969 | /* Are we racing with known updates of the metadata on the server? */ | 974 | /* Are we racing with known updates of the metadata on the server? */ |
970 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); | 975 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); |
@@ -990,7 +995,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
990 | inode->i_size = new_isize; | 995 | inode->i_size = new_isize; |
991 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 996 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
992 | } | 997 | } |
993 | nfsi->cache_change_attribute = jiffies; | 998 | nfsi->cache_change_attribute = now; |
994 | dprintk("NFS: isize change on server for file %s/%ld\n", | 999 | dprintk("NFS: isize change on server for file %s/%ld\n", |
995 | inode->i_sb->s_id, inode->i_ino); | 1000 | inode->i_sb->s_id, inode->i_ino); |
996 | } | 1001 | } |
@@ -1001,14 +1006,14 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1001 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1006 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
1002 | inode->i_sb->s_id, inode->i_ino); | 1007 | inode->i_sb->s_id, inode->i_ino); |
1003 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1008 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1004 | nfsi->cache_change_attribute = jiffies; | 1009 | nfsi->cache_change_attribute = now; |
1005 | } | 1010 | } |
1006 | 1011 | ||
1007 | /* If ctime has changed we should definitely clear access+acl caches */ | 1012 | /* If ctime has changed we should definitely clear access+acl caches */ |
1008 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { | 1013 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { |
1009 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1014 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1010 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 1015 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
1011 | nfsi->cache_change_attribute = jiffies; | 1016 | nfsi->cache_change_attribute = now; |
1012 | } | 1017 | } |
1013 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); | 1018 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); |
1014 | 1019 | ||
@@ -1037,18 +1042,18 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1037 | inode->i_sb->s_id, inode->i_ino); | 1042 | inode->i_sb->s_id, inode->i_ino); |
1038 | nfsi->change_attr = fattr->change_attr; | 1043 | nfsi->change_attr = fattr->change_attr; |
1039 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1044 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1040 | nfsi->cache_change_attribute = jiffies; | 1045 | nfsi->cache_change_attribute = now; |
1041 | } | 1046 | } |
1042 | 1047 | ||
1043 | /* Update attrtimeo value if we're out of the unstable period */ | 1048 | /* Update attrtimeo value if we're out of the unstable period */ |
1044 | if (invalid & NFS_INO_INVALID_ATTR) { | 1049 | if (invalid & NFS_INO_INVALID_ATTR) { |
1045 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1050 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
1046 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1051 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
1047 | nfsi->attrtimeo_timestamp = jiffies; | 1052 | nfsi->attrtimeo_timestamp = now; |
1048 | } else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { | 1053 | } else if (time_after(now, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { |
1049 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) | 1054 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) |
1050 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | 1055 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); |
1051 | nfsi->attrtimeo_timestamp = jiffies; | 1056 | nfsi->attrtimeo_timestamp = now; |
1052 | } | 1057 | } |
1053 | /* Don't invalidate the data if we were to blame */ | 1058 | /* Don't invalidate the data if we were to blame */ |
1054 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1059 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |