iomap: don't increase i_size if it's not a write operation
Increase i_size in iomap_zero_range() and iomap_unshare_iter() is not needed, the caller should handle it. Especially, when truncate partial block, we should not increase i_size beyond the new EOF here. It doesn't affect xfs and gfs2 now because they set the new file size after zero out, it doesn't matter that a transient increase in i_size, but it will affect ext4 because it set file size before truncate. So move the i_size updating logic to iomap_write_iter(). Signed-off-by: Zhang Yi <yi.zhang@huawei.com> Link: https://lore.kernel.org/r/20240320110548.2200662-7-yi.zhang@huaweicloud.com Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
89c6c1d91a
commit
943bc0882c
|
@ -875,32 +875,13 @@ static size_t iomap_write_end(struct iomap_iter *iter, loff_t pos, size_t len,
|
|||
size_t copied, struct folio *folio)
|
||||
{
|
||||
const struct iomap *srcmap = iomap_iter_srcmap(iter);
|
||||
loff_t old_size = iter->inode->i_size;
|
||||
size_t ret;
|
||||
|
||||
if (srcmap->type == IOMAP_INLINE) {
|
||||
ret = iomap_write_end_inline(iter, folio, pos, copied);
|
||||
} else if (srcmap->flags & IOMAP_F_BUFFER_HEAD) {
|
||||
ret = block_write_end(NULL, iter->inode->i_mapping, pos, len,
|
||||
copied, &folio->page, NULL);
|
||||
} else {
|
||||
ret = __iomap_write_end(iter->inode, pos, len, copied, folio);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the in-memory inode size after copying the data into the page
|
||||
* cache. It's up to the file system to write the updated size to disk,
|
||||
* preferably after I/O completion so that no stale data is exposed.
|
||||
*/
|
||||
if (pos + ret > old_size) {
|
||||
i_size_write(iter->inode, pos + ret);
|
||||
iter->iomap.flags |= IOMAP_F_SIZE_CHANGED;
|
||||
}
|
||||
__iomap_put_folio(iter, pos, ret, folio);
|
||||
|
||||
if (old_size < pos)
|
||||
pagecache_isize_extended(iter->inode, old_size, pos);
|
||||
return ret;
|
||||
if (srcmap->type == IOMAP_INLINE)
|
||||
return iomap_write_end_inline(iter, folio, pos, copied);
|
||||
if (srcmap->flags & IOMAP_F_BUFFER_HEAD)
|
||||
return block_write_end(NULL, iter->inode->i_mapping, pos, len,
|
||||
copied, &folio->page, NULL);
|
||||
return __iomap_write_end(iter->inode, pos, len, copied, folio);
|
||||
}
|
||||
|
||||
static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
|
||||
|
@ -915,6 +896,7 @@ static loff_t iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i)
|
|||
|
||||
do {
|
||||
struct folio *folio;
|
||||
loff_t old_size;
|
||||
size_t offset; /* Offset into folio */
|
||||
size_t bytes; /* Bytes to write to folio */
|
||||
size_t copied; /* Bytes copied from user */
|
||||
|
@ -964,6 +946,22 @@ retry:
|
|||
copied = copy_folio_from_iter_atomic(folio, offset, bytes, i);
|
||||
status = iomap_write_end(iter, pos, bytes, copied, folio);
|
||||
|
||||
/*
|
||||
* Update the in-memory inode size after copying the data into
|
||||
* the page cache. It's up to the file system to write the
|
||||
* updated size to disk, preferably after I/O completion so that
|
||||
* no stale data is exposed. Only once that's done can we
|
||||
* unlock and release the folio.
|
||||
*/
|
||||
old_size = iter->inode->i_size;
|
||||
if (pos + status > old_size) {
|
||||
i_size_write(iter->inode, pos + status);
|
||||
iter->iomap.flags |= IOMAP_F_SIZE_CHANGED;
|
||||
}
|
||||
__iomap_put_folio(iter, pos, status, folio);
|
||||
|
||||
if (old_size < pos)
|
||||
pagecache_isize_extended(iter->inode, old_size, pos);
|
||||
if (status < bytes)
|
||||
iomap_write_failed(iter->inode, pos + status,
|
||||
bytes - status);
|
||||
|
@ -1336,6 +1334,7 @@ static loff_t iomap_unshare_iter(struct iomap_iter *iter)
|
|||
bytes = folio_size(folio) - offset;
|
||||
|
||||
bytes = iomap_write_end(iter, pos, bytes, bytes, folio);
|
||||
__iomap_put_folio(iter, pos, bytes, folio);
|
||||
if (WARN_ON_ONCE(bytes == 0))
|
||||
return -EIO;
|
||||
|
||||
|
@ -1400,6 +1399,7 @@ static loff_t iomap_zero_iter(struct iomap_iter *iter, bool *did_zero)
|
|||
folio_mark_accessed(folio);
|
||||
|
||||
bytes = iomap_write_end(iter, pos, bytes, bytes, folio);
|
||||
__iomap_put_folio(iter, pos, bytes, folio);
|
||||
if (WARN_ON_ONCE(bytes == 0))
|
||||
return -EIO;
|
||||
|
||||
|
|
Loading…
Reference in New Issue