From e26ae9f6f941a6c4bba9a6f32185053d9b0dc517 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 23 Sep 2008 17:28:41 -0400 Subject: [PATCH] --- yaml --- r: 115380 b: refs/heads/master c: a10ad17630024bf7aae8e7f18352f816ee483091 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/fs/nfs/inode.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 26023124d3d1..89f4e7b0d14d 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 870a5be8b92151332da65021b7b21104e9c1de07 +refs/heads/master: a10ad17630024bf7aae8e7f18352f816ee483091 diff --git a/trunk/fs/nfs/inode.c b/trunk/fs/nfs/inode.c index f189169348b1..8c514a1353c0 100644 --- a/trunk/fs/nfs/inode.c +++ b/trunk/fs/nfs/inode.c @@ -948,11 +948,49 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat return 0; } -static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) +static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr) { - struct nfs_inode *nfsi = NFS_I(inode); + return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; +} + +static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) +{ + return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); +} - if (time_after(fattr->time_start, nfsi->last_updated)) +/** + * nfs_inode_attrs_need_update - check if the inode attributes need updating + * @inode - pointer to inode + * @fattr - attributes + * + * Attempt to divine whether or not an RPC call reply carrying stale + * attributes got scheduled after another call carrying updated ones. + * + * To do so, the function first assumes that a more recent ctime means + * that the attributes in fattr are newer, however it also attempt to + * catch the case where ctime either didn't change, or went backwards + * (if someone reset the clock on the server) by looking at whether + * or not this RPC call was started after the inode was last updated. + * Note also the check for jiffy wraparound if the last_updated timestamp + * is later than 'jiffies'. + * + * The function returns 'true' if it thinks the attributes in 'fattr' are + * more recent than the ones cached in the inode. + * + */ +static int nfs_inode_attrs_need_update(const struct inode *inode, const struct nfs_fattr *fattr) +{ + const struct nfs_inode *nfsi = NFS_I(inode); + + return nfs_ctime_need_update(inode, fattr) || + nfs_size_need_update(inode, fattr) || + time_after(fattr->time_start, nfsi->last_updated) || + time_after(nfsi->last_updated, jiffies); +} + +static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) +{ + if (nfs_inode_attrs_need_update(inode, fattr)) return nfs_update_inode(inode, fattr); return nfs_check_inode_attributes(inode, fattr); }