diff -prNu a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c --- a/fs/ecryptfs/inode.c 2012-01-05 07:55:44.000000000 +0800 +++ b/fs/ecryptfs/inode.c 2012-01-21 15:55:21.000000000 +0800 @@ -841,18 +841,6 @@ static int truncate_upper(struct dentry size_t num_zeros = (PAGE_CACHE_SIZE - (ia->ia_size & ~PAGE_CACHE_MASK)); - - /* - * XXX(truncate) this should really happen at the begginning - * of ->setattr. But the code is too messy to that as part - * of a larger patch. ecryptfs is also totally missing out - * on the inode_change_ok check at the beginning of - * ->setattr while would include this. - */ - rc = inode_newsize_ok(inode, ia->ia_size); - if (rc) - goto out; - if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { truncate_setsize(inode, ia->ia_size); lower_ia->ia_size = ia->ia_size; @@ -916,8 +904,14 @@ int ecryptfs_truncate(struct dentry *den { struct iattr ia = { .ia_valid = ATTR_SIZE, .ia_size = new_length }; struct iattr lower_ia = { .ia_valid = 0 }; + struct ecryptfs_crypt_stat *crypt_stat; int rc; - + + crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; + rc = inode_newsize_ok(ecryptfs_inode_to_lower(dentry->d_inode), new_length + ecryptfs_lower_header_size(crypt_stat)); + if (rc) + return rc; + rc = truncate_upper(dentry, &ia, &lower_ia); if (!rc && lower_ia.ia_valid & ATTR_SIZE) { struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); @@ -997,6 +991,15 @@ static int ecryptfs_setattr(struct dentr } } mutex_unlock(&crypt_stat->cs_mutex); + + rc = inode_change_ok(inode, ia); + if (rc) + goto out; + if (ia->ia_valid & ATTR_SIZE) + rc = inode_newsize_ok(lower_inode, ia->ia_size + ecryptfs_lower_header_size(crypt_stat)); + if (rc) + goto out; + if (S_ISREG(inode->i_mode)) { rc = filemap_write_and_wait(inode->i_mapping); if (rc)