|
@@ -556,6 +556,7 @@ EXPORT_SYMBOL_GPL(nfs_setattr);
|
|
|
* This is a copy of the common vmtruncate, but with the locking
|
|
|
* corrected to take into account the fact that NFS requires
|
|
|
* inode->i_size to be updated under the inode->i_lock.
|
|
|
+ * Note: must be called with inode->i_lock held!
|
|
|
*/
|
|
|
static int nfs_vmtruncate(struct inode * inode, loff_t offset)
|
|
|
{
|
|
@@ -565,14 +566,14 @@ static int nfs_vmtruncate(struct inode * inode, loff_t offset)
|
|
|
if (err)
|
|
|
goto out;
|
|
|
|
|
|
- spin_lock(&inode->i_lock);
|
|
|
i_size_write(inode, offset);
|
|
|
/* Optimisation */
|
|
|
if (offset == 0)
|
|
|
NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_DATA;
|
|
|
- spin_unlock(&inode->i_lock);
|
|
|
|
|
|
+ spin_unlock(&inode->i_lock);
|
|
|
truncate_pagecache(inode, offset);
|
|
|
+ spin_lock(&inode->i_lock);
|
|
|
out:
|
|
|
return err;
|
|
|
}
|
|
@@ -585,10 +586,15 @@ out:
|
|
|
* Note: we do this in the *proc.c in order to ensure that
|
|
|
* it works for things like exclusive creates too.
|
|
|
*/
|
|
|
-void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
|
|
|
+void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
|
|
|
+ struct nfs_fattr *fattr)
|
|
|
{
|
|
|
+ /* Barrier: bump the attribute generation count. */
|
|
|
+ nfs_fattr_set_barrier(fattr);
|
|
|
+
|
|
|
+ spin_lock(&inode->i_lock);
|
|
|
+ NFS_I(inode)->attr_gencount = fattr->gencount;
|
|
|
if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
|
|
|
- spin_lock(&inode->i_lock);
|
|
|
if ((attr->ia_valid & ATTR_MODE) != 0) {
|
|
|
int mode = attr->ia_mode & S_IALLUGO;
|
|
|
mode |= inode->i_mode & ~S_IALLUGO;
|
|
@@ -600,12 +606,13 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr)
|
|
|
inode->i_gid = attr->ia_gid;
|
|
|
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS
|
|
|
| NFS_INO_INVALID_ACL);
|
|
|
- spin_unlock(&inode->i_lock);
|
|
|
}
|
|
|
if ((attr->ia_valid & ATTR_SIZE) != 0) {
|
|
|
nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
|
|
|
nfs_vmtruncate(inode, attr->ia_size);
|
|
|
}
|
|
|
+ nfs_update_inode(inode, fattr);
|
|
|
+ spin_unlock(&inode->i_lock);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(nfs_setattr_update_inode);
|
|
|
|