Commit 20cf7d4e authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Fix handling of non-atomic change attrbute updates

If the change attribute update is declared to be non-atomic by the
server, or our cached value does not match the server's value before the
operation was performed, then we should declare the inode cache invalid.

On the other hand, if the change to the directory raced with a lookup or
getattr which already updated the change attribute, then optimise away
the revalidation.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 213bb584
......@@ -1205,12 +1205,12 @@ nfs4_update_changeattr_locked(struct inode *inode,
u64 change_attr = inode_peek_iversion_raw(inode);
cache_validity |= NFS_INO_INVALID_CTIME | NFS_INO_INVALID_MTIME;
if (S_ISDIR(inode->i_mode))
cache_validity |= NFS_INO_INVALID_DATA;
switch (NFS_SERVER(inode)->change_attr_type) {
case NFS4_CHANGE_TYPE_IS_UNDEFINED:
break;
case NFS4_CHANGE_TYPE_IS_TIME_METADATA:
if ((s64)(change_attr - cinfo->after) > 0)
if (cinfo->after == change_attr)
goto out;
break;
default:
......@@ -1218,24 +1218,21 @@ nfs4_update_changeattr_locked(struct inode *inode,
goto out;
}
if (cinfo->atomic && cinfo->before == change_attr) {
nfsi->attrtimeo_timestamp = jiffies;
} else {
if (S_ISDIR(inode->i_mode)) {
cache_validity |= NFS_INO_INVALID_DATA;
inode_set_iversion_raw(inode, cinfo->after);
if (!cinfo->atomic || cinfo->before != change_attr) {
if (S_ISDIR(inode->i_mode))
nfs_force_lookup_revalidate(inode);
} else {
if (!NFS_PROTO(inode)->have_delegation(inode,
FMODE_READ))
cache_validity |= NFS_INO_REVAL_PAGECACHE;
}
if (cinfo->before != change_attr)
cache_validity |= NFS_INO_INVALID_ACCESS |
NFS_INO_INVALID_ACL |
NFS_INO_INVALID_XATTR;
if (!NFS_PROTO(inode)->have_delegation(inode, FMODE_READ))
cache_validity |=
NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL |
NFS_INO_INVALID_SIZE | NFS_INO_INVALID_OTHER |
NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_NLINK |
NFS_INO_INVALID_MODE | NFS_INO_INVALID_XATTR |
NFS_INO_REVAL_PAGECACHE;
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
}
inode_set_iversion_raw(inode, cinfo->after);
nfsi->attrtimeo_timestamp = jiffies;
nfsi->read_cache_jiffies = timestamp;
nfsi->attr_gencount = nfs_inc_attr_generation_counter();
nfsi->cache_validity &= ~NFS_INO_INVALID_CHANGE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment