Skip to content

Commit 8bb93d9

Browse files
zhangyi089gregkh
authored andcommitted
ext4: refactor ext4_collapse_range()
[ Upstream commit 162e3c5 ] Simplify ext4_collapse_range() and align its code style with that of ext4_zero_range() and ext4_punch_hole(). Refactor it by: a) renaming variables, b) removing redundant input parameter checks and moving the remaining checks under i_rwsem in preparation for future refactoring, and c) renaming the three stale error tags. 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 db1fcf7 commit 8bb93d9

File tree

1 file changed

+48
-55
lines changed

1 file changed

+48
-55
lines changed

fs/ext4/extents.c

Lines changed: 48 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5288,51 +5288,44 @@ static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
52885288
struct inode *inode = file_inode(file);
52895289
struct super_block *sb = inode->i_sb;
52905290
struct address_space *mapping = inode->i_mapping;
5291-
ext4_lblk_t punch_start, punch_stop;
5291+
loff_t end = offset + len;
5292+
ext4_lblk_t start_lblk, end_lblk;
52925293
handle_t *handle;
52935294
unsigned int credits;
5294-
loff_t new_size, ioffset;
5295+
loff_t start, new_size;
52955296
int ret;
52965297

5297-
/*
5298-
* We need to test this early because xfstests assumes that a
5299-
* collapse range of (0, 1) will return EOPNOTSUPP if the file
5300-
* system does not support collapse range.
5301-
*/
5302-
if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
5303-
return -EOPNOTSUPP;
5298+
trace_ext4_collapse_range(inode, offset, len);
53045299

5305-
/* Collapse range works only on fs cluster size aligned regions. */
5306-
if (!IS_ALIGNED(offset | len, EXT4_CLUSTER_SIZE(sb)))
5307-
return -EINVAL;
5300+
inode_lock(inode);
53085301

5309-
trace_ext4_collapse_range(inode, offset, len);
5302+
/* Currently just for extent based files */
5303+
if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
5304+
ret = -EOPNOTSUPP;
5305+
goto out;
5306+
}
53105307

5311-
punch_start = offset >> EXT4_BLOCK_SIZE_BITS(sb);
5312-
punch_stop = (offset + len) >> EXT4_BLOCK_SIZE_BITS(sb);
5308+
/* Collapse range works only on fs cluster size aligned regions. */
5309+
if (!IS_ALIGNED(offset | len, EXT4_CLUSTER_SIZE(sb))) {
5310+
ret = -EINVAL;
5311+
goto out;
5312+
}
53135313

5314-
inode_lock(inode);
53155314
/*
53165315
* There is no need to overlap collapse range with EOF, in which case
53175316
* it is effectively a truncate operation
53185317
*/
5319-
if (offset + len >= inode->i_size) {
5318+
if (end >= inode->i_size) {
53205319
ret = -EINVAL;
5321-
goto out_mutex;
5322-
}
5323-
5324-
/* Currently just for extent based files */
5325-
if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
5326-
ret = -EOPNOTSUPP;
5327-
goto out_mutex;
5320+
goto out;
53285321
}
53295322

53305323
/* Wait for existing dio to complete */
53315324
inode_dio_wait(inode);
53325325

53335326
ret = file_modified(file);
53345327
if (ret)
5335-
goto out_mutex;
5328+
goto out;
53365329

53375330
/*
53385331
* Prevent page faults from reinstantiating pages we have released from
@@ -5342,72 +5335,72 @@ static int ext4_collapse_range(struct file *file, loff_t offset, loff_t len)
53425335

53435336
ret = ext4_break_layouts(inode);
53445337
if (ret)
5345-
goto out_mmap;
5338+
goto out_invalidate_lock;
53465339

53475340
/*
5341+
* Write tail of the last page before removed range and data that
5342+
* will be shifted since they will get removed from the page cache
5343+
* below. We are also protected from pages becoming dirty by
5344+
* i_rwsem and invalidate_lock.
53485345
* Need to round down offset to be aligned with page size boundary
53495346
* for page size > block size.
53505347
*/
5351-
ioffset = round_down(offset, PAGE_SIZE);
5352-
/*
5353-
* Write tail of the last page before removed range since it will get
5354-
* removed from the page cache below.
5355-
*/
5356-
ret = filemap_write_and_wait_range(mapping, ioffset, offset);
5357-
if (ret)
5358-
goto out_mmap;
5359-
/*
5360-
* Write data that will be shifted to preserve them when discarding
5361-
* page cache below. We are also protected from pages becoming dirty
5362-
* by i_rwsem and invalidate_lock.
5363-
*/
5364-
ret = filemap_write_and_wait_range(mapping, offset + len,
5365-
LLONG_MAX);
5348+
start = round_down(offset, PAGE_SIZE);
5349+
ret = filemap_write_and_wait_range(mapping, start, offset);
5350+
if (!ret)
5351+
ret = filemap_write_and_wait_range(mapping, end, LLONG_MAX);
53665352
if (ret)
5367-
goto out_mmap;
5368-
truncate_pagecache(inode, ioffset);
5353+
goto out_invalidate_lock;
5354+
5355+
truncate_pagecache(inode, start);
53695356

53705357
credits = ext4_writepage_trans_blocks(inode);
53715358
handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits);
53725359
if (IS_ERR(handle)) {
53735360
ret = PTR_ERR(handle);
5374-
goto out_mmap;
5361+
goto out_invalidate_lock;
53755362
}
53765363
ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_FALLOC_RANGE, handle);
53775364

5365+
start_lblk = offset >> inode->i_blkbits;
5366+
end_lblk = (offset + len) >> inode->i_blkbits;
5367+
53785368
down_write(&EXT4_I(inode)->i_data_sem);
53795369
ext4_discard_preallocations(inode);
5380-
ext4_es_remove_extent(inode, punch_start, EXT_MAX_BLOCKS - punch_start);
5370+
ext4_es_remove_extent(inode, start_lblk, EXT_MAX_BLOCKS - start_lblk);
53815371

5382-
ret = ext4_ext_remove_space(inode, punch_start, punch_stop - 1);
5372+
ret = ext4_ext_remove_space(inode, start_lblk, end_lblk - 1);
53835373
if (ret) {
53845374
up_write(&EXT4_I(inode)->i_data_sem);
5385-
goto out_stop;
5375+
goto out_handle;
53865376
}
53875377
ext4_discard_preallocations(inode);
53885378

5389-
ret = ext4_ext_shift_extents(inode, handle, punch_stop,
5390-
punch_stop - punch_start, SHIFT_LEFT);
5379+
ret = ext4_ext_shift_extents(inode, handle, end_lblk,
5380+
end_lblk - start_lblk, SHIFT_LEFT);
53915381
if (ret) {
53925382
up_write(&EXT4_I(inode)->i_data_sem);
5393-
goto out_stop;
5383+
goto out_handle;
53945384
}
53955385

53965386
new_size = inode->i_size - len;
53975387
i_size_write(inode, new_size);
53985388
EXT4_I(inode)->i_disksize = new_size;
53995389

54005390
up_write(&EXT4_I(inode)->i_data_sem);
5401-
if (IS_SYNC(inode))
5402-
ext4_handle_sync(handle);
54035391
ret = ext4_mark_inode_dirty(handle, inode);
5392+
if (ret)
5393+
goto out_handle;
5394+
54045395
ext4_update_inode_fsync_trans(handle, inode, 1);
5396+
if (IS_SYNC(inode))
5397+
ext4_handle_sync(handle);
54055398

5406-
out_stop:
5399+
out_handle:
54075400
ext4_journal_stop(handle);
5408-
out_mmap:
5401+
out_invalidate_lock:
54095402
filemap_invalidate_unlock(mapping);
5410-
out_mutex:
5403+
out:
54115404
inode_unlock(inode);
54125405
return ret;
54135406
}

0 commit comments

Comments
 (0)