@@ -4569,7 +4569,6 @@ static long ext4_zero_range(struct file *file, loff_t offset,
45694569 loff_t len , int mode )
45704570{
45714571 struct inode * inode = file_inode (file );
4572- struct address_space * mapping = file -> f_mapping ;
45734572 handle_t * handle = NULL ;
45744573 loff_t new_size = 0 ;
45754574 loff_t end = offset + len ;
@@ -4593,23 +4592,6 @@ static long ext4_zero_range(struct file *file, loff_t offset,
45934592 return ret ;
45944593 }
45954594
4596- /* Wait all existing dio workers, newcomers will block on i_rwsem */
4597- inode_dio_wait (inode );
4598-
4599- ret = file_modified (file );
4600- if (ret )
4601- return ret ;
4602-
4603- /*
4604- * Prevent page faults from reinstantiating pages we have released
4605- * from page cache.
4606- */
4607- filemap_invalidate_lock (mapping );
4608-
4609- ret = ext4_break_layouts (inode );
4610- if (ret )
4611- goto out_invalidate_lock ;
4612-
46134595 flags = EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT ;
46144596 /* Preallocate the range including the unaligned edges */
46154597 if (!IS_ALIGNED (offset | end , blocksize )) {
@@ -4619,17 +4601,17 @@ static long ext4_zero_range(struct file *file, loff_t offset,
46194601 ret = ext4_alloc_file_blocks (file , alloc_lblk , len_lblk ,
46204602 new_size , flags );
46214603 if (ret )
4622- goto out_invalidate_lock ;
4604+ return ret ;
46234605 }
46244606
46254607 ret = ext4_update_disksize_before_punch (inode , offset , len );
46264608 if (ret )
4627- goto out_invalidate_lock ;
4609+ return ret ;
46284610
46294611 /* Now release the pages and zero block aligned part of pages */
46304612 ret = ext4_truncate_page_cache_block_range (inode , offset , end );
46314613 if (ret )
4632- goto out_invalidate_lock ;
4614+ return ret ;
46334615
46344616 /* Zero range excluding the unaligned edges */
46354617 start_lblk = EXT4_B_TO_LBLK (inode , offset );
@@ -4641,11 +4623,11 @@ static long ext4_zero_range(struct file *file, loff_t offset,
46414623 ret = ext4_alloc_file_blocks (file , start_lblk , zero_blks ,
46424624 new_size , flags );
46434625 if (ret )
4644- goto out_invalidate_lock ;
4626+ return ret ;
46454627 }
46464628 /* Finish zeroing out if it doesn't contain partial block */
46474629 if (IS_ALIGNED (offset | end , blocksize ))
4648- goto out_invalidate_lock ;
4630+ return ret ;
46494631
46504632 /*
46514633 * In worst case we have to writeout two nonadjacent unwritten
@@ -4658,7 +4640,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
46584640 if (IS_ERR (handle )) {
46594641 ret = PTR_ERR (handle );
46604642 ext4_std_error (inode -> i_sb , ret );
4661- goto out_invalidate_lock ;
4643+ return ret ;
46624644 }
46634645
46644646 /* Zero out partial block at the edges of the range */
@@ -4678,8 +4660,6 @@ static long ext4_zero_range(struct file *file, loff_t offset,
46784660
46794661out_handle :
46804662 ext4_journal_stop (handle );
4681- out_invalidate_lock :
4682- filemap_invalidate_unlock (mapping );
46834663 return ret ;
46844664}
46854665
@@ -4712,13 +4692,6 @@ static long ext4_do_fallocate(struct file *file, loff_t offset,
47124692 goto out ;
47134693 }
47144694
4715- /* Wait all existing dio workers, newcomers will block on i_rwsem */
4716- inode_dio_wait (inode );
4717-
4718- ret = file_modified (file );
4719- if (ret )
4720- goto out ;
4721-
47224695 ret = ext4_alloc_file_blocks (file , start_lblk , len_lblk , new_size ,
47234696 EXT4_GET_BLOCKS_CREATE_UNWRIT_EXT );
47244697 if (ret )
@@ -4743,6 +4716,7 @@ static long ext4_do_fallocate(struct file *file, loff_t offset,
47434716long ext4_fallocate (struct file * file , int mode , loff_t offset , loff_t len )
47444717{
47454718 struct inode * inode = file_inode (file );
4719+ struct address_space * mapping = file -> f_mapping ;
47464720 int ret ;
47474721
47484722 /*
@@ -4766,6 +4740,29 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
47664740 if (ret )
47674741 goto out_inode_lock ;
47684742
4743+ /* Wait all existing dio workers, newcomers will block on i_rwsem */
4744+ inode_dio_wait (inode );
4745+
4746+ ret = file_modified (file );
4747+ if (ret )
4748+ return ret ;
4749+
4750+ if ((mode & FALLOC_FL_MODE_MASK ) == FALLOC_FL_ALLOCATE_RANGE ) {
4751+ ret = ext4_do_fallocate (file , offset , len , mode );
4752+ goto out_inode_lock ;
4753+ }
4754+
4755+ /*
4756+ * Follow-up operations will drop page cache, hold invalidate lock
4757+ * to prevent page faults from reinstantiating pages we have
4758+ * released from page cache.
4759+ */
4760+ filemap_invalidate_lock (mapping );
4761+
4762+ ret = ext4_break_layouts (inode );
4763+ if (ret )
4764+ goto out_invalidate_lock ;
4765+
47694766 if (mode & FALLOC_FL_PUNCH_HOLE )
47704767 ret = ext4_punch_hole (file , offset , len );
47714768 else if (mode & FALLOC_FL_COLLAPSE_RANGE )
@@ -4775,7 +4772,10 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
47754772 else if (mode & FALLOC_FL_ZERO_RANGE )
47764773 ret = ext4_zero_range (file , offset , len , mode );
47774774 else
4778- ret = ext4_do_fallocate (file , offset , len , mode );
4775+ ret = - EOPNOTSUPP ;
4776+
4777+ out_invalidate_lock :
4778+ filemap_invalidate_unlock (mapping );
47794779out_inode_lock :
47804780 inode_unlock (inode );
47814781 return ret ;
@@ -5297,23 +5297,6 @@ static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
52975297 if (end >= inode -> i_size )
52985298 return - EINVAL ;
52995299
5300- /* Wait for existing dio to complete */
5301- inode_dio_wait (inode );
5302-
5303- ret = file_modified (file );
5304- if (ret )
5305- return ret ;
5306-
5307- /*
5308- * Prevent page faults from reinstantiating pages we have released from
5309- * page cache.
5310- */
5311- filemap_invalidate_lock (mapping );
5312-
5313- ret = ext4_break_layouts (inode );
5314- if (ret )
5315- goto out_invalidate_lock ;
5316-
53175300 /*
53185301 * Write tail of the last page before removed range and data that
53195302 * will be shifted since they will get removed from the page cache
@@ -5327,16 +5310,15 @@ static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
53275310 if (!ret )
53285311 ret = filemap_write_and_wait_range (mapping , end , LLONG_MAX );
53295312 if (ret )
5330- goto out_invalidate_lock ;
5313+ return ret ;
53315314
53325315 truncate_pagecache (inode , start );
53335316
53345317 credits = ext4_writepage_trans_blocks (inode );
53355318 handle = ext4_journal_start (inode , EXT4_HT_TRUNCATE , credits );
5336- if (IS_ERR (handle )) {
5337- ret = PTR_ERR (handle );
5338- goto out_invalidate_lock ;
5339- }
5319+ if (IS_ERR (handle ))
5320+ return PTR_ERR (handle );
5321+
53405322 ext4_fc_mark_ineligible (sb , EXT4_FC_REASON_FALLOC_RANGE , handle );
53415323
53425324 start_lblk = offset >> inode -> i_blkbits ;
@@ -5375,8 +5357,6 @@ static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
53755357
53765358out_handle :
53775359 ext4_journal_stop (handle );
5378- out_invalidate_lock :
5379- filemap_invalidate_unlock (mapping );
53805360 return ret ;
53815361}
53825362
@@ -5417,40 +5397,22 @@ static int ext4_insert_range(struct file *file, loff_t offset, loff_t len)
54175397 if (len > inode -> i_sb -> s_maxbytes - inode -> i_size )
54185398 return - EFBIG ;
54195399
5420- /* Wait for existing dio to complete */
5421- inode_dio_wait (inode );
5422-
5423- ret = file_modified (file );
5424- if (ret )
5425- return ret ;
5426-
5427- /*
5428- * Prevent page faults from reinstantiating pages we have released from
5429- * page cache.
5430- */
5431- filemap_invalidate_lock (mapping );
5432-
5433- ret = ext4_break_layouts (inode );
5434- if (ret )
5435- goto out_invalidate_lock ;
5436-
54375400 /*
54385401 * Write out all dirty pages. Need to round down to align start offset
54395402 * to page size boundary for page size > block size.
54405403 */
54415404 start = round_down (offset , PAGE_SIZE );
54425405 ret = filemap_write_and_wait_range (mapping , start , LLONG_MAX );
54435406 if (ret )
5444- goto out_invalidate_lock ;
5407+ return ret ;
54455408
54465409 truncate_pagecache (inode , start );
54475410
54485411 credits = ext4_writepage_trans_blocks (inode );
54495412 handle = ext4_journal_start (inode , EXT4_HT_TRUNCATE , credits );
5450- if (IS_ERR (handle )) {
5451- ret = PTR_ERR (handle );
5452- goto out_invalidate_lock ;
5453- }
5413+ if (IS_ERR (handle ))
5414+ return PTR_ERR (handle );
5415+
54545416 ext4_fc_mark_ineligible (sb , EXT4_FC_REASON_FALLOC_RANGE , handle );
54555417
54565418 /* Expand file to avoid data loss if there is error while shifting */
@@ -5521,8 +5483,6 @@ static int ext4_insert_range(struct file *file, loff_t offset, loff_t len)
55215483
55225484out_handle :
55235485 ext4_journal_stop (handle );
5524- out_invalidate_lock :
5525- filemap_invalidate_unlock (mapping );
55265486 return ret ;
55275487}
55285488
0 commit comments