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.
Unified · Split
| @@ -461,7 +461,7 @@ static inline void memcpy_from_folio(char *to, struct folio *folio, · 460 unmodified lines | ||
| 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,7 +489,7 @@ static inline void memcpy_to_folio(struct folio *folio, size_t offset, · 21 unmodified lines | ||
| 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,7 +522,7 @@ static inline __must_check void *folio_zero_tail(struct folio *folio, · 26 unmodified lines | ||
| 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,7 +560,7 @@ static inline void folio_fill_tail(struct folio *folio, size_t offset, · 31 unmodified lines | ||
| 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,7 +597,7 @@ static inline size_t memcpy_from_file_folio(char *to, struct folio *folio, · 30 unmodified lines | ||
| 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 |
| @@ -615,6 +615,13 @@ FOLIO_FLAG(dropbehind, FOLIO_HEAD_PAGE) · 614 unmodified lines | ||
| 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 | { |