diff options
author | Qu Wenruo <quwenruo@cn.fujitsu.com> | 2015-10-14 03:26:13 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-10-20 22:07:29 -0400 |
commit | 0f6925fa2907df58496cabc33fa4677c635e2223 (patch) | |
tree | 85b4f57ea06fb3f0b0cbb50412742d64719defbb /fs | |
parent | dc6c5fb3b514221f2e9d21ee626a9d95d3418dff (diff) |
btrfs: Avoid truncate tailing page if fallocate range doesn't exceed inode size
Current code will always truncate tailing page if its alloc_start is
smaller than inode size.
For example, the file extent layout is like:
0 4K 8K 16K 32K
|<-----Extent A---------------->|
|<--Inode size: 18K---------->|
But if calling fallocate even for range [0,4K), it will cause btrfs to
re-truncate the range [16,32K), causing COW and a new extent.
0 4K 8K 16K 32K
|///////| <- Fallocate call range
|<-----Extent A-------->|<--B-->|
The cause is quite easy, just a careless btrfs_truncate_inode() in a
else branch without extra judgment.
Fix it by add judgment on whether the fallocate range is beyond isize.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/file.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index b823fac91c92..8c6f247ba81d 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -2584,7 +2584,7 @@ static long btrfs_fallocate(struct file *file, int mode, | |||
2584 | alloc_start); | 2584 | alloc_start); |
2585 | if (ret) | 2585 | if (ret) |
2586 | goto out; | 2586 | goto out; |
2587 | } else { | 2587 | } else if (offset + len > inode->i_size) { |
2588 | /* | 2588 | /* |
2589 | * If we are fallocating from the end of the file onward we | 2589 | * If we are fallocating from the end of the file onward we |
2590 | * need to zero out the end of the page if i_size lands in the | 2590 | * need to zero out the end of the page if i_size lands in the |