Skip to content

Commit 35bd33e

Browse files
zhangyi089gregkh
authored andcommitted
ext4: move out common parts into ext4_fallocate()
[ Upstream commit 2890e5e ] Currently, all zeroing ranges, punch holes, collapse ranges, and insert ranges first wait for all existing direct I/O workers to complete, and then they acquire the mapping's invalidate lock before performing the actual work. These common components are nearly identical, so we can simplify the code by factoring them out into the ext4_fallocate(). Signed-off-by: Zhang Yi <[email protected]> Reviewed-by: Jan Kara <[email protected]> Reviewed-by: Ojaswin Mujoo <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Theodore Ts'o <[email protected]> Stable-dep-of: 29ec9be ("ext4: fix incorrect punch max_end") Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 8a98313 commit 35bd33e

File tree

2 files changed

+45
-104
lines changed

2 files changed

+45
-104
lines changed

fs/ext4/extents.c

Lines changed: 42 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -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

46794661
out_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,
47434716
long 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);
47794779
out_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

53765358
out_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

55225484
out_handle:
55235485
ext4_journal_stop(handle);
5524-
out_invalidate_lock:
5525-
filemap_invalidate_unlock(mapping);
55265486
return ret;
55275487
}
55285488

fs/ext4/inode.c

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3992,7 +3992,6 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
39923992
struct inode *inode = file_inode(file);
39933993
struct super_block *sb = inode->i_sb;
39943994
ext4_lblk_t start_lblk, end_lblk;
3995-
struct address_space *mapping = inode->i_mapping;
39963995
loff_t max_end = EXT4_SB(sb)->s_bitmap_maxbytes - sb->s_blocksize;
39973996
loff_t end = offset + length;
39983997
handle_t *handle;
@@ -4027,31 +4026,15 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
40274026
return ret;
40284027
}
40294028

4030-
/* Wait all existing dio workers, newcomers will block on i_rwsem */
4031-
inode_dio_wait(inode);
4032-
4033-
ret = file_modified(file);
4034-
if (ret)
4035-
return ret;
4036-
4037-
/*
4038-
* Prevent page faults from reinstantiating pages we have released from
4039-
* page cache.
4040-
*/
4041-
filemap_invalidate_lock(mapping);
4042-
4043-
ret = ext4_break_layouts(inode);
4044-
if (ret)
4045-
goto out_invalidate_lock;
40464029

40474030
ret = ext4_update_disksize_before_punch(inode, offset, length);
40484031
if (ret)
4049-
goto out_invalidate_lock;
4032+
return ret;
40504033

40514034
/* Now release the pages and zero block aligned part of pages*/
40524035
ret = ext4_truncate_page_cache_block_range(inode, offset, end);
40534036
if (ret)
4054-
goto out_invalidate_lock;
4037+
return ret;
40554038

40564039
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
40574040
credits = ext4_writepage_trans_blocks(inode);
@@ -4061,7 +4044,7 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
40614044
if (IS_ERR(handle)) {
40624045
ret = PTR_ERR(handle);
40634046
ext4_std_error(sb, ret);
4064-
goto out_invalidate_lock;
4047+
return ret;
40654048
}
40664049

40674050
ret = ext4_zero_partial_blocks(handle, inode, offset, length);
@@ -4106,8 +4089,6 @@ int ext4_punch_hole(struct file *file, loff_t offset, loff_t length)
41064089
ext4_handle_sync(handle);
41074090
out_handle:
41084091
ext4_journal_stop(handle);
4109-
out_invalidate_lock:
4110-
filemap_invalidate_unlock(mapping);
41114092
return ret;
41124093
}
41134094

0 commit comments

Comments
 (0)