diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2019-06-27 17:28:40 -0700 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2019-06-27 17:28:40 -0700 |
commit | 8d3e72a180b42c01ec00045e1bb8eb91175adafe (patch) | |
tree | 28ceebc6e241391ac9a4f1a44e9da6122d02ba37 /fs/iomap.c | |
parent | d1fdb6d8f6a4109a4263176c84b899076a5f8008 (diff) | |
download | linux-8d3e72a180b42c01ec00045e1bb8eb91175adafe.tar.bz2 |
iomap: don't mark the inode dirty in iomap_write_end
Marking the inode dirty for each page copied into the page cache can be
very inefficient for file systems that use the VFS dirty inode tracking,
and is completely pointless for those that don't use the VFS dirty inode
tracking. So instead, only set an iomap flag when changing the in-core
inode size, and open code the rest of __generic_write_end.
Partially based on code from Christoph Hellwig.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs/iomap.c')
-rw-r--r-- | fs/iomap.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/fs/iomap.c b/fs/iomap.c index 23ef63fd1669..c4acf69b7196 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -773,6 +773,7 @@ iomap_write_end(struct inode *inode, loff_t pos, unsigned len, unsigned copied, struct page *page, struct iomap *iomap) { const struct iomap_page_ops *page_ops = iomap->page_ops; + loff_t old_size = inode->i_size; int ret; if (iomap->type == IOMAP_INLINE) { @@ -784,7 +785,19 @@ iomap_write_end(struct inode *inode, loff_t pos, unsigned len, ret = __iomap_write_end(inode, pos, len, copied, page, iomap); } - __generic_write_end(inode, pos, ret, page); + /* + * 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(inode, pos + ret); + iomap->flags |= IOMAP_F_SIZE_CHANGED; + } + unlock_page(page); + + if (old_size < pos) + pagecache_isize_extended(inode, old_size, pos); if (page_ops && page_ops->page_done) page_ops->page_done(inode, pos, copied, page, iomap); put_page(page); |