Skip to content

[26.04_linux-nvidia]: Backport: "mm/gup: fix GUP-fast fallback for NULL-mapping order-0 folios" - #531

Closed
jamieNguyenNVIDIA wants to merge 1 commit into
NVIDIA:26.04_linux-nvidiafrom
jamieNguyenNVIDIA:jamien/7.0/gup-fast-null-mapping
Closed

[26.04_linux-nvidia]: Backport: "mm/gup: fix GUP-fast fallback for NULL-mapping order-0 folios"#531
jamieNguyenNVIDIA wants to merge 1 commit into
NVIDIA:26.04_linux-nvidiafrom
jamieNguyenNVIDIA:jamien/7.0/gup-fast-null-mapping

Conversation

@jamieNguyenNVIDIA

Copy link
Copy Markdown
Collaborator

Target: 26.04_linux-nvidia · Topic: jamien/7.0/gup-fast-null-mapping · Base: c5d9f1a36baea

Clean cherry-pick from linux-next:

(cherry picked from commit ae75e88d8c258fd849de594e7d468b5263e7b3e3 linux-next)

John Hubbard, Acked-by David Hildenbrand, applied by Andrew Morton.
Lore thread.

Problem

f002882ca369 (present on this branch) made gup_fast_folio_allowed() bail to the
slow path for any order-0 folio with a NULL ->mapping when CONFIG_SECRETMEM=y.
Pages from alloc_page() + vm_insert_page() legitimately have a NULL mapping, so
every pin_user_pages_fast() over such a range misses the fast path — nvidia-fs
(GPUDirect Storage) allocates its shadow buffers exactly this way.

The NULL check was meant to catch truncated file-backed pages, not secretmem.
Secretmem folios are published via filemap_add_folio(), which always sets
->mapping, so a NULL mapping proves the folio is not secretmem. Returning
!reject_file_backed keeps long-term writable pins on the slow path and restores
the fast path otherwise — exactly the pre-f002882ca369 behaviour.

CONFIG_SECRETMEM=y on amd64 and arm64, so this is live on every flavour we ship.

Measurement (GH200, 288 cores)

A module reproducing the nvidia-fs pattern (alloc_page + vm_insert_page, then
pin_user_pages_fast(..., FOLL_WRITE, ...)), with an anonymous-memory control the
patch cannot affect. get_user_pages_fast_only() gives the GUP-fast verdict
directly: 0/N unpatched, N/N patched.

Median ns/page, 512 pages/thread, 5 reps:

threads 4K unpatched → patched 64K unpatched → patched
1 34 → 34 (1.0x) 33 → 30 (1.1x)
8 74 → 33 (2.2x) 1920 → 31 (62x)
32 95 → 33 (2.9x) 4792 → 33 (145x)
128 500 → 218 (noisy) 16673 → 76 (219x)

The anon control held at 30-35 ns/page across all four kernels, so only the affected
range moved. Stock 7.0.0-1015-nvidia-64k independently reproduces the unpatched 64K
numbers (8 threads: 1176 vs 37), so this isn't a test-config artefact.

Single-threaded it's a wash; the win is under concurrency. perf on the unpatched
64K kernel shows the slow path is ~90% lock contention (queued_spin_lock_slowpath
72%), gone entirely once patched — contention that scales with thread count, not a
fixed per-page cost.

Risk

Low. One line in a static function with three callers, all in GUP-fast. Only
reject_file_backed == false && check_secretmem && mapping == NULL changes
behaviour; long-term writable pins are untouched.

A secretmem folio caught mid-truncate can't happen here: secretmem_setattr()
refuses to shrink, there's no .fallocate (so no punch-hole), and
secretmem_migrate_folio() returns -EBUSY. Only inode eviction remains, which
requires every VMA gone — no VMA, no PTE for GUP-fast to walk. Raised by David
Hildenbrand on v1 and resolved before he Acked.

Testing

Applies cleanly; built arm64 4K/64K and x86_64, no new warnings; verified in the
binary (unpatched mov w0, #0x0 vs patched eor w0, w0, #0x1); benchmarked as above.

Bugs

nvbug: 6064778
LP: https://bugs.launchpad.net/ubuntu/+source/linux-nvidia-7.0/+bug/2162917

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

PR Validation Report

Patchscan ✅ No Missing Fixes

All cherry-picked commits checked — no missing upstream fixes found.

PR Lint ❌ Errors found

Details
Checking 1 commits...

Cherry-pick digest:
┌──────────────┬──────────────────────────────────────────────────────────────────┬────────────┬─────────┬───────────────────────────┐
│ Local        │ Referenced upstream / Patch subject                              │ Patch-ID   │ Subject │ SoB chain                 │
├──────────────┼──────────────────────────────────────────────────────────────────┼────────────┼─────────┼───────────────────────────┤
│ 3d700fb5ab3a │ [SAUCE] mm/gup: fix gup-fast fallback for null-mapping order-0 f │ N/A        │ N/A     │ jhubbard, akpm, jamien    │
└──────────────┴──────────────────────────────────────────────────────────────────┴────────────┴─────────┴───────────────────────────┘

Lint results:
E: 3d700fb5ab3a ("mm/gup: fix GUP-fast fallback for NULL-mapping ord"): not SAUCE/UBUNTU/Revert but has no upstream reference trailer (cherry picked from commit ... or backported from ...)

@nirmoy nirmoy left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acked-by: Nirmoy Das <nirmoyd@nvidia.com>

@clsotog clsotog left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acked-by: Carol L Soto <csoto@nvidia.com>

@nvmochs

nvmochs commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Since commit f002882 ("mm: merge folio_is_secretmem() and
folio_fast_pin_allowed() into gup_fast_folio_allowed()"),
gup_fast_folio_allowed() falls back to the slow path for any order-0 folio
with a NULL mapping when CONFIG_SECRETMEM=y.  This causes a performance
regression for drivers that allocate pages with alloc_page() and insert
them into VMAs via vm_insert_page().  These pages legitimately have a NULL
folio->mapping, but they cannot be secretmem pages.

Secretmem pages are always added to the secretmem inode's page cache via
filemap_add_folio(), which sets folio->mapping to the inode's i_mapping.
A folio with a NULL mapping can never be a secretmem folio.  The
NULL-mapping check was intended to handle truncated file-backed pages (a
reject_file_backed concern), not secretmem detection.

When only check_secretmem is true (and reject_file_backed is false), a
NULL mapping is sufficient to prove the folio is not secretmem, so the
fast path can proceed.

Link: https://lore.kernel.org/20260708005745.164928-1-jhubbard@nvidia.com
Fixes: f002882 ("mm: merge folio_is_secretmem() and folio_fast_pin_allowed() into gup_fast_folio_allowed()")
Signed-off-by: John Hubbard <jhubbard@nvidia.com>
Tested-by: Sourab Gupta <sougupta@nvidia.com>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Cc: Alistair Popple <apopple@nvidia.com>
Cc: Balbir Singh <balbirs@nvidia.com>
Cc: Zi Yan <ziy@nvidia.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit c494788faffe67216c56623d240541fde50139c3 linux-next)
Signed-off-by: Jamie Nguyen <jamien@nvidia.com>
@jamieNguyenNVIDIA
jamieNguyenNVIDIA force-pushed the jamien/7.0/gup-fast-null-mapping branch from b24c16e to 3d700fb Compare August 5, 2026 17:07
@nvmochs

nvmochs commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Thanks for fixing the SHA!

Acked-by: Matthew R. Ochs <mochs@nvidia.com>

@clsotog

clsotog commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Acked-by: Carol L Soto csoto@nvidia.com

@jamieNguyenNVIDIA

Copy link
Copy Markdown
Collaborator Author

@nirmoy

nirmoy commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

BaseOS Kernel Review

Summary

No issues found across the reviewed commits.

Findings: no problems found

Latest watcher review: open review

Generated test plan: open test plan

Kernel deb build: successful (download debs, 4 files)

Head: 3d700fb5ab3a

This comment is maintained by nv-pr-bot. It is updated when the GitHub watcher publishes a newer review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants