|
@@ -195,7 +195,10 @@ bool nfs_check_cache_invalid(struct inode *inode, unsigned long flags)
|
|
static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
|
|
static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
|
|
{
|
|
{
|
|
struct nfs_inode *nfsi = NFS_I(inode);
|
|
struct nfs_inode *nfsi = NFS_I(inode);
|
|
|
|
+ bool have_delegation = nfs_have_delegated_attributes(inode);
|
|
|
|
|
|
|
|
+ if (have_delegation)
|
|
|
|
+ flags &= ~(NFS_INO_INVALID_CHANGE|NFS_INO_REVAL_PAGECACHE);
|
|
if (inode->i_mapping->nrpages == 0)
|
|
if (inode->i_mapping->nrpages == 0)
|
|
flags &= ~NFS_INO_INVALID_DATA;
|
|
flags &= ~NFS_INO_INVALID_DATA;
|
|
nfsi->cache_validity |= flags;
|
|
nfsi->cache_validity |= flags;
|
|
@@ -447,7 +450,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
|
|
inode->i_mode = fattr->mode;
|
|
inode->i_mode = fattr->mode;
|
|
if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0
|
|
if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0
|
|
&& nfs_server_capable(inode, NFS_CAP_MODE))
|
|
&& nfs_server_capable(inode, NFS_CAP_MODE))
|
|
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR);
|
|
|
|
|
|
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
|
|
/* Why so? Because we want revalidate for devices/FIFOs, and
|
|
/* Why so? Because we want revalidate for devices/FIFOs, and
|
|
* that's precisely what we have in nfs_file_inode_operations.
|
|
* that's precisely what we have in nfs_file_inode_operations.
|
|
*/
|
|
*/
|
|
@@ -493,37 +496,35 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
|
|
if (fattr->valid & NFS_ATTR_FATTR_ATIME)
|
|
if (fattr->valid & NFS_ATTR_FATTR_ATIME)
|
|
inode->i_atime = fattr->atime;
|
|
inode->i_atime = fattr->atime;
|
|
else if (nfs_server_capable(inode, NFS_CAP_ATIME))
|
|
else if (nfs_server_capable(inode, NFS_CAP_ATIME))
|
|
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR);
|
|
|
|
|
|
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATIME);
|
|
if (fattr->valid & NFS_ATTR_FATTR_MTIME)
|
|
if (fattr->valid & NFS_ATTR_FATTR_MTIME)
|
|
inode->i_mtime = fattr->mtime;
|
|
inode->i_mtime = fattr->mtime;
|
|
else if (nfs_server_capable(inode, NFS_CAP_MTIME))
|
|
else if (nfs_server_capable(inode, NFS_CAP_MTIME))
|
|
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR);
|
|
|
|
|
|
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
|
|
if (fattr->valid & NFS_ATTR_FATTR_CTIME)
|
|
if (fattr->valid & NFS_ATTR_FATTR_CTIME)
|
|
inode->i_ctime = fattr->ctime;
|
|
inode->i_ctime = fattr->ctime;
|
|
else if (nfs_server_capable(inode, NFS_CAP_CTIME))
|
|
else if (nfs_server_capable(inode, NFS_CAP_CTIME))
|
|
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR);
|
|
|
|
|
|
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CTIME);
|
|
if (fattr->valid & NFS_ATTR_FATTR_CHANGE)
|
|
if (fattr->valid & NFS_ATTR_FATTR_CHANGE)
|
|
inode_set_iversion_raw(inode, fattr->change_attr);
|
|
inode_set_iversion_raw(inode, fattr->change_attr);
|
|
else
|
|
else
|
|
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR
|
|
|
|
- | NFS_INO_REVAL_PAGECACHE);
|
|
|
|
|
|
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE);
|
|
if (fattr->valid & NFS_ATTR_FATTR_SIZE)
|
|
if (fattr->valid & NFS_ATTR_FATTR_SIZE)
|
|
inode->i_size = nfs_size_to_loff_t(fattr->size);
|
|
inode->i_size = nfs_size_to_loff_t(fattr->size);
|
|
else
|
|
else
|
|
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR
|
|
|
|
- | NFS_INO_REVAL_PAGECACHE);
|
|
|
|
|
|
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_SIZE);
|
|
if (fattr->valid & NFS_ATTR_FATTR_NLINK)
|
|
if (fattr->valid & NFS_ATTR_FATTR_NLINK)
|
|
set_nlink(inode, fattr->nlink);
|
|
set_nlink(inode, fattr->nlink);
|
|
else if (nfs_server_capable(inode, NFS_CAP_NLINK))
|
|
else if (nfs_server_capable(inode, NFS_CAP_NLINK))
|
|
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR);
|
|
|
|
|
|
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
|
|
if (fattr->valid & NFS_ATTR_FATTR_OWNER)
|
|
if (fattr->valid & NFS_ATTR_FATTR_OWNER)
|
|
inode->i_uid = fattr->uid;
|
|
inode->i_uid = fattr->uid;
|
|
else if (nfs_server_capable(inode, NFS_CAP_OWNER))
|
|
else if (nfs_server_capable(inode, NFS_CAP_OWNER))
|
|
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR);
|
|
|
|
|
|
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
|
|
if (fattr->valid & NFS_ATTR_FATTR_GROUP)
|
|
if (fattr->valid & NFS_ATTR_FATTR_GROUP)
|
|
inode->i_gid = fattr->gid;
|
|
inode->i_gid = fattr->gid;
|
|
else if (nfs_server_capable(inode, NFS_CAP_OWNER_GROUP))
|
|
else if (nfs_server_capable(inode, NFS_CAP_OWNER_GROUP))
|
|
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR);
|
|
|
|
|
|
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
|
|
if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
|
|
if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
|
|
inode->i_blocks = fattr->du.nfs2.blocks;
|
|
inode->i_blocks = fattr->du.nfs2.blocks;
|
|
if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) {
|
|
if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) {
|
|
@@ -608,11 +609,6 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
- * Return any delegations if we're going to change ACLs
|
|
|
|
- */
|
|
|
|
- if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
|
|
|
|
- NFS_PROTO(inode)->return_delegation(inode);
|
|
|
|
error = NFS_PROTO(inode)->setattr(dentry, fattr, attr);
|
|
error = NFS_PROTO(inode)->setattr(dentry, fattr, attr);
|
|
if (error == 0)
|
|
if (error == 0)
|
|
error = nfs_refresh_inode(inode, fattr);
|
|
error = nfs_refresh_inode(inode, fattr);
|
|
@@ -645,6 +641,7 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset)
|
|
/* Optimisation */
|
|
/* Optimisation */
|
|
if (offset == 0)
|
|
if (offset == 0)
|
|
NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA;
|
|
NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA;
|
|
|
|
+ NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_SIZE;
|
|
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
spin_unlock(&inode->i_lock);
|
|
truncate_pagecache(inode, offset);
|
|
truncate_pagecache(inode, offset);
|
|
@@ -657,6 +654,7 @@ out:
|
|
* nfs_setattr_update_inode - Update inode metadata after a setattr call.
|
|
* nfs_setattr_update_inode - Update inode metadata after a setattr call.
|
|
* @inode: pointer to struct inode
|
|
* @inode: pointer to struct inode
|
|
* @attr: pointer to struct iattr
|
|
* @attr: pointer to struct iattr
|
|
|
|
+ * @fattr: pointer to struct nfs_fattr
|
|
*
|
|
*
|
|
* Note: we do this in the *proc.c in order to ensure that
|
|
* Note: we do this in the *proc.c in order to ensure that
|
|
* it works for things like exclusive creates too.
|
|
* it works for things like exclusive creates too.
|
|
@@ -669,6 +667,8 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
|
|
|
|
|
|
spin_lock(&inode->i_lock);
|
|
spin_lock(&inode->i_lock);
|
|
NFS_I(inode)->attr_gencount = fattr->gencount;
|
|
NFS_I(inode)->attr_gencount = fattr->gencount;
|
|
|
|
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
|
|
|
|
+ | NFS_INO_INVALID_CTIME);
|
|
if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
|
|
if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
|
|
if ((attr->ia_valid & ATTR_MODE) != 0) {
|
|
if ((attr->ia_valid & ATTR_MODE) != 0) {
|
|
int mode = attr->ia_mode & S_IALLUGO;
|
|
int mode = attr->ia_mode & S_IALLUGO;
|
|
@@ -683,13 +683,12 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
|
|
| NFS_INO_INVALID_ACL);
|
|
| NFS_INO_INVALID_ACL);
|
|
}
|
|
}
|
|
if ((attr->ia_valid & ATTR_SIZE) != 0) {
|
|
if ((attr->ia_valid & ATTR_SIZE) != 0) {
|
|
|
|
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
|
|
nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
|
|
nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
|
|
nfs_vmtruncate(inode, attr->ia_size);
|
|
nfs_vmtruncate(inode, attr->ia_size);
|
|
}
|
|
}
|
|
if (fattr->valid)
|
|
if (fattr->valid)
|
|
nfs_update_inode(inode, fattr);
|
|
nfs_update_inode(inode, fattr);
|
|
- else
|
|
|
|
- NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR;
|
|
|
|
spin_unlock(&inode->i_lock);
|
|
spin_unlock(&inode->i_lock);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(nfs_setattr_update_inode);
|
|
EXPORT_SYMBOL_GPL(nfs_setattr_update_inode);
|
|
@@ -1303,24 +1302,20 @@ static bool nfs_file_has_buffered_writers(struct nfs_inode *nfsi)
|
|
return nfs_file_has_writers(nfsi) && nfs_file_io_is_buffered(nfsi);
|
|
return nfs_file_has_writers(nfsi) && nfs_file_io_is_buffered(nfsi);
|
|
}
|
|
}
|
|
|
|
|
|
-static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
|
|
|
|
+static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
{
|
|
{
|
|
- unsigned long ret = 0;
|
|
|
|
-
|
|
|
|
if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE)
|
|
if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE)
|
|
&& (fattr->valid & NFS_ATTR_FATTR_CHANGE)
|
|
&& (fattr->valid & NFS_ATTR_FATTR_CHANGE)
|
|
&& inode_eq_iversion_raw(inode, fattr->pre_change_attr)) {
|
|
&& inode_eq_iversion_raw(inode, fattr->pre_change_attr)) {
|
|
inode_set_iversion_raw(inode, fattr->change_attr);
|
|
inode_set_iversion_raw(inode, fattr->change_attr);
|
|
if (S_ISDIR(inode->i_mode))
|
|
if (S_ISDIR(inode->i_mode))
|
|
nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA);
|
|
nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA);
|
|
- ret |= NFS_INO_INVALID_ATTR;
|
|
|
|
}
|
|
}
|
|
/* If we have atomic WCC data, we may update some attributes */
|
|
/* If we have atomic WCC data, we may update some attributes */
|
|
if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME)
|
|
if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME)
|
|
&& (fattr->valid & NFS_ATTR_FATTR_CTIME)
|
|
&& (fattr->valid & NFS_ATTR_FATTR_CTIME)
|
|
&& timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) {
|
|
&& timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) {
|
|
memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
|
|
memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
|
|
- ret |= NFS_INO_INVALID_ATTR;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME)
|
|
if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME)
|
|
@@ -1329,17 +1324,13 @@ static unsigned long nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr
|
|
memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
|
|
memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
|
|
if (S_ISDIR(inode->i_mode))
|
|
if (S_ISDIR(inode->i_mode))
|
|
nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA);
|
|
nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA);
|
|
- ret |= NFS_INO_INVALID_ATTR;
|
|
|
|
}
|
|
}
|
|
if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE)
|
|
if ((fattr->valid & NFS_ATTR_FATTR_PRESIZE)
|
|
&& (fattr->valid & NFS_ATTR_FATTR_SIZE)
|
|
&& (fattr->valid & NFS_ATTR_FATTR_SIZE)
|
|
&& i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size)
|
|
&& i_size_read(inode) == nfs_size_to_loff_t(fattr->pre_size)
|
|
&& !nfs_have_writebacks(inode)) {
|
|
&& !nfs_have_writebacks(inode)) {
|
|
i_size_write(inode, nfs_size_to_loff_t(fattr->size));
|
|
i_size_write(inode, nfs_size_to_loff_t(fattr->size));
|
|
- ret |= NFS_INO_INVALID_ATTR;
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
- return ret;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -1369,33 +1360,41 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
|
|
if (!nfs_file_has_buffered_writers(nfsi)) {
|
|
if (!nfs_file_has_buffered_writers(nfsi)) {
|
|
/* Verify a few of the more important attributes */
|
|
/* Verify a few of the more important attributes */
|
|
if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && !inode_eq_iversion_raw(inode, fattr->change_attr))
|
|
if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 && !inode_eq_iversion_raw(inode, fattr->change_attr))
|
|
- invalid |= NFS_INO_INVALID_ATTR | NFS_INO_REVAL_PAGECACHE;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_CHANGE
|
|
|
|
+ | NFS_INO_REVAL_PAGECACHE;
|
|
|
|
|
|
if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&inode->i_mtime, &fattr->mtime))
|
|
if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&inode->i_mtime, &fattr->mtime))
|
|
- invalid |= NFS_INO_INVALID_ATTR;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_MTIME;
|
|
|
|
|
|
if ((fattr->valid & NFS_ATTR_FATTR_CTIME) && !timespec_equal(&inode->i_ctime, &fattr->ctime))
|
|
if ((fattr->valid & NFS_ATTR_FATTR_CTIME) && !timespec_equal(&inode->i_ctime, &fattr->ctime))
|
|
- invalid |= NFS_INO_INVALID_ATTR;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_CTIME;
|
|
|
|
|
|
if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
|
|
if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
|
|
cur_size = i_size_read(inode);
|
|
cur_size = i_size_read(inode);
|
|
new_isize = nfs_size_to_loff_t(fattr->size);
|
|
new_isize = nfs_size_to_loff_t(fattr->size);
|
|
if (cur_size != new_isize)
|
|
if (cur_size != new_isize)
|
|
- invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_SIZE
|
|
|
|
+ | NFS_INO_REVAL_PAGECACHE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Have any file permissions changed? */
|
|
/* Have any file permissions changed? */
|
|
if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO))
|
|
if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO))
|
|
- invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_ACCESS
|
|
|
|
+ | NFS_INO_INVALID_ACL
|
|
|
|
+ | NFS_INO_INVALID_OTHER;
|
|
if ((fattr->valid & NFS_ATTR_FATTR_OWNER) && !uid_eq(inode->i_uid, fattr->uid))
|
|
if ((fattr->valid & NFS_ATTR_FATTR_OWNER) && !uid_eq(inode->i_uid, fattr->uid))
|
|
- invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_ACCESS
|
|
|
|
+ | NFS_INO_INVALID_ACL
|
|
|
|
+ | NFS_INO_INVALID_OTHER;
|
|
if ((fattr->valid & NFS_ATTR_FATTR_GROUP) && !gid_eq(inode->i_gid, fattr->gid))
|
|
if ((fattr->valid & NFS_ATTR_FATTR_GROUP) && !gid_eq(inode->i_gid, fattr->gid))
|
|
- invalid |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_ACCESS
|
|
|
|
+ | NFS_INO_INVALID_ACL
|
|
|
|
+ | NFS_INO_INVALID_OTHER;
|
|
|
|
|
|
/* Has the link count changed? */
|
|
/* Has the link count changed? */
|
|
if ((fattr->valid & NFS_ATTR_FATTR_NLINK) && inode->i_nlink != fattr->nlink)
|
|
if ((fattr->valid & NFS_ATTR_FATTR_NLINK) && inode->i_nlink != fattr->nlink)
|
|
- invalid |= NFS_INO_INVALID_ATTR;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_OTHER;
|
|
|
|
|
|
if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&inode->i_atime, &fattr->atime))
|
|
if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&inode->i_atime, &fattr->atime))
|
|
invalid |= NFS_INO_INVALID_ATIME;
|
|
invalid |= NFS_INO_INVALID_ATIME;
|
|
@@ -1597,10 +1596,9 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(nfs_refresh_inode);
|
|
EXPORT_SYMBOL_GPL(nfs_refresh_inode);
|
|
|
|
|
|
-static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
|
|
|
|
|
|
+static int nfs_post_op_update_inode_locked(struct inode *inode,
|
|
|
|
+ struct nfs_fattr *fattr, unsigned int invalid)
|
|
{
|
|
{
|
|
- unsigned long invalid = NFS_INO_INVALID_ATTR;
|
|
|
|
-
|
|
|
|
if (S_ISDIR(inode->i_mode))
|
|
if (S_ISDIR(inode->i_mode))
|
|
invalid |= NFS_INO_INVALID_DATA;
|
|
invalid |= NFS_INO_INVALID_DATA;
|
|
nfs_set_cache_invalid(inode, invalid);
|
|
nfs_set_cache_invalid(inode, invalid);
|
|
@@ -1629,7 +1627,9 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
|
|
|
|
spin_lock(&inode->i_lock);
|
|
spin_lock(&inode->i_lock);
|
|
nfs_fattr_set_barrier(fattr);
|
|
nfs_fattr_set_barrier(fattr);
|
|
- status = nfs_post_op_update_inode_locked(inode, fattr);
|
|
|
|
|
|
+ status = nfs_post_op_update_inode_locked(inode, fattr,
|
|
|
|
+ NFS_INO_INVALID_CHANGE
|
|
|
|
+ | NFS_INO_INVALID_CTIME);
|
|
spin_unlock(&inode->i_lock);
|
|
spin_unlock(&inode->i_lock);
|
|
|
|
|
|
return status;
|
|
return status;
|
|
@@ -1681,7 +1681,10 @@ int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fa
|
|
fattr->valid |= NFS_ATTR_FATTR_PRESIZE;
|
|
fattr->valid |= NFS_ATTR_FATTR_PRESIZE;
|
|
}
|
|
}
|
|
out_noforce:
|
|
out_noforce:
|
|
- status = nfs_post_op_update_inode_locked(inode, fattr);
|
|
|
|
|
|
+ status = nfs_post_op_update_inode_locked(inode, fattr,
|
|
|
|
+ NFS_INO_INVALID_CHANGE
|
|
|
|
+ | NFS_INO_INVALID_CTIME
|
|
|
|
+ | NFS_INO_INVALID_MTIME);
|
|
return status;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1789,7 +1792,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
| NFS_INO_REVAL_PAGECACHE);
|
|
| NFS_INO_REVAL_PAGECACHE);
|
|
|
|
|
|
/* Do atomic weak cache consistency updates */
|
|
/* Do atomic weak cache consistency updates */
|
|
- invalid |= nfs_wcc_update_inode(inode, fattr);
|
|
|
|
|
|
+ nfs_wcc_update_inode(inode, fattr);
|
|
|
|
|
|
if (pnfs_layoutcommit_outstanding(inode)) {
|
|
if (pnfs_layoutcommit_outstanding(inode)) {
|
|
nfsi->cache_validity |= save_cache_validity & NFS_INO_INVALID_ATTR;
|
|
nfsi->cache_validity |= save_cache_validity & NFS_INO_INVALID_ATTR;
|
|
@@ -1803,17 +1806,25 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
inode->i_sb->s_id, inode->i_ino);
|
|
inode->i_sb->s_id, inode->i_ino);
|
|
/* Could it be a race with writeback? */
|
|
/* Could it be a race with writeback? */
|
|
if (!have_writers) {
|
|
if (!have_writers) {
|
|
- invalid |= NFS_INO_INVALID_ATTR
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_CHANGE
|
|
| NFS_INO_INVALID_DATA
|
|
| NFS_INO_INVALID_DATA
|
|
| NFS_INO_INVALID_ACCESS
|
|
| NFS_INO_INVALID_ACCESS
|
|
| NFS_INO_INVALID_ACL;
|
|
| NFS_INO_INVALID_ACL;
|
|
|
|
+ /* Force revalidate of all attributes */
|
|
|
|
+ save_cache_validity |= NFS_INO_INVALID_CTIME
|
|
|
|
+ | NFS_INO_INVALID_MTIME
|
|
|
|
+ | NFS_INO_INVALID_SIZE
|
|
|
|
+ | NFS_INO_INVALID_OTHER;
|
|
if (S_ISDIR(inode->i_mode))
|
|
if (S_ISDIR(inode->i_mode))
|
|
nfs_force_lookup_revalidate(inode);
|
|
nfs_force_lookup_revalidate(inode);
|
|
}
|
|
}
|
|
inode_set_iversion_raw(inode, fattr->change_attr);
|
|
inode_set_iversion_raw(inode, fattr->change_attr);
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- nfsi->cache_validity |= save_cache_validity;
|
|
|
|
|
|
+ nfsi->cache_validity |= save_cache_validity &
|
|
|
|
+ (NFS_INO_INVALID_CHANGE
|
|
|
|
+ | NFS_INO_REVAL_PAGECACHE
|
|
|
|
+ | NFS_INO_REVAL_FORCED);
|
|
cache_revalidated = false;
|
|
cache_revalidated = false;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1821,7 +1832,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
|
|
memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
|
|
} else if (server->caps & NFS_CAP_MTIME) {
|
|
} else if (server->caps & NFS_CAP_MTIME) {
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
- (NFS_INO_INVALID_ATTR
|
|
|
|
|
|
+ (NFS_INO_INVALID_MTIME
|
|
| NFS_INO_REVAL_FORCED);
|
|
| NFS_INO_REVAL_FORCED);
|
|
cache_revalidated = false;
|
|
cache_revalidated = false;
|
|
}
|
|
}
|
|
@@ -1830,7 +1841,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
|
|
memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
|
|
} else if (server->caps & NFS_CAP_CTIME) {
|
|
} else if (server->caps & NFS_CAP_CTIME) {
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
- (NFS_INO_INVALID_ATTR
|
|
|
|
|
|
+ (NFS_INO_INVALID_CTIME
|
|
| NFS_INO_REVAL_FORCED);
|
|
| NFS_INO_REVAL_FORCED);
|
|
cache_revalidated = false;
|
|
cache_revalidated = false;
|
|
}
|
|
}
|
|
@@ -1845,7 +1856,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
if (!nfs_have_writebacks(inode) || new_isize > cur_isize) {
|
|
if (!nfs_have_writebacks(inode) || new_isize > cur_isize) {
|
|
i_size_write(inode, new_isize);
|
|
i_size_write(inode, new_isize);
|
|
if (!have_writers)
|
|
if (!have_writers)
|
|
- invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_DATA;
|
|
}
|
|
}
|
|
dprintk("NFS: isize change on server for file %s/%ld "
|
|
dprintk("NFS: isize change on server for file %s/%ld "
|
|
"(%Ld to %Ld)\n",
|
|
"(%Ld to %Ld)\n",
|
|
@@ -1856,7 +1867,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
- (NFS_INO_INVALID_ATTR
|
|
|
|
|
|
+ (NFS_INO_INVALID_SIZE
|
|
| NFS_INO_REVAL_PAGECACHE
|
|
| NFS_INO_REVAL_PAGECACHE
|
|
| NFS_INO_REVAL_FORCED);
|
|
| NFS_INO_REVAL_FORCED);
|
|
cache_revalidated = false;
|
|
cache_revalidated = false;
|
|
@@ -1877,55 +1888,61 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
umode_t newmode = inode->i_mode & S_IFMT;
|
|
umode_t newmode = inode->i_mode & S_IFMT;
|
|
newmode |= fattr->mode & S_IALLUGO;
|
|
newmode |= fattr->mode & S_IALLUGO;
|
|
inode->i_mode = newmode;
|
|
inode->i_mode = newmode;
|
|
- invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_ACCESS
|
|
|
|
+ | NFS_INO_INVALID_ACL
|
|
|
|
+ | NFS_INO_INVALID_OTHER;
|
|
}
|
|
}
|
|
} else if (server->caps & NFS_CAP_MODE) {
|
|
} else if (server->caps & NFS_CAP_MODE) {
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
- (NFS_INO_INVALID_ATTR
|
|
|
|
- | NFS_INO_INVALID_ACCESS
|
|
|
|
|
|
+ (NFS_INO_INVALID_ACCESS
|
|
| NFS_INO_INVALID_ACL
|
|
| NFS_INO_INVALID_ACL
|
|
|
|
+ | NFS_INO_INVALID_OTHER
|
|
| NFS_INO_REVAL_FORCED);
|
|
| NFS_INO_REVAL_FORCED);
|
|
cache_revalidated = false;
|
|
cache_revalidated = false;
|
|
}
|
|
}
|
|
|
|
|
|
if (fattr->valid & NFS_ATTR_FATTR_OWNER) {
|
|
if (fattr->valid & NFS_ATTR_FATTR_OWNER) {
|
|
if (!uid_eq(inode->i_uid, fattr->uid)) {
|
|
if (!uid_eq(inode->i_uid, fattr->uid)) {
|
|
- invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_ACCESS
|
|
|
|
+ | NFS_INO_INVALID_ACL
|
|
|
|
+ | NFS_INO_INVALID_OTHER;
|
|
inode->i_uid = fattr->uid;
|
|
inode->i_uid = fattr->uid;
|
|
}
|
|
}
|
|
} else if (server->caps & NFS_CAP_OWNER) {
|
|
} else if (server->caps & NFS_CAP_OWNER) {
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
- (NFS_INO_INVALID_ATTR
|
|
|
|
- | NFS_INO_INVALID_ACCESS
|
|
|
|
|
|
+ (NFS_INO_INVALID_ACCESS
|
|
| NFS_INO_INVALID_ACL
|
|
| NFS_INO_INVALID_ACL
|
|
|
|
+ | NFS_INO_INVALID_OTHER
|
|
| NFS_INO_REVAL_FORCED);
|
|
| NFS_INO_REVAL_FORCED);
|
|
cache_revalidated = false;
|
|
cache_revalidated = false;
|
|
}
|
|
}
|
|
|
|
|
|
if (fattr->valid & NFS_ATTR_FATTR_GROUP) {
|
|
if (fattr->valid & NFS_ATTR_FATTR_GROUP) {
|
|
if (!gid_eq(inode->i_gid, fattr->gid)) {
|
|
if (!gid_eq(inode->i_gid, fattr->gid)) {
|
|
- invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_ACCESS
|
|
|
|
+ | NFS_INO_INVALID_ACL
|
|
|
|
+ | NFS_INO_INVALID_OTHER;
|
|
inode->i_gid = fattr->gid;
|
|
inode->i_gid = fattr->gid;
|
|
}
|
|
}
|
|
} else if (server->caps & NFS_CAP_OWNER_GROUP) {
|
|
} else if (server->caps & NFS_CAP_OWNER_GROUP) {
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
- (NFS_INO_INVALID_ATTR
|
|
|
|
- | NFS_INO_INVALID_ACCESS
|
|
|
|
|
|
+ (NFS_INO_INVALID_ACCESS
|
|
| NFS_INO_INVALID_ACL
|
|
| NFS_INO_INVALID_ACL
|
|
|
|
+ | NFS_INO_INVALID_OTHER
|
|
| NFS_INO_REVAL_FORCED);
|
|
| NFS_INO_REVAL_FORCED);
|
|
cache_revalidated = false;
|
|
cache_revalidated = false;
|
|
}
|
|
}
|
|
|
|
|
|
if (fattr->valid & NFS_ATTR_FATTR_NLINK) {
|
|
if (fattr->valid & NFS_ATTR_FATTR_NLINK) {
|
|
if (inode->i_nlink != fattr->nlink) {
|
|
if (inode->i_nlink != fattr->nlink) {
|
|
- invalid |= NFS_INO_INVALID_ATTR;
|
|
|
|
|
|
+ invalid |= NFS_INO_INVALID_OTHER;
|
|
if (S_ISDIR(inode->i_mode))
|
|
if (S_ISDIR(inode->i_mode))
|
|
invalid |= NFS_INO_INVALID_DATA;
|
|
invalid |= NFS_INO_INVALID_DATA;
|
|
set_nlink(inode, fattr->nlink);
|
|
set_nlink(inode, fattr->nlink);
|
|
}
|
|
}
|
|
} else if (server->caps & NFS_CAP_NLINK) {
|
|
} else if (server->caps & NFS_CAP_NLINK) {
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
nfsi->cache_validity |= save_cache_validity &
|
|
- (NFS_INO_INVALID_ATTR
|
|
|
|
|
|
+ (NFS_INO_INVALID_OTHER
|
|
| NFS_INO_REVAL_FORCED);
|
|
| NFS_INO_REVAL_FORCED);
|
|
cache_revalidated = false;
|
|
cache_revalidated = false;
|
|
}
|
|
}
|
|
@@ -1942,6 +1959,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
|
|
|
|
/* Update attrtimeo value if we're out of the unstable period */
|
|
/* Update attrtimeo value if we're out of the unstable period */
|
|
if (invalid & NFS_INO_INVALID_ATTR) {
|
|
if (invalid & NFS_INO_INVALID_ATTR) {
|
|
|
|
+ invalid &= ~NFS_INO_INVALID_ATTR;
|
|
nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
|
|
nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
|
|
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
|
|
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
|
|
nfsi->attrtimeo_timestamp = now;
|
|
nfsi->attrtimeo_timestamp = now;
|
|
@@ -1962,10 +1980,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
nfsi->attr_gencount = fattr->gencount;
|
|
nfsi->attr_gencount = fattr->gencount;
|
|
}
|
|
}
|
|
|
|
|
|
- /* Don't declare attrcache up to date if there were no attrs! */
|
|
|
|
- if (cache_revalidated)
|
|
|
|
- invalid &= ~NFS_INO_INVALID_ATTR;
|
|
|
|
-
|
|
|
|
/* Don't invalidate the data if we were to blame */
|
|
/* Don't invalidate the data if we were to blame */
|
|
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
|
|
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
|
|
|| S_ISLNK(inode->i_mode)))
|
|
|| S_ISLNK(inode->i_mode)))
|