Commit ab70155b authored by Long Li's avatar Long Li
Browse files

iomap: Ensure sub-page dirty state is set during mmap writes

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I9UNQS


CVE: NA

------------------------------------------

While running xfstests, specifically test xfs/032, the following errors
were reported:

 XFS (sdb): ino 4a data fork has delalloc extent at [0x3c:0x10]
 XFS: Assertion failed: 0, file: fs/xfs/xfs_icache.c, line: 1854

The issue stems from the dirty state of sub-pages not being set during mmap
writes. This behavior was observed after the introduction of the commit
99e9a55b ("iomap: add support to track dirty state of sub-pages"),
which enabled iomap to track the dirty state of sub-pages when the block
size is smaller than the page size. Currently, iomap updates the sub-page
dirty state only in `__iomap_write_end()`. However, the mmap write path
does not invoke this function, resulting in dirty pages created by mmap
writes not being scheduled for write-back.

This patch fixes the issue by ensuring that the sub-page dirty state is
set during mmap writes.

Fixes: 99e9a55b ("iomap: add support to track dirty state of sub pages")
Signed-off-by: default avatarLong Li <leo.lilong@huawei.com>
parent cd49bc20
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -158,9 +158,6 @@ iomap_set_range_dirty(struct page *page, unsigned int off, unsigned int len)
	if (PageError(page))
		return;

	if (len)
		iomap_set_page_dirty(page);

	if (!page_has_private(page))
		return;

@@ -757,6 +754,7 @@ static size_t __iomap_write_end(struct inode *inode, loff_t pos, size_t len,
	if (unlikely(copied < len && !PageUptodate(page)))
		return 0;
	iomap_set_range_uptodate(page, offset_in_page(pos), len);
	iomap_set_page_dirty(page);
	iomap_set_range_dirty(page, offset_in_page(pos), len);
	return copied;
}
@@ -1075,6 +1073,7 @@ iomap_page_mkwrite_actor(struct inode *inode, loff_t pos, loff_t length,
		WARN_ON_ONCE(!PageUptodate(page));
		iomap_page_create(inode, page);
		set_page_dirty(page);
		iomap_set_range_dirty(page, offset_in_page(pos), length);
	}

	return length;