aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/inode.c44
1 files changed, 41 insertions, 3 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index f189169348b1..8c514a1353c0 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -948,11 +948,49 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
948 return 0; 948 return 0;
949} 949}
950 950
951static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) 951static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr)
952{ 952{
953 struct nfs_inode *nfsi = NFS_I(inode); 953 return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0;
954}
955
956static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr)
957{
958 return nfs_size_to_loff_t(fattr->size) > i_size_read(inode);
959}
954 960
955 if (time_after(fattr->time_start, nfsi->last_updated)) 961/**
962 * nfs_inode_attrs_need_update - check if the inode attributes need updating
963 * @inode - pointer to inode
964 * @fattr - attributes
965 *
966 * Attempt to divine whether or not an RPC call reply carrying stale
967 * attributes got scheduled after another call carrying updated ones.
968 *
969 * To do so, the function first assumes that a more recent ctime means
970 * that the attributes in fattr are newer, however it also attempt to
971 * catch the case where ctime either didn't change, or went backwards
972 * (if someone reset the clock on the server) by looking at whether
973 * or not this RPC call was started after the inode was last updated.
974 * Note also the check for jiffy wraparound if the last_updated timestamp
975 * is later than 'jiffies'.
976 *
977 * The function returns 'true' if it thinks the attributes in 'fattr' are
978 * more recent than the ones cached in the inode.
979 *
980 */
981static int nfs_inode_attrs_need_update(const struct inode *inode, const struct nfs_fattr *fattr)
982{
983 const struct nfs_inode *nfsi = NFS_I(inode);
984
985 return nfs_ctime_need_update(inode, fattr) ||
986 nfs_size_need_update(inode, fattr) ||
987 time_after(fattr->time_start, nfsi->last_updated) ||
988 time_after(nfsi->last_updated, jiffies);
989}
990
991static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
992{
993 if (nfs_inode_attrs_need_update(inode, fattr))
956 return nfs_update_inode(inode, fattr); 994 return nfs_update_inode(inode, fattr);
957 return nfs_check_inode_attributes(inode, fattr); 995 return nfs_check_inode_attributes(inode, fattr);
958} 996}