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 | const char *from = kmap_local_folio(folio, offset); | 461 | const char *from = kmap_local_folio(folio, offset); |
| 462 | size_t chunk = len; | 462 | size_t chunk = len; |
| 463 | 463 | ||
| 464 | if (folio_test_highmem(folio) && | 464 | if (folio_test_partial_kmap(folio) && |
| 465 | chunk > PAGE_SIZE - offset_in_page(offset)) | 465 | chunk > PAGE_SIZE - offset_in_page(offset)) |
| 466 | chunk = PAGE_SIZE - offset_in_page(offset); | 466 | chunk = PAGE_SIZE - offset_in_page(offset); |
| 467 | memcpy(to, from, chunk); | 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 | char *to = kmap_local_folio(folio, offset); | 489 | char *to = kmap_local_folio(folio, offset); |
| 490 | size_t chunk = len; | 490 | size_t chunk = len; |
| 491 | 491 | ||
| 492 | if (folio_test_highmem(folio) && | 492 | if (folio_test_partial_kmap(folio) && |
| 493 | chunk > PAGE_SIZE - offset_in_page(offset)) | 493 | chunk > PAGE_SIZE - offset_in_page(offset)) |
| 494 | chunk = PAGE_SIZE - offset_in_page(offset); | 494 | chunk = PAGE_SIZE - offset_in_page(offset); |
| 495 | memcpy(to, from, chunk); | 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 | size_t len = folio_size(folio) - offset; | 523 | size_t len = folio_size(folio) - offset; |
| 524 | 524 | ||
| 525 | if (folio_test_highmem(folio)) { | 525 | if (folio_test_partial_kmap(folio)) { |
| 526 | size_t max = PAGE_SIZE - offset_in_page(offset); | 526 | size_t max = PAGE_SIZE - offset_in_page(offset); |
| 527 | 527 | ||
| 528 | while (len > max) { | 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 | VM_BUG_ON(offset + len > folio_size(folio)); | 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 | size_t max = PAGE_SIZE - offset_in_page(offset); | 564 | size_t max = PAGE_SIZE - offset_in_page(offset); |
| 565 | 565 | ||
| 566 | while (len > max) { | 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 | size_t offset = offset_in_folio(folio, pos); | 597 | size_t offset = offset_in_folio(folio, pos); |
| 598 | char *from = kmap_local_folio(folio, offset); | 598 | char *from = kmap_local_folio(folio, offset); |
| 599 | 599 | ||
| 600 | if (folio_test_highmem(folio)) { | 600 | if (folio_test_partial_kmap(folio)) { |
| 601 | offset = offset_in_page(offset); | 601 | offset = offset_in_page(offset); |
| 602 | len = min_t(size_t, len, PAGE_SIZE - offset); | 602 | len = min_t(size_t, len, PAGE_SIZE - offset); |
| 603 | } else | 603 | } else |
| @@ -615,6 +615,13 @@ FOLIO_FLAG(dropbehind, FOLIO_HEAD_PAGE) · 614 unmodified lines | |||
| 615 | PAGEFLAG_FALSE(HighMem, highmem) | 615 | PAGEFLAG_FALSE(HighMem, highmem) |
| 616 | #endif | 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 | #ifdef CONFIG_SWAP | 625 | #ifdef CONFIG_SWAP |
| 619 | static __always_inline bool folio_test_swapcache(const struct folio *folio) | 626 | static __always_inline bool folio_test_swapcache(const struct folio *folio) |
| 620 | { | 627 | { |