Commit 1e829880 authored by Nick Piggin's avatar Nick Piggin Committed by James Toy

Signed-off-by: Nick Piggin <npiggin@suse.de>

Cc: Christoph Hellwig <hch@lst.de>
Acked-by: default avatarHugh Dickins <hugh.dickins@tiscali.co.uk>
Cc: Jan Kara <jack@suse.cz>
Cc: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Cc: Chris Mason <chris.mason@oracle.com>
Cc: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: Trond Myklebust <trond.myklebust@fys.uio.no>
Cc: Steven French <sfrench@us.ibm.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent f4b723e8
...@@ -730,10 +730,11 @@ done2: ...@@ -730,10 +730,11 @@ done2:
if (inode->i_mapping->nrpages && (info->flags & SHMEM_PAGEIN)) { if (inode->i_mapping->nrpages && (info->flags & SHMEM_PAGEIN)) {
/* /*
* Call truncate_inode_pages again: racing shmem_unuse_inode * Call truncate_inode_pages again: racing shmem_unuse_inode
* may have swizzled a page in from swap since vmtruncate or * may have swizzled a page in from swap since
* generic_delete_inode did it, before we lowered next_index. * truncate_pagecache or generic_delete_inode did it, before we
* Also, though shmem_getpage checks i_size before adding to * lowered next_index. Also, though shmem_getpage checks
* cache, no recheck after: so fix the narrow window there too. * i_size before adding to cache, no recheck after: so fix the
* narrow window there too.
* *
* Recalling truncate_inode_pages_range and unmap_mapping_range * Recalling truncate_inode_pages_range and unmap_mapping_range
* every time for punch_hole (which never got a chance to clear * every time for punch_hole (which never got a chance to clear
...@@ -763,19 +764,16 @@ done2: ...@@ -763,19 +764,16 @@ done2:
} }
} }
static void shmem_truncate(struct inode *inode)
{
shmem_truncate_range(inode, inode->i_size, (loff_t)-1);
}
static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct page *page = NULL;
int error; int error;
if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
if (attr->ia_size < inode->i_size) { loff_t newsize = attr->ia_size;
struct page *page = NULL;
if (newsize < inode->i_size) {
/* /*
* If truncating down to a partial page, then * If truncating down to a partial page, then
* if that page is already allocated, hold it * if that page is already allocated, hold it
...@@ -783,9 +781,9 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) ...@@ -783,9 +781,9 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
* truncate_partial_page cannnot miss it were * truncate_partial_page cannnot miss it were
* it assigned to swap. * it assigned to swap.
*/ */
if (attr->ia_size & (PAGE_CACHE_SIZE-1)) { if (newsize & (PAGE_CACHE_SIZE-1)) {
(void) shmem_getpage(inode, (void) shmem_getpage(inode,
attr->ia_size>>PAGE_CACHE_SHIFT, newsize >> PAGE_CACHE_SHIFT,
&page, SGP_READ, NULL); &page, SGP_READ, NULL);
if (page) if (page)
unlock_page(page); unlock_page(page);
...@@ -797,24 +795,29 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) ...@@ -797,24 +795,29 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
* if it's being fully truncated to zero-length: the * if it's being fully truncated to zero-length: the
* nrpages check is efficient enough in that case. * nrpages check is efficient enough in that case.
*/ */
if (attr->ia_size) { if (newsize) {
struct shmem_inode_info *info = SHMEM_I(inode); struct shmem_inode_info *info = SHMEM_I(inode);
spin_lock(&info->lock); spin_lock(&info->lock);
info->flags &= ~SHMEM_PAGEIN; info->flags &= ~SHMEM_PAGEIN;
spin_unlock(&info->lock); spin_unlock(&info->lock);
} }
} }
error = simple_setsize(inode, newsize);
if (page)
page_cache_release(page);
if (error)
return error;
shmem_truncate_range(inode, newsize, (loff_t)-1);
} }
error = inode_change_ok(inode, attr); error = inode_change_ok(inode, attr);
if (!error) if (!error)
error = inode_setattr(inode, attr); generic_setattr(inode, attr);
#ifdef CONFIG_TMPFS_POSIX_ACL #ifdef CONFIG_TMPFS_POSIX_ACL
if (!error && (attr->ia_valid & ATTR_MODE)) if (!error && (attr->ia_valid & ATTR_MODE))
error = generic_acl_chmod(inode, &shmem_acl_ops); error = generic_acl_chmod(inode, &shmem_acl_ops);
#endif #endif
if (page)
page_cache_release(page);
return error; return error;
} }
...@@ -822,11 +825,11 @@ static void shmem_delete_inode(struct inode *inode) ...@@ -822,11 +825,11 @@ static void shmem_delete_inode(struct inode *inode)
{ {
struct shmem_inode_info *info = SHMEM_I(inode); struct shmem_inode_info *info = SHMEM_I(inode);
if (inode->i_op->truncate == shmem_truncate) { if (inode->i_mapping->a_ops == &shmem_aops) {
truncate_inode_pages(inode->i_mapping, 0); truncate_inode_pages(inode->i_mapping, 0);
shmem_unacct_size(info->flags, inode->i_size); shmem_unacct_size(info->flags, inode->i_size);
inode->i_size = 0; inode->i_size = 0;
shmem_truncate(inode); shmem_truncate_range(inode, 0, (loff_t)-1);
if (!list_empty(&info->swaplist)) { if (!list_empty(&info->swaplist)) {
mutex_lock(&shmem_swaplist_mutex); mutex_lock(&shmem_swaplist_mutex);
list_del_init(&info->swaplist); list_del_init(&info->swaplist);
...@@ -2018,7 +2021,6 @@ static const struct inode_operations shmem_symlink_inline_operations = { ...@@ -2018,7 +2021,6 @@ static const struct inode_operations shmem_symlink_inline_operations = {
}; };
static const struct inode_operations shmem_symlink_inode_operations = { static const struct inode_operations shmem_symlink_inode_operations = {
.truncate = shmem_truncate,
.readlink = generic_readlink, .readlink = generic_readlink,
.follow_link = shmem_follow_link, .follow_link = shmem_follow_link,
.put_link = shmem_put_link, .put_link = shmem_put_link,
...@@ -2438,7 +2440,7 @@ static const struct file_operations shmem_file_operations = { ...@@ -2438,7 +2440,7 @@ static const struct file_operations shmem_file_operations = {
}; };
static const struct inode_operations shmem_inode_operations = { static const struct inode_operations shmem_inode_operations = {
.truncate = shmem_truncate, .new_truncate = 1,
.setattr = shmem_notify_change, .setattr = shmem_notify_change,
.truncate_range = shmem_truncate_range, .truncate_range = shmem_truncate_range,
#ifdef CONFIG_TMPFS_POSIX_ACL #ifdef CONFIG_TMPFS_POSIX_ACL
......
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