提交 c08d3b0e 编写于 作者: N npiggin@suse.de 提交者: al

truncate: use new helpers

Update some fs code to make use of new helper functions introduced
in the previous patch. Should be no significant change in behaviour
(except CIFS now calls send_sig under i_lock, via inode_newsize_ok).
Reviewed-by: NChristoph Hellwig <hch@lst.de>
Acked-by: NMiklos Szeredi <miklos@szeredi.hu>
Cc: linux-nfs@vger.kernel.org
Cc: Trond.Myklebust@netapp.com
Cc: linux-cifs-client@lists.samba.org
Cc: sfrench@samba.org
Signed-off-by: NNick Piggin <npiggin@suse.de>
Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
上级 25d9e2d1
...@@ -2239,16 +2239,10 @@ int generic_cont_expand_simple(struct inode *inode, loff_t size) ...@@ -2239,16 +2239,10 @@ int generic_cont_expand_simple(struct inode *inode, loff_t size)
struct address_space *mapping = inode->i_mapping; struct address_space *mapping = inode->i_mapping;
struct page *page; struct page *page;
void *fsdata; void *fsdata;
unsigned long limit;
int err; int err;
err = -EFBIG; err = inode_newsize_ok(inode, size);
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; if (err)
if (limit != RLIM_INFINITY && size > (loff_t)limit) {
send_sig(SIGXFSZ, current, 0);
goto out;
}
if (size > inode->i_sb->s_maxbytes)
goto out; goto out;
err = pagecache_write_begin(NULL, mapping, size, 0, err = pagecache_write_begin(NULL, mapping, size, 0,
......
...@@ -1557,57 +1557,24 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from) ...@@ -1557,57 +1557,24 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
static int cifs_vmtruncate(struct inode *inode, loff_t offset) static int cifs_vmtruncate(struct inode *inode, loff_t offset)
{ {
struct address_space *mapping = inode->i_mapping; loff_t oldsize;
unsigned long limit; int err;
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
if (inode->i_size < offset) err = inode_newsize_ok(inode, offset);
goto do_expand; if (err) {
/*
* truncation of in-use swapfiles is disallowed - it would cause
* subsequent swapout to scribble on the now-freed blocks.
*/
if (IS_SWAPFILE(inode)) {
spin_unlock(&inode->i_lock);
goto out_busy;
}
i_size_write(inode, offset);
spin_unlock(&inode->i_lock);
/*
* unmap_mapping_range is called twice, first simply for efficiency
* so that truncate_inode_pages does fewer single-page unmaps. However
* after this first call, and before truncate_inode_pages finishes,
* it is possible for private pages to be COWed, which remain after
* truncate_inode_pages finishes, hence the second unmap_mapping_range
* call must be made for correctness.
*/
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
truncate_inode_pages(mapping, offset);
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
goto out_truncate;
do_expand:
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
if (limit != RLIM_INFINITY && offset > limit) {
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
goto out_sig; goto out;
}
if (offset > inode->i_sb->s_maxbytes) {
spin_unlock(&inode->i_lock);
goto out_big;
} }
oldsize = inode->i_size;
i_size_write(inode, offset); i_size_write(inode, offset);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
out_truncate: truncate_pagecache(inode, oldsize, offset);
if (inode->i_op->truncate) if (inode->i_op->truncate)
inode->i_op->truncate(inode); inode->i_op->truncate(inode);
return 0; out:
out_sig: return err;
send_sig(SIGXFSZ, current, 0);
out_big:
return -EFBIG;
out_busy:
return -ETXTBSY;
} }
static int static int
......
...@@ -1276,14 +1276,9 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, ...@@ -1276,14 +1276,9 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
return 0; return 0;
if (attr->ia_valid & ATTR_SIZE) { if (attr->ia_valid & ATTR_SIZE) {
unsigned long limit; err = inode_newsize_ok(inode, attr->ia_size);
if (IS_SWAPFILE(inode)) if (err)
return -ETXTBSY; return err;
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
if (limit != RLIM_INFINITY && attr->ia_size > (loff_t) limit) {
send_sig(SIGXFSZ, current, 0);
return -EFBIG;
}
is_truncate = true; is_truncate = true;
} }
...@@ -1350,8 +1345,7 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, ...@@ -1350,8 +1345,7 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
* FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
*/ */
if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
if (outarg.attr.size < oldsize) truncate_pagecache(inode, oldsize, outarg.attr.size);
fuse_truncate(inode->i_mapping, outarg.attr.size);
invalidate_inode_pages2(inode->i_mapping); invalidate_inode_pages2(inode->i_mapping);
} }
......
...@@ -606,8 +606,6 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, ...@@ -606,8 +606,6 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
u64 attr_valid); u64 attr_valid);
void fuse_truncate(struct address_space *mapping, loff_t offset);
/** /**
* Initialize the client device * Initialize the client device
*/ */
......
...@@ -140,14 +140,6 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) ...@@ -140,14 +140,6 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
return 0; return 0;
} }
void fuse_truncate(struct address_space *mapping, loff_t offset)
{
/* See vmtruncate() */
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
truncate_inode_pages(mapping, offset);
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
}
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
u64 attr_valid) u64 attr_valid)
{ {
...@@ -205,8 +197,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, ...@@ -205,8 +197,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
spin_unlock(&fc->lock); spin_unlock(&fc->lock);
if (S_ISREG(inode->i_mode) && oldsize != attr->size) { if (S_ISREG(inode->i_mode) && oldsize != attr->size) {
if (attr->size < oldsize) truncate_pagecache(inode, oldsize, attr->size);
fuse_truncate(inode->i_mapping, attr->size);
invalidate_inode_pages2(inode->i_mapping); invalidate_inode_pages2(inode->i_mapping);
} }
} }
......
...@@ -458,49 +458,21 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -458,49 +458,21 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
*/ */
static int nfs_vmtruncate(struct inode * inode, loff_t offset) static int nfs_vmtruncate(struct inode * inode, loff_t offset)
{ {
if (i_size_read(inode) < offset) { loff_t oldsize;
unsigned long limit; int err;
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
if (limit != RLIM_INFINITY && offset > limit)
goto out_sig;
if (offset > inode->i_sb->s_maxbytes)
goto out_big;
spin_lock(&inode->i_lock);
i_size_write(inode, offset);
spin_unlock(&inode->i_lock);
} else {
struct address_space *mapping = inode->i_mapping;
/* err = inode_newsize_ok(inode, offset);
* truncation of in-use swapfiles is disallowed - it would if (err)
* cause subsequent swapout to scribble on the now-freed goto out;
* blocks.
*/
if (IS_SWAPFILE(inode))
return -ETXTBSY;
spin_lock(&inode->i_lock);
i_size_write(inode, offset);
spin_unlock(&inode->i_lock);
/* spin_lock(&inode->i_lock);
* unmap_mapping_range is called twice, first simply for oldsize = inode->i_size;
* efficiency so that truncate_inode_pages does fewer i_size_write(inode, offset);
* single-page unmaps. However after this first call, and spin_unlock(&inode->i_lock);
* before truncate_inode_pages finishes, it is possible for
* private pages to be COWed, which remain after truncate_pagecache(inode, oldsize, offset);
* truncate_inode_pages finishes, hence the second out:
* unmap_mapping_range call must be made for correctness. return err;
*/
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
truncate_inode_pages(mapping, offset);
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
}
return 0;
out_sig:
send_sig(SIGXFSZ, current, 0);
out_big:
return -EFBIG;
} }
/** /**
......
...@@ -69,14 +69,11 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) ...@@ -69,14 +69,11 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
/* make various checks */ /* make various checks */
order = get_order(newsize); order = get_order(newsize);
if (unlikely(order >= MAX_ORDER)) if (unlikely(order >= MAX_ORDER))
goto too_big; return -EFBIG;
limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; ret = inode_newsize_ok(inode, newsize);
if (limit != RLIM_INFINITY && newsize > limit) if (ret)
goto fsize_exceeded; return ret;
if (newsize > inode->i_sb->s_maxbytes)
goto too_big;
i_size_write(inode, newsize); i_size_write(inode, newsize);
...@@ -118,12 +115,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) ...@@ -118,12 +115,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
return 0; return 0;
fsize_exceeded: add_error:
send_sig(SIGXFSZ, current, 0);
too_big:
return -EFBIG;
add_error:
while (loop < npages) while (loop < npages)
__free_page(pages + loop++); __free_page(pages + loop++);
return ret; return ret;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册