Skip to content

Commit

Permalink
kill spurious reference to vmtruncate
Browse files Browse the repository at this point in the history
Lots of filesystems calls vmtruncate despite not implementing the old
->truncate method.  Switch them to use simple_setsize and add some
comments about the truncate code where it seems fitting.

Signed-off-by: Christoph Hellwig <[email protected]>
Signed-off-by: Nick Piggin <[email protected]>
Signed-off-by: Al Viro <[email protected]>
  • Loading branch information
[email protected] authored and Al Viro committed May 28, 2010
1 parent 7bb46a6 commit 15c6fd9
Show file tree
Hide file tree
Showing 10 changed files with 37 additions and 22 deletions.
3 changes: 2 additions & 1 deletion fs/adfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,9 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr)
if (error)
goto out;

/* XXX: this is missing some actual on-disk truncation.. */
if (ia_valid & ATTR_SIZE)
error = vmtruncate(inode, attr->ia_size);
error = simple_setsize(inode, attr->ia_size);

if (error)
goto out;
Expand Down
4 changes: 2 additions & 2 deletions fs/ecryptfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
- (ia->ia_size & ~PAGE_CACHE_MASK));

if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
rc = vmtruncate(inode, ia->ia_size);
rc = simple_setsize(inode, ia->ia_size);
if (rc)
goto out;
lower_ia->ia_size = ia->ia_size;
Expand All @@ -830,7 +830,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
goto out;
}
}
vmtruncate(inode, ia->ia_size);
simple_setsize(inode, ia->ia_size);
rc = ecryptfs_write_inode_size_to_metadata(inode);
if (rc) {
printk(KERN_ERR "Problem with "
Expand Down
8 changes: 7 additions & 1 deletion fs/gfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -700,8 +700,14 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping,
return 0;

page_cache_release(page);

/*
* XXX(hch): the call below should probably be replaced with
* a call to the gfs2-specific truncate blocks helper to actually
* release disk blocks..
*/
if (pos + len > ip->i_inode.i_size)
vmtruncate(&ip->i_inode, ip->i_inode.i_size);
simple_setsize(&ip->i_inode, ip->i_inode.i_size);
out_endtrans:
gfs2_trans_end(sdp);
out_trans_fail:
Expand Down
5 changes: 4 additions & 1 deletion fs/gfs2/ops_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,9 @@ int gfs2_permission(struct inode *inode, int mask)
return error;
}

/*
* XXX: should be changed to have proper ordering by opencoding simple_setsize
*/
static int setattr_size(struct inode *inode, struct iattr *attr)
{
struct gfs2_inode *ip = GFS2_I(inode);
Expand All @@ -1081,7 +1084,7 @@ static int setattr_size(struct inode *inode, struct iattr *attr)
error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);
if (error)
return error;
error = vmtruncate(inode, attr->ia_size);
error = simple_setsize(inode, attr->ia_size);
gfs2_trans_end(sdp);
if (error)
return error;
Expand Down
4 changes: 2 additions & 2 deletions fs/jffs2/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,13 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
mutex_unlock(&f->sem);
jffs2_complete_reservation(c);

/* We have to do the vmtruncate() without f->sem held, since
/* We have to do the simple_setsize() without f->sem held, since
some pages may be locked and waiting for it in readpage().
We are protected from a simultaneous write() extending i_size
back past iattr->ia_size, because do_truncate() holds the
generic inode semaphore. */
if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
vmtruncate(inode, iattr->ia_size);
simple_setsize(inode, iattr->ia_size);
inode->i_blocks = (inode->i_size + 511) >> 9;
}

Expand Down
8 changes: 6 additions & 2 deletions fs/ocfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
}

/*
* This will intentionally not wind up calling vmtruncate(),
* This will intentionally not wind up calling simple_setsize(),
* since all the work for a size change has been done above.
* Otherwise, we could get into problems with truncate as
* ip_alloc_sem is used there to protect against i_size
Expand Down Expand Up @@ -2118,9 +2118,13 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
* direct write may have instantiated a few
* blocks outside i_size. Trim these off again.
* Don't need i_size_read because we hold i_mutex.
*
* XXX(hch): this looks buggy because ocfs2 did not
* actually implement ->truncate. Take a look at
* the new truncate sequence and update this accordingly
*/
if (*ppos + count > inode->i_size)
vmtruncate(inode, inode->i_size);
simple_setsize(inode, inode->i_size);
ret = written;
goto out_dio;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/smbfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ smb_notify_change(struct dentry *dentry, struct iattr *attr)
error = server->ops->truncate(inode, attr->ia_size);
if (error)
goto out;
error = vmtruncate(inode, attr->ia_size);
error = simple_setsize(inode, attr->ia_size);
if (error)
goto out;
refresh = 1;
Expand Down
13 changes: 8 additions & 5 deletions fs/ubifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -967,12 +967,15 @@ static int do_writepage(struct page *page, int len)
* the page locked, and it locks @ui_mutex. However, write-back does take inode
* @i_mutex, which means other VFS operations may be run on this inode at the
* same time. And the problematic one is truncation to smaller size, from where
* we have to call 'vmtruncate()', which first changes @inode->i_size, then
* we have to call 'simple_setsize()', which first changes @inode->i_size, then
* drops the truncated pages. And while dropping the pages, it takes the page
* lock. This means that 'do_truncation()' cannot call 'vmtruncate()' with
* lock. This means that 'do_truncation()' cannot call 'simple_setsize()' with
* @ui_mutex locked, because it would deadlock with 'ubifs_writepage()'. This
* means that @inode->i_size is changed while @ui_mutex is unlocked.
*
* XXX: with the new truncate the above is not true anymore, the simple_setsize
* calls can be replaced with the individual components.
*
* But in 'ubifs_writepage()' we have to guarantee that we do not write beyond
* inode size. How do we do this if @inode->i_size may became smaller while we
* are in the middle of 'ubifs_writepage()'? The UBIFS solution is the
Expand Down Expand Up @@ -1125,7 +1128,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
budgeted = 0;
}

err = vmtruncate(inode, new_size);
err = simple_setsize(inode, new_size);
if (err)
goto out_budg;

Expand Down Expand Up @@ -1214,7 +1217,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode,

if (attr->ia_valid & ATTR_SIZE) {
dbg_gen("size %lld -> %lld", inode->i_size, new_size);
err = vmtruncate(inode, new_size);
err = simple_setsize(inode, new_size);
if (err)
goto out;
}
Expand All @@ -1223,7 +1226,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode,
if (attr->ia_valid & ATTR_SIZE) {
/* Truncation changes inode [mc]time */
inode->i_mtime = inode->i_ctime = ubifs_current_time(inode);
/* 'vmtruncate()' changed @i_size, update @ui_size */
/* 'simple_setsize()' changed @i_size, update @ui_size */
ui->ui_size = inode->i_size;
}

Expand Down
2 changes: 1 addition & 1 deletion fs/ubifs/ubifs.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ struct ubifs_gced_idx_leb {
* The @ui_size is a "shadow" variable for @inode->i_size and UBIFS uses
* @ui_size instead of @inode->i_size. The reason for this is that UBIFS cannot
* make sure @inode->i_size is always changed under @ui_mutex, because it
* cannot call 'vmtruncate()' with @ui_mutex locked, because it would deadlock
* cannot call 'simple_setsize()' with @ui_mutex locked, because it would deadlock
* with 'ubifs_writepage()' (see file.c). All the other inode fields are
* changed under @ui_mutex, so they do not need "shadow" fields. Note, one
* could consider to rework locking and base it on "shadow" fields.
Expand Down
10 changes: 4 additions & 6 deletions fs/ufs/truncate.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,12 +501,10 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size)
return err;
}


/*
* We don't define our `inode->i_op->truncate', and call it here,
* because of:
* - there is no way to know old size
* - there is no way inform user about error, if it happens in `truncate'
* TODO:
* - truncate case should use proper ordering instead of using
* simple_setsize
*/
int ufs_setattr(struct dentry *dentry, struct iattr *attr)
{
Expand All @@ -530,7 +528,7 @@ int ufs_setattr(struct dentry *dentry, struct iattr *attr)
if (ia_valid & ATTR_SIZE && attr->ia_size != inode->i_size) {
loff_t old_i_size = inode->i_size;

error = vmtruncate(inode, attr->ia_size);
error = simple_setsize(inode, attr->ia_size);
if (error)
return error;
error = ufs_truncate(inode, old_i_size);
Expand Down

0 comments on commit 15c6fd9

Please sign in to comment.