Skip to content

Commit 0841ea4

Browse files
zhangyi089brauner
authored andcommitted
iomap: keep on increasing i_size in iomap_write_end()
Commit '943bc0882ceb ("iomap: don't increase i_size if it's not a write operation")' breaks xfs with realtime device on generic/561, the problem is when unaligned truncate down a xfs realtime inode with rtextsize > 1 fs block, xfs only zero out the EOF block but doesn't zero out the tail blocks that aligned to rtextsize, so if we don't increase i_size in iomap_write_end(), it could expose stale data after we do an append write beyond the aligned EOF block. xfs should zero out the tail blocks when truncate down, but before we finish that, let's fix the issue by just revert the changes in iomap_write_end(). Fixes: 943bc08 ("iomap: don't increase i_size if it's not a write operation") Reported-by: Chandan Babu R <[email protected]> Link: https://lore.kernel.org/linux-xfs/[email protected] Signed-off-by: Zhang Yi <[email protected]> Link: https://lore.kernel.org/r/[email protected] Tested-by: Chandan Babu R <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent 3d11749 commit 0841ea4

File tree

1 file changed

+24
-29
lines changed

1 file changed

+24
-29
lines changed

fs/iomap/buffered-io.c

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -877,22 +877,37 @@ static bool iomap_write_end(struct iomap_iter *iter, loff_t pos, size_t len,
877877
size_t copied, struct folio *folio)
878878
{
879879
const struct iomap *srcmap = iomap_iter_srcmap(iter);
880+
loff_t old_size = iter->inode->i_size;
881+
size_t written;
880882

881883
if (srcmap->type == IOMAP_INLINE) {
882884
iomap_write_end_inline(iter, folio, pos, copied);
883-
return true;
885+
written = copied;
886+
} else if (srcmap->flags & IOMAP_F_BUFFER_HEAD) {
887+
written = block_write_end(NULL, iter->inode->i_mapping, pos,
888+
len, copied, &folio->page, NULL);
889+
WARN_ON_ONCE(written != copied && written != 0);
890+
} else {
891+
written = __iomap_write_end(iter->inode, pos, len, copied,
892+
folio) ? copied : 0;
884893
}
885894

886-
if (srcmap->flags & IOMAP_F_BUFFER_HEAD) {
887-
size_t bh_written;
888-
889-
bh_written = block_write_end(NULL, iter->inode->i_mapping, pos,
890-
len, copied, &folio->page, NULL);
891-
WARN_ON_ONCE(bh_written != copied && bh_written != 0);
892-
return bh_written == copied;
895+
/*
896+
* Update the in-memory inode size after copying the data into the page
897+
* cache. It's up to the file system to write the updated size to disk,
898+
* preferably after I/O completion so that no stale data is exposed.
899+
* Only once that's done can we unlock and release the folio.
900+
*/
901+
if (pos + written > old_size) {
902+
i_size_write(iter->inode, pos + written);
903+
iter->iomap.flags |= IOMAP_F_SIZE_CHANGED;
893904
}
905+
__iomap_put_folio(iter, pos, written, folio);
894906

895-
return __iomap_write_end(iter->inode, pos, len, copied, folio);
907+
if (old_size < pos)
908+
pagecache_isize_extended(iter->inode, old_size, pos);
909+
910+
return written == copied;
896911
}
897912

898913
static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
@@ -907,7 +922,6 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
907922

908923
do {
909924
struct folio *folio;
910-
loff_t old_size;
911925
size_t offset; /* Offset into folio */
912926
size_t bytes; /* Bytes to write to folio */
913927
size_t copied; /* Bytes copied from user */
@@ -959,23 +973,6 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
959973
written = iomap_write_end(iter, pos, bytes, copied, folio) ?
960974
copied : 0;
961975

962-
/*
963-
* Update the in-memory inode size after copying the data into
964-
* the page cache. It's up to the file system to write the
965-
* updated size to disk, preferably after I/O completion so that
966-
* no stale data is exposed. Only once that's done can we
967-
* unlock and release the folio.
968-
*/
969-
old_size = iter->inode->i_size;
970-
if (pos + written > old_size) {
971-
i_size_write(iter->inode, pos + written);
972-
iter->iomap.flags |= IOMAP_F_SIZE_CHANGED;
973-
}
974-
__iomap_put_folio(iter, pos, written, folio);
975-
976-
if (old_size < pos)
977-
pagecache_isize_extended(iter->inode, old_size, pos);
978-
979976
cond_resched();
980977
if (unlikely(written == 0)) {
981978
/*
@@ -1346,7 +1343,6 @@ static loff_t iomap_unshare_iter(struct iomap_iter *iter)
13461343
bytes = folio_size(folio) - offset;
13471344

13481345
ret = iomap_write_end(iter, pos, bytes, bytes, folio);
1349-
__iomap_put_folio(iter, pos, bytes, folio);
13501346
if (WARN_ON_ONCE(!ret))
13511347
return -EIO;
13521348

@@ -1412,7 +1408,6 @@ static loff_t iomap_zero_iter(struct iomap_iter *iter, bool *did_zero)
14121408
folio_mark_accessed(folio);
14131409

14141410
ret = iomap_write_end(iter, pos, bytes, bytes, folio);
1415-
__iomap_put_folio(iter, pos, bytes, folio);
14161411
if (WARN_ON_ONCE(!ret))
14171412
return -EIO;
14181413

0 commit comments

Comments
 (0)