mm: Account dirty folios properly during splits

If the last folio in a file is split as a result of truncation,
we simply clear the dirty bits for the pages we're discarding.
That causes NR_FILE_DIRTY (among other counters) to be thrown off
and eventually Linux will hang in balance_dirty_pages_ratelimited()
Reported-by: default avatarDave Chinner <dchinner@redhat.com>
Tested-by: default avatarDave Chinner <dchinner@redhat.com>
Tested-by: default avatarDarrick J. Wong <djwong@kernel.org>
Fixes: d68eccad ("mm/filemap: Allow large folios to be added to the page cache")
Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
parent 0840a791
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/shrinker.h> #include <linux/shrinker.h>
#include <linux/mm_inline.h> #include <linux/mm_inline.h>
#include <linux/swapops.h> #include <linux/swapops.h>
#include <linux/backing-dev.h>
#include <linux/dax.h> #include <linux/dax.h>
#include <linux/khugepaged.h> #include <linux/khugepaged.h>
#include <linux/freezer.h> #include <linux/freezer.h>
...@@ -2440,11 +2441,15 @@ static void __split_huge_page(struct page *page, struct list_head *list, ...@@ -2440,11 +2441,15 @@ static void __split_huge_page(struct page *page, struct list_head *list,
__split_huge_page_tail(head, i, lruvec, list); __split_huge_page_tail(head, i, lruvec, list);
/* Some pages can be beyond EOF: drop them from page cache */ /* Some pages can be beyond EOF: drop them from page cache */
if (head[i].index >= end) { if (head[i].index >= end) {
ClearPageDirty(head + i); struct folio *tail = page_folio(head + i);
__delete_from_page_cache(head + i, NULL);
if (shmem_mapping(head->mapping)) if (shmem_mapping(head->mapping))
shmem_uncharge(head->mapping->host, 1); shmem_uncharge(head->mapping->host, 1);
put_page(head + i); else if (folio_test_clear_dirty(tail))
folio_account_cleaned(tail,
inode_to_wb(folio->mapping->host));
__filemap_remove_folio(tail, NULL);
folio_put(tail);
} else if (!PageAnon(page)) { } else if (!PageAnon(page)) {
__xa_store(&head->mapping->i_pages, head[i].index, __xa_store(&head->mapping->i_pages, head[i].index,
head + i, 0); head + i, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment