diff options
author | Theodore Ts'o <tytso@mit.edu> | 2013-04-03 12:47:17 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2013-04-03 12:47:17 -0400 |
commit | 819c4920b7e60ecfd6f0f61d890af4cdf3873d18 (patch) | |
tree | 85f995b14c7308080d196d85b9b3d148337a6382 /fs/ext4/inode.c | |
parent | 26a4c0c6ccecf6814cf44f951c97222bd795bc1a (diff) |
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>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 74 |
1 files changed, 71 insertions, 3 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 9bda50aa34e2..49c80e4ac5ac 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -3738,9 +3738,9 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length) | |||
3738 | stop_block); | 3738 | stop_block); |
3739 | 3739 | ||
3740 | ext4_discard_preallocations(inode); | 3740 | ext4_discard_preallocations(inode); |
3741 | up_write(&EXT4_I(inode)->i_data_sem); | ||
3741 | if (IS_SYNC(inode)) | 3742 | if (IS_SYNC(inode)) |
3742 | ext4_handle_sync(handle); | 3743 | ext4_handle_sync(handle); |
3743 | up_write(&EXT4_I(inode)->i_data_sem); | ||
3744 | inode->i_mtime = inode->i_ctime = ext4_current_time(inode); | 3744 | inode->i_mtime = inode->i_ctime = ext4_current_time(inode); |
3745 | ext4_mark_inode_dirty(handle, inode); | 3745 | ext4_mark_inode_dirty(handle, inode); |
3746 | out_stop: | 3746 | out_stop: |
@@ -3782,6 +3782,12 @@ out_mutex: | |||
3782 | */ | 3782 | */ |
3783 | void ext4_truncate(struct inode *inode) | 3783 | void ext4_truncate(struct inode *inode) |
3784 | { | 3784 | { |
3785 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
3786 | unsigned int credits; | ||
3787 | handle_t *handle; | ||
3788 | struct address_space *mapping = inode->i_mapping; | ||
3789 | loff_t page_len; | ||
3790 | |||
3785 | trace_ext4_truncate_enter(inode); | 3791 | trace_ext4_truncate_enter(inode); |
3786 | 3792 | ||
3787 | if (!ext4_can_truncate(inode)) | 3793 | if (!ext4_can_truncate(inode)) |
@@ -3800,10 +3806,72 @@ void ext4_truncate(struct inode *inode) | |||
3800 | return; | 3806 | return; |
3801 | } | 3807 | } |
3802 | 3808 | ||
3809 | /* | ||
3810 | * finish any pending end_io work so we won't run the risk of | ||
3811 | * converting any truncated blocks to initialized later | ||
3812 | */ | ||
3813 | ext4_flush_unwritten_io(inode); | ||
3814 | |||
3815 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) | ||
3816 | credits = ext4_writepage_trans_blocks(inode); | ||
3817 | else | ||
3818 | credits = ext4_blocks_for_truncate(inode); | ||
3819 | |||
3820 | handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); | ||
3821 | if (IS_ERR(handle)) { | ||
3822 | ext4_std_error(inode->i_sb, PTR_ERR(handle)); | ||
3823 | return; | ||
3824 | } | ||
3825 | |||
3826 | if (inode->i_size % PAGE_CACHE_SIZE != 0) { | ||
3827 | page_len = PAGE_CACHE_SIZE - | ||
3828 | (inode->i_size & (PAGE_CACHE_SIZE - 1)); | ||
3829 | |||
3830 | if (ext4_discard_partial_page_buffers(handle, | ||
3831 | mapping, inode->i_size, page_len, 0)) | ||
3832 | goto out_stop; | ||
3833 | } | ||
3834 | |||
3835 | /* | ||
3836 | * We add the inode to the orphan list, so that if this | ||
3837 | * truncate spans multiple transactions, and we crash, we will | ||
3838 | * resume the truncate when the filesystem recovers. It also | ||
3839 | * marks the inode dirty, to catch the new size. | ||
3840 | * | ||
3841 | * Implication: the file must always be in a sane, consistent | ||
3842 | * truncatable state while each transaction commits. | ||
3843 | */ | ||
3844 | if (ext4_orphan_add(handle, inode)) | ||
3845 | goto out_stop; | ||
3846 | |||
3847 | down_write(&EXT4_I(inode)->i_data_sem); | ||
3848 | |||
3849 | ext4_discard_preallocations(inode); | ||
3850 | |||
3803 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) | 3851 | if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) |
3804 | ext4_ext_truncate(inode); | 3852 | ext4_ext_truncate(handle, inode); |
3805 | else | 3853 | else |
3806 | ext4_ind_truncate(inode); | 3854 | ext4_ind_truncate(handle, inode); |
3855 | |||
3856 | up_write(&ei->i_data_sem); | ||
3857 | |||
3858 | if (IS_SYNC(inode)) | ||
3859 | ext4_handle_sync(handle); | ||
3860 | |||
3861 | out_stop: | ||
3862 | /* | ||
3863 | * If this was a simple ftruncate() and the file will remain alive, | ||
3864 | * then we need to clear up the orphan record which we created above. | ||
3865 | * However, if this was a real unlink then we were called by | ||
3866 | * ext4_delete_inode(), and we allow that function to clean up the | ||
3867 | * orphan info for us. | ||
3868 | */ | ||
3869 | if (inode->i_nlink) | ||
3870 | ext4_orphan_del(handle, inode); | ||
3871 | |||
3872 | inode->i_mtime = inode->i_ctime = ext4_current_time(inode); | ||
3873 | ext4_mark_inode_dirty(handle, inode); | ||
3874 | ext4_journal_stop(handle); | ||
3807 | 3875 | ||
3808 | trace_ext4_truncate_exit(inode); | 3876 | trace_ext4_truncate_exit(inode); |
3809 | } | 3877 | } |