ext4: refactor truncate code
Move common code in ext4_ind_truncate() and ext4_ext_truncate() into ext4_truncate(). This saves over 60 lines of code. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
@@ -3738,9 +3738,9 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
|
||||
stop_block);
|
||||
|
||||
ext4_discard_preallocations(inode);
|
||||
up_write(&EXT4_I(inode)->i_data_sem);
|
||||
if (IS_SYNC(inode))
|
||||
ext4_handle_sync(handle);
|
||||
up_write(&EXT4_I(inode)->i_data_sem);
|
||||
inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
|
||||
ext4_mark_inode_dirty(handle, inode);
|
||||
out_stop:
|
||||
@@ -3782,6 +3782,12 @@ out_mutex:
|
||||
*/
|
||||
void ext4_truncate(struct inode *inode)
|
||||
{
|
||||
struct ext4_inode_info *ei = EXT4_I(inode);
|
||||
unsigned int credits;
|
||||
handle_t *handle;
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
loff_t page_len;
|
||||
|
||||
trace_ext4_truncate_enter(inode);
|
||||
|
||||
if (!ext4_can_truncate(inode))
|
||||
@@ -3800,10 +3806,72 @@ void ext4_truncate(struct inode *inode)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* finish any pending end_io work so we won't run the risk of
|
||||
* converting any truncated blocks to initialized later
|
||||
*/
|
||||
ext4_flush_unwritten_io(inode);
|
||||
|
||||
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
|
||||
ext4_ext_truncate(inode);
|
||||
credits = ext4_writepage_trans_blocks(inode);
|
||||
else
|
||||
ext4_ind_truncate(inode);
|
||||
credits = ext4_blocks_for_truncate(inode);
|
||||
|
||||
handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
|
||||
if (IS_ERR(handle)) {
|
||||
ext4_std_error(inode->i_sb, PTR_ERR(handle));
|
||||
return;
|
||||
}
|
||||
|
||||
if (inode->i_size % PAGE_CACHE_SIZE != 0) {
|
||||
page_len = PAGE_CACHE_SIZE -
|
||||
(inode->i_size & (PAGE_CACHE_SIZE - 1));
|
||||
|
||||
if (ext4_discard_partial_page_buffers(handle,
|
||||
mapping, inode->i_size, page_len, 0))
|
||||
goto out_stop;
|
||||
}
|
||||
|
||||
/*
|
||||
* We add the inode to the orphan list, so that if this
|
||||
* truncate spans multiple transactions, and we crash, we will
|
||||
* resume the truncate when the filesystem recovers. It also
|
||||
* marks the inode dirty, to catch the new size.
|
||||
*
|
||||
* Implication: the file must always be in a sane, consistent
|
||||
* truncatable state while each transaction commits.
|
||||
*/
|
||||
if (ext4_orphan_add(handle, inode))
|
||||
goto out_stop;
|
||||
|
||||
down_write(&EXT4_I(inode)->i_data_sem);
|
||||
|
||||
ext4_discard_preallocations(inode);
|
||||
|
||||
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
|
||||
ext4_ext_truncate(handle, inode);
|
||||
else
|
||||
ext4_ind_truncate(handle, inode);
|
||||
|
||||
up_write(&ei->i_data_sem);
|
||||
|
||||
if (IS_SYNC(inode))
|
||||
ext4_handle_sync(handle);
|
||||
|
||||
out_stop:
|
||||
/*
|
||||
* If this was a simple ftruncate() and the file will remain alive,
|
||||
* then we need to clear up the orphan record which we created above.
|
||||
* However, if this was a real unlink then we were called by
|
||||
* ext4_delete_inode(), and we allow that function to clean up the
|
||||
* orphan info for us.
|
||||
*/
|
||||
if (inode->i_nlink)
|
||||
ext4_orphan_del(handle, inode);
|
||||
|
||||
inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
|
||||
ext4_mark_inode_dirty(handle, inode);
|
||||
ext4_journal_stop(handle);
|
||||
|
||||
trace_ext4_truncate_exit(inode);
|
||||
}
|
||||
|
Reference in New Issue
Block a user