Skip to content

Commit b44679c

Browse files
Long Librauner
authored andcommitted
iomap: pass byte granular end position to iomap_add_to_ioend
This is a preparatory patch for fixing zero padding issues in concurrent append write scenarios. In the following patches, we need to obtain byte-granular writeback end position for io_size trimming after EOF handling. Due to concurrent writeback and truncate operations, inode size may shrink. Resampling inode size would force writeback code to handle the newly appeared post-EOF blocks, which is undesirable. As Dave explained in [1]: "Really, the issue is that writeback mappings have to be able to handle the range being mapped suddenly appear to be beyond EOF. This behaviour is a longstanding writeback constraint, and is what iomap_writepage_handle_eof() is attempting to handle. We handle this by only sampling i_size_read() whilst we have the folio locked and can determine the action we should take with that folio (i.e. nothing, partial zeroing, or skip altogether). Once we've made the decision that the folio is within EOF and taken action on it (i.e. moved the folio to writeback state), we cannot then resample the inode size because a truncate may have started and changed the inode size." To avoid resampling inode size after EOF handling, we convert end_pos to byte-granular writeback position and return it from EOF handling function. Since iomap_set_range_dirty() can handle unaligned lengths, this conversion has no impact on it. However, iomap_find_dirty_range() requires aligned start and end range to find dirty blocks within the given range, so the end position needs to be rounded up when passed to it. LINK [1]: https://lore.kernel.org/linux-xfs/[email protected]/ Signed-off-by: Long Li <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Brian Foster <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent 930e7c2 commit b44679c

File tree

1 file changed

+12
-9
lines changed

1 file changed

+12
-9
lines changed

fs/iomap/buffered-io.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1774,7 +1774,8 @@ static bool iomap_can_add_to_ioend(struct iomap_writepage_ctx *wpc, loff_t pos)
17741774
*/
17751775
static int iomap_add_to_ioend(struct iomap_writepage_ctx *wpc,
17761776
struct writeback_control *wbc, struct folio *folio,
1777-
struct inode *inode, loff_t pos, unsigned len)
1777+
struct inode *inode, loff_t pos, loff_t end_pos,
1778+
unsigned len)
17781779
{
17791780
struct iomap_folio_state *ifs = folio->private;
17801781
size_t poff = offset_in_folio(folio, pos);
@@ -1800,8 +1801,8 @@ static int iomap_add_to_ioend(struct iomap_writepage_ctx *wpc,
18001801

18011802
static int iomap_writepage_map_blocks(struct iomap_writepage_ctx *wpc,
18021803
struct writeback_control *wbc, struct folio *folio,
1803-
struct inode *inode, u64 pos, unsigned dirty_len,
1804-
unsigned *count)
1804+
struct inode *inode, u64 pos, u64 end_pos,
1805+
unsigned dirty_len, unsigned *count)
18051806
{
18061807
int error;
18071808

@@ -1826,7 +1827,7 @@ static int iomap_writepage_map_blocks(struct iomap_writepage_ctx *wpc,
18261827
break;
18271828
default:
18281829
error = iomap_add_to_ioend(wpc, wbc, folio, inode, pos,
1829-
map_len);
1830+
end_pos, map_len);
18301831
if (!error)
18311832
(*count)++;
18321833
break;
@@ -1897,11 +1898,11 @@ static bool iomap_writepage_handle_eof(struct folio *folio, struct inode *inode,
18971898
* remaining memory is zeroed when mapped, and writes to that
18981899
* region are not written out to the file.
18991900
*
1900-
* Also adjust the writeback range to skip all blocks entirely
1901-
* beyond i_size.
1901+
* Also adjust the end_pos to the end of file and skip writeback
1902+
* for all blocks entirely beyond i_size.
19021903
*/
19031904
folio_zero_segment(folio, poff, folio_size(folio));
1904-
*end_pos = round_up(isize, i_blocksize(inode));
1905+
*end_pos = isize;
19051906
}
19061907

19071908
return true;
@@ -1914,6 +1915,7 @@ static int iomap_writepage_map(struct iomap_writepage_ctx *wpc,
19141915
struct inode *inode = folio->mapping->host;
19151916
u64 pos = folio_pos(folio);
19161917
u64 end_pos = pos + folio_size(folio);
1918+
u64 end_aligned = 0;
19171919
unsigned count = 0;
19181920
int error = 0;
19191921
u32 rlen;
@@ -1955,9 +1957,10 @@ static int iomap_writepage_map(struct iomap_writepage_ctx *wpc,
19551957
/*
19561958
* Walk through the folio to find dirty areas to write back.
19571959
*/
1958-
while ((rlen = iomap_find_dirty_range(folio, &pos, end_pos))) {
1960+
end_aligned = round_up(end_pos, i_blocksize(inode));
1961+
while ((rlen = iomap_find_dirty_range(folio, &pos, end_aligned))) {
19591962
error = iomap_writepage_map_blocks(wpc, wbc, folio, inode,
1960-
pos, rlen, &count);
1963+
pos, end_pos, rlen, &count);
19611964
if (error)
19621965
break;
19631966
pos += rlen;

0 commit comments

Comments
 (0)