Skip to content

Commit 0a417b8

Browse files
jankaradjwong
authored andcommitted
xfs: Timely free truncated dirty pages
Commit 99579cc "xfs: skip dirty pages in ->releasepage()" started to skip dirty pages in xfs_vm_releasepage() which also has the effect that if a dirty page is truncated, it does not get freed by block_invalidatepage() and is lingering in LRU list waiting for reclaim. So a simple loop like: while true; do dd if=/dev/zero of=file bs=1M count=100 rm file done will keep using more and more memory until we hit low watermarks and start pagecache reclaim which will eventually reclaim also the truncate pages. Keeping these truncated (and thus never usable) pages in memory is just a waste of memory, is unnecessarily stressing page cache reclaim, and reportedly also leads to anonymous mmap(2) returning ENOMEM prematurely. So instead of just skipping dirty pages in xfs_vm_releasepage(), return to old behavior of skipping them only if they have delalloc or unwritten buffers and fix the spurious warnings by warning only if the page is clean. CC: [email protected] CC: Brian Foster <[email protected]> CC: Vlastimil Babka <[email protected]> Reported-by: Petr Tůma <[email protected]> Fixes: 99579cc Signed-off-by: Jan Kara <[email protected]> Reviewed-by: Brian Foster <[email protected]> Signed-off-by: Darrick J. Wong <[email protected]>
1 parent 84a4620 commit 0a417b8

File tree

1 file changed

+11
-8
lines changed

1 file changed

+11
-8
lines changed

fs/xfs/xfs_aops.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,19 +1152,22 @@ xfs_vm_releasepage(
11521152
* block_invalidatepage() can send pages that are still marked dirty
11531153
* but otherwise have invalidated buffers.
11541154
*
1155-
* We've historically freed buffers on the latter. Instead, quietly
1156-
* filter out all dirty pages to avoid spurious buffer state warnings.
1157-
* This can likely be removed once shrink_active_list() is fixed.
1155+
* We want to release the latter to avoid unnecessary buildup of the
1156+
* LRU, skip the former and warn if we've left any lingering
1157+
* delalloc/unwritten buffers on clean pages. Skip pages with delalloc
1158+
* or unwritten buffers and warn if the page is not dirty. Otherwise
1159+
* try to release the buffers.
11581160
*/
1159-
if (PageDirty(page))
1160-
return 0;
1161-
11621161
xfs_count_page_state(page, &delalloc, &unwritten);
11631162

1164-
if (WARN_ON_ONCE(delalloc))
1163+
if (delalloc) {
1164+
WARN_ON_ONCE(!PageDirty(page));
11651165
return 0;
1166-
if (WARN_ON_ONCE(unwritten))
1166+
}
1167+
if (unwritten) {
1168+
WARN_ON_ONCE(!PageDirty(page));
11671169
return 0;
1170+
}
11681171

11691172
return try_to_free_buffers(page);
11701173
}

0 commit comments

Comments
 (0)