aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-09-23 17:28:41 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-10-07 17:34:17 -0400
commita10ad17630024bf7aae8e7f18352f816ee483091 (patch)
treea290be6e6660766ceac3d06f022d2bc5d15a1602 /fs/nfs
parent870a5be8b92151332da65021b7b21104e9c1de07 (diff)
NFS: Fix the NFS attribute update
Currently nfs_refresh_inode() will only update the inode metadata if it sees that the RPC call that returned the nfs_fattr was started after the last update of the inode. This means that if we have parallel RPC calls to the same inode (when sending WRITE calls, for instance), we may often miss updates. This patch attempts to recover those missed updates by also accepting them if the ctime in the nfs_fattr is more recent than the inode's cached ctime. It also recovers the case where the file size has increased, but the ctime has not been updated due to limited ctime resolution. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-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}