Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

highmem: add folio_test_partial_kmap()

In commit c749d9b7ebbc ("iov_iter: fix copy_page_from_iter_atomic() if
KMAP_LOCAL_FORCE_MAP"), Hugh correctly noted that if KMAP_LOCAL_FORCE_MAP
is enabled, we must limit ourselves to PAGE_SIZE bytes per call to
kmap_local(). The same problem exists in memcpy_from_folio(),
memcpy_to_folio(), folio_zero_tail(), folio_fill_tail() and
memcpy_from_file_folio(), so add folio_test_partial_kmap() to do this more
succinctly.

Link: https://lkml.kernel.org/r/20250514170607.3000994-2-willy@infradead.org
Fixes: 00cdf76012ab ("mm: add memcpy_from_file_folio()")
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Hugh Dickins <hughd@google.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Matthew Wilcox (Oracle) and committed by
Andrew Morton
97dfbbd1 6fa04511

+12 -5
+5 -5
include/linux/highmem.h
··· 461 461 const char *from = kmap_local_folio(folio, offset); 462 462 size_t chunk = len; 463 463 464 - if (folio_test_highmem(folio) && 464 + if (folio_test_partial_kmap(folio) && 465 465 chunk > PAGE_SIZE - offset_in_page(offset)) 466 466 chunk = PAGE_SIZE - offset_in_page(offset); 467 467 memcpy(to, from, chunk); ··· 489 489 char *to = kmap_local_folio(folio, offset); 490 490 size_t chunk = len; 491 491 492 - if (folio_test_highmem(folio) && 492 + if (folio_test_partial_kmap(folio) && 493 493 chunk > PAGE_SIZE - offset_in_page(offset)) 494 494 chunk = PAGE_SIZE - offset_in_page(offset); 495 495 memcpy(to, from, chunk); ··· 522 522 { 523 523 size_t len = folio_size(folio) - offset; 524 524 525 - if (folio_test_highmem(folio)) { 525 + if (folio_test_partial_kmap(folio)) { 526 526 size_t max = PAGE_SIZE - offset_in_page(offset); 527 527 528 528 while (len > max) { ··· 560 560 561 561 VM_BUG_ON(offset + len > folio_size(folio)); 562 562 563 - if (folio_test_highmem(folio)) { 563 + if (folio_test_partial_kmap(folio)) { 564 564 size_t max = PAGE_SIZE - offset_in_page(offset); 565 565 566 566 while (len > max) { ··· 597 597 size_t offset = offset_in_folio(folio, pos); 598 598 char *from = kmap_local_folio(folio, offset); 599 599 600 - if (folio_test_highmem(folio)) { 600 + if (folio_test_partial_kmap(folio)) { 601 601 offset = offset_in_page(offset); 602 602 len = min_t(size_t, len, PAGE_SIZE - offset); 603 603 } else
+7
include/linux/page-flags.h
··· 615 615 PAGEFLAG_FALSE(HighMem, highmem) 616 616 #endif 617 617 618 + /* Does kmap_local_folio() only allow access to one page of the folio? */ 619 + #ifdef CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP 620 + #define folio_test_partial_kmap(f) true 621 + #else 622 + #define folio_test_partial_kmap(f) folio_test_highmem(f) 623 + #endif 624 + 618 625 #ifdef CONFIG_SWAP 619 626 static __always_inline bool folio_test_swapcache(const struct folio *folio) 620 627 {