@@ -4706,81 +4706,70 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr)
4706
4706
ext4_journal_stop (handle );
4707
4707
}
4708
4708
4709
- if (attr -> ia_valid & ATTR_SIZE ) {
4709
+ if (attr -> ia_valid & ATTR_SIZE && attr -> ia_size != inode -> i_size ) {
4710
+ handle_t * handle ;
4711
+ loff_t oldsize = inode -> i_size ;
4710
4712
4711
4713
if (!(ext4_test_inode_flag (inode , EXT4_INODE_EXTENTS ))) {
4712
4714
struct ext4_sb_info * sbi = EXT4_SB (inode -> i_sb );
4713
4715
4714
4716
if (attr -> ia_size > sbi -> s_bitmap_maxbytes )
4715
4717
return - EFBIG ;
4716
4718
}
4717
- }
4718
-
4719
- if (S_ISREG (inode -> i_mode ) &&
4720
- attr -> ia_valid & ATTR_SIZE &&
4721
- (attr -> ia_size < inode -> i_size )) {
4722
- handle_t * handle ;
4723
-
4724
- handle = ext4_journal_start (inode , EXT4_HT_INODE , 3 );
4725
- if (IS_ERR (handle )) {
4726
- error = PTR_ERR (handle );
4727
- goto err_out ;
4728
- }
4729
- if (ext4_handle_valid (handle )) {
4730
- error = ext4_orphan_add (handle , inode );
4731
- orphan = 1 ;
4732
- }
4733
- EXT4_I (inode )-> i_disksize = attr -> ia_size ;
4734
- rc = ext4_mark_inode_dirty (handle , inode );
4735
- if (!error )
4736
- error = rc ;
4737
- ext4_journal_stop (handle );
4738
-
4739
- if (ext4_should_order_data (inode )) {
4740
- error = ext4_begin_ordered_truncate (inode ,
4719
+ if (S_ISREG (inode -> i_mode ) &&
4720
+ (attr -> ia_size < inode -> i_size )) {
4721
+ if (ext4_should_order_data (inode )) {
4722
+ error = ext4_begin_ordered_truncate (inode ,
4741
4723
attr -> ia_size );
4742
- if (error ) {
4743
- /* Do as much error cleanup as possible */
4744
- handle = ext4_journal_start (inode ,
4745
- EXT4_HT_INODE , 3 );
4746
- if (IS_ERR (handle )) {
4747
- ext4_orphan_del (NULL , inode );
4724
+ if (error )
4748
4725
goto err_out ;
4749
- }
4750
- ext4_orphan_del (handle , inode );
4751
- orphan = 0 ;
4752
- ext4_journal_stop (handle );
4726
+ }
4727
+ handle = ext4_journal_start (inode , EXT4_HT_INODE , 3 );
4728
+ if (IS_ERR (handle )) {
4729
+ error = PTR_ERR (handle );
4730
+ goto err_out ;
4731
+ }
4732
+ if (ext4_handle_valid (handle )) {
4733
+ error = ext4_orphan_add (handle , inode );
4734
+ orphan = 1 ;
4735
+ }
4736
+ EXT4_I (inode )-> i_disksize = attr -> ia_size ;
4737
+ rc = ext4_mark_inode_dirty (handle , inode );
4738
+ if (!error )
4739
+ error = rc ;
4740
+ ext4_journal_stop (handle );
4741
+ if (error ) {
4742
+ ext4_orphan_del (NULL , inode );
4753
4743
goto err_out ;
4754
4744
}
4755
4745
}
4756
- }
4757
-
4758
- if (attr -> ia_valid & ATTR_SIZE ) {
4759
- if (attr -> ia_size != inode -> i_size ) {
4760
- loff_t oldsize = inode -> i_size ;
4761
4746
4762
- i_size_write (inode , attr -> ia_size );
4763
- /*
4764
- * Blocks are going to be removed from the inode. Wait
4765
- * for dio in flight. Temporarily disable
4766
- * dioread_nolock to prevent livelock.
4767
- */
4768
- if (orphan ) {
4769
- if (!ext4_should_journal_data (inode )) {
4770
- ext4_inode_block_unlocked_dio (inode );
4771
- inode_dio_wait (inode );
4772
- ext4_inode_resume_unlocked_dio (inode );
4773
- } else
4774
- ext4_wait_for_tail_page_commit (inode );
4775
- }
4776
- /*
4777
- * Truncate pagecache after we've waited for commit
4778
- * in data=journal mode to make pages freeable.
4779
- */
4780
- truncate_pagecache (inode , oldsize , inode -> i_size );
4747
+ i_size_write (inode , attr -> ia_size );
4748
+ /*
4749
+ * Blocks are going to be removed from the inode. Wait
4750
+ * for dio in flight. Temporarily disable
4751
+ * dioread_nolock to prevent livelock.
4752
+ */
4753
+ if (orphan ) {
4754
+ if (!ext4_should_journal_data (inode )) {
4755
+ ext4_inode_block_unlocked_dio (inode );
4756
+ inode_dio_wait (inode );
4757
+ ext4_inode_resume_unlocked_dio (inode );
4758
+ } else
4759
+ ext4_wait_for_tail_page_commit (inode );
4781
4760
}
4782
- ext4_truncate (inode );
4761
+ /*
4762
+ * Truncate pagecache after we've waited for commit
4763
+ * in data=journal mode to make pages freeable.
4764
+ */
4765
+ truncate_pagecache (inode , oldsize , inode -> i_size );
4783
4766
}
4767
+ /*
4768
+ * We want to call ext4_truncate() even if attr->ia_size ==
4769
+ * inode->i_size for cases like truncation of fallocated space
4770
+ */
4771
+ if (attr -> ia_valid & ATTR_SIZE )
4772
+ ext4_truncate (inode );
4784
4773
4785
4774
if (!rc ) {
4786
4775
setattr_copy (inode , attr );
0 commit comments