diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-07-18 16:55:52 +0200 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-07-18 16:55:52 +0200 |
| commit | 93467b31bec6da512b51544e5e4584f2745e995e (patch) | |
| tree | 2ea2be38c5e4dc9aafffbbc0db5aae0f6513a1d9 /mm/khugepaged.c | |
| parent | 8ca1f4c6fb1462ee120730ea75c19da10d2f2d6f (diff) | |
| parent | 7a5cef0db4795d9d453a12e0f61b5b7634fc4d40 (diff) | |
| download | linux-stable-linux-rolling-stable.tar.gz linux-stable-linux-rolling-stable.zip | |
Merge v7.1.4linux-rolling-stable
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'mm/khugepaged.c')
| -rw-r--r-- | mm/khugepaged.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/mm/khugepaged.c b/mm/khugepaged.c index b8452dbdb043..d6e04041f5dc 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -2094,32 +2094,43 @@ out_unlock: goto xa_unlocked; } - if (!is_shmem) { +xa_locked: + xas_unlock_irq(&xas); +xa_unlocked: + + /* + * If collapse is successful, flush must be done now before copying. + * If collapse is unsuccessful, does flush actually need to be done? + * Do it anyway, to clear the state. + */ + try_to_unmap_flush(); + + if (result == SCAN_SUCCEED && !is_shmem && !mapping_large_folio_support(mapping)) { + /* + * invalidate_lock as shared excludes against concurrent opens + * in do_dentry_open() truncating the page cache. This is + * particularly important if there are dirty folios in transit. + */ + filemap_invalidate_lock_shared(mapping); filemap_nr_thps_inc(mapping); /* * Paired with the fence in do_dentry_open() -> get_write_access() * to ensure i_writecount is up to date and the update to nr_thps * is visible. Ensures the page cache will be truncated if the - * file is opened writable. + * file is opened writable. If collapse looks to be successful, + * flush any dirty pages out the page cache. With the nr_thps + * incremented, there won't be any new writers (nor new dirties). */ smp_mb(); - if (inode_is_open_for_write(mapping->host)) { + if (inode_is_open_for_write(mapping->host) || filemap_write_and_wait(mapping)) { result = SCAN_FAIL; filemap_nr_thps_dec(mapping); + filemap_invalidate_unlock_shared(mapping); + goto rollback; } + filemap_invalidate_unlock_shared(mapping); } -xa_locked: - xas_unlock_irq(&xas); -xa_unlocked: - - /* - * If collapse is successful, flush must be done now before copying. - * If collapse is unsuccessful, does flush actually need to be done? - * Do it anyway, to clear the state. - */ - try_to_unmap_flush(); - if (result == SCAN_SUCCEED && nr_none && !shmem_charge(mapping->host, nr_none)) result = SCAN_FAIL; |
