From bbfd062db86a8cfa75adc9118bd6e33a8a8f23f5 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sat, 19 Apr 2014 16:37:47 -0400 Subject: [PATCH] add patch fix-collapse-range-failure-with-1k-block-size --- fix-collapse-range-failure-with-1k-block-size | 64 +++++++++++++++++++++++++++ series | 1 + 2 files changed, 65 insertions(+) create mode 100644 fix-collapse-range-failure-with-1k-block-size diff --git a/fix-collapse-range-failure-with-1k-block-size b/fix-collapse-range-failure-with-1k-block-size new file mode 100644 index 00000000..838f49cc --- /dev/null +++ b/fix-collapse-range-failure-with-1k-block-size @@ -0,0 +1,64 @@ +ext4: fix COLLAPSE_RANGE failure with 1KB block size + +From: Namjae Jeon + +When formatting with 1KB or 2KB(not aligned with PAGE SIZE) block +size, xfstests generic/075 and 091 are failing. The offset supplied to +function truncate_pagecache_range is block size aligned. In this +function start offset is re-aligned to PAGE_SIZE by rounding_up to the +next page boundary. Due to this rounding up, old data remains in the +page cache when blocksize is less than page size and start offset is +not aligned with page size. In case of collapse range, we need to +align start offset to page size boundary by doing a round down +operation instead of round up. + +Signed-off-by: Namjae Jeon +Signed-off-by: Ashish Sangwan +Signed-off-by: "Theodore Ts'o" +--- + fs/ext4/extents.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 9b9251a..4cf8c5b 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -5395,7 +5395,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) + ext4_lblk_t punch_start, punch_stop; + handle_t *handle; + unsigned int credits; +- loff_t new_size; ++ loff_t new_size, ioffset; + int ret; + + /* Collapse range works only on fs block size aligned offsets. */ +@@ -5418,8 +5418,15 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) + return ret; + } + ++ /* ++ * Need to round down offset to be aligned with page size boundary ++ * for page size > block size. ++ */ ++ ioffset = round_down(offset, PAGE_SIZE); ++ + /* Write out all dirty pages */ +- ret = filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX); ++ ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, ++ LLONG_MAX); + if (ret) + return ret; + +@@ -5441,7 +5448,7 @@ int ext4_collapse_range(struct inode *inode, loff_t offset, loff_t len) + goto out_mutex; + } + +- truncate_pagecache(inode, offset); ++ truncate_pagecache(inode, ioffset); + + /* Wait for existing dio to complete */ + ext4_inode_block_unlocked_dio(inode); +-- +1.7.11-rc0 + + diff --git a/series b/series index dabb0b87..b9706f48 100644 --- a/series +++ b/series @@ -29,6 +29,7 @@ discard-preallocations-after-removing-space fix-extent-merging-in-ext4_shift_path_extents enforce-regular-file-in-ext4_zero_range use-EINVAL-if-not-regular-file-in-ext4_collapse_range +fix-collapse-range-failure-with-1k-block-size # ^^^ above are to be pushed to Linus for 3.15-rc1 -- 2.11.4.GIT