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

mm: merge folio_is_secretmem() and folio_fast_pin_allowed() into gup_fast_folio_allowed()

folio_is_secretmem() is currently only used during GUP-fast. Nowadays,
folio_fast_pin_allowed() performs similar checks during GUP-fast and
contains a lot of careful handling -- READ_ONCE() -- , sanity checks --
lockdep_assert_irqs_disabled() -- and helpful comments on how this
handling is safe and correct.

So let's merge folio_is_secretmem() into folio_fast_pin_allowed(). Rename
folio_fast_pin_allowed() to gup_fast_folio_allowed(), to better match the
new semantics.

Link: https://lkml.kernel.org/r/20240326143210.291116-4-david@redhat.com
Signed-off-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Mike Rapoport (IBM) <rppt@kernel.org>
Cc: David Hildenbrand <david@redhat.com>
Cc: Lorenzo Stoakes <lstoakes@gmail.com>
Cc: Miklos Szeredi <mszeredi@redhat.com>
Cc: xingwei lee <xrivendell7@gmail.com>
Cc: yue sun <samsun1006219@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

David Hildenbrand and committed by
Andrew Morton
f002882c c139ca42

+30 -39
+2 -19
include/linux/secretmem.h
··· 6 6 7 7 extern const struct address_space_operations secretmem_aops; 8 8 9 - static inline bool folio_is_secretmem(struct folio *folio) 9 + static inline bool secretmem_mapping(struct address_space *mapping) 10 10 { 11 - struct address_space *mapping; 12 - 13 - /* 14 - * Using folio_mapping() is quite slow because of the actual call 15 - * instruction. 16 - * We know that secretmem pages are not compound, so we can 17 - * save a couple of cycles here. 18 - */ 19 - if (folio_test_large(folio)) 20 - return false; 21 - 22 - mapping = (struct address_space *) 23 - ((unsigned long)folio->mapping & ~PAGE_MAPPING_FLAGS); 24 - 25 - if (!mapping || mapping != folio->mapping) 26 - return false; 27 - 28 11 return mapping->a_ops == &secretmem_aops; 29 12 } 30 13 ··· 21 38 return false; 22 39 } 23 40 24 - static inline bool folio_is_secretmem(struct folio *folio) 41 + static inline bool secretmem_mapping(struct address_space *mapping) 25 42 { 26 43 return false; 27 44 }
+28 -20
mm/gup.c
··· 2468 2468 #ifdef CONFIG_HAVE_FAST_GUP 2469 2469 2470 2470 /* 2471 - * Used in the GUP-fast path to determine whether a pin is permitted for a 2472 - * specific folio. 2471 + * Used in the GUP-fast path to determine whether GUP is permitted to work on 2472 + * a specific folio. 2473 2473 * 2474 2474 * This call assumes the caller has pinned the folio, that the lowest page table 2475 2475 * level still points to this folio, and that interrupts have been disabled. 2476 + * 2477 + * GUP-fast must reject all secretmem folios. 2476 2478 * 2477 2479 * Writing to pinned file-backed dirty tracked folios is inherently problematic 2478 2480 * (see comment describing the writable_file_mapping_allowed() function). We ··· 2485 2483 * in the fast path, so instead we whitelist known good cases and if in doubt, 2486 2484 * fall back to the slow path. 2487 2485 */ 2488 - static bool folio_fast_pin_allowed(struct folio *folio, unsigned int flags) 2486 + static bool gup_fast_folio_allowed(struct folio *folio, unsigned int flags) 2489 2487 { 2488 + bool reject_file_backed = false; 2490 2489 struct address_space *mapping; 2490 + bool check_secretmem = false; 2491 2491 unsigned long mapping_flags; 2492 2492 2493 2493 /* 2494 2494 * If we aren't pinning then no problematic write can occur. A long term 2495 2495 * pin is the most egregious case so this is the one we disallow. 2496 2496 */ 2497 - if ((flags & (FOLL_PIN | FOLL_LONGTERM | FOLL_WRITE)) != 2497 + if ((flags & (FOLL_PIN | FOLL_LONGTERM | FOLL_WRITE)) == 2498 2498 (FOLL_PIN | FOLL_LONGTERM | FOLL_WRITE)) 2499 - return true; 2499 + reject_file_backed = true; 2500 2500 2501 - /* The folio is pinned, so we can safely access folio fields. */ 2501 + /* We hold a folio reference, so we can safely access folio fields. */ 2502 + 2503 + /* secretmem folios are always order-0 folios. */ 2504 + if (IS_ENABLED(CONFIG_SECRETMEM) && !folio_test_large(folio)) 2505 + check_secretmem = true; 2506 + 2507 + if (!reject_file_backed && !check_secretmem) 2508 + return true; 2502 2509 2503 2510 if (WARN_ON_ONCE(folio_test_slab(folio))) 2504 2511 return false; 2505 2512 2506 - /* hugetlb mappings do not require dirty-tracking. */ 2513 + /* hugetlb neither requires dirty-tracking nor can be secretmem. */ 2507 2514 if (folio_test_hugetlb(folio)) 2508 2515 return true; 2509 2516 ··· 2548 2537 2549 2538 /* 2550 2539 * At this point, we know the mapping is non-null and points to an 2551 - * address_space object. The only remaining whitelisted file system is 2552 - * shmem. 2540 + * address_space object. 2553 2541 */ 2554 - return shmem_mapping(mapping); 2542 + if (check_secretmem && secretmem_mapping(mapping)) 2543 + return false; 2544 + /* The only remaining allowed file system is shmem. */ 2545 + return !reject_file_backed || shmem_mapping(mapping); 2555 2546 } 2556 2547 2557 2548 static void __maybe_unused undo_dev_pagemap(int *nr, int nr_start, ··· 2639 2626 if (!folio) 2640 2627 goto pte_unmap; 2641 2628 2642 - if (unlikely(folio_is_secretmem(folio))) { 2643 - gup_put_folio(folio, 1, flags); 2644 - goto pte_unmap; 2645 - } 2646 - 2647 2629 if (unlikely(pmd_val(pmd) != pmd_val(*pmdp)) || 2648 2630 unlikely(pte_val(pte) != pte_val(ptep_get(ptep)))) { 2649 2631 gup_put_folio(folio, 1, flags); 2650 2632 goto pte_unmap; 2651 2633 } 2652 2634 2653 - if (!folio_fast_pin_allowed(folio, flags)) { 2635 + if (!gup_fast_folio_allowed(folio, flags)) { 2654 2636 gup_put_folio(folio, 1, flags); 2655 2637 goto pte_unmap; 2656 2638 } ··· 2842 2834 return 0; 2843 2835 } 2844 2836 2845 - if (!folio_fast_pin_allowed(folio, flags)) { 2837 + if (!gup_fast_folio_allowed(folio, flags)) { 2846 2838 gup_put_folio(folio, refs, flags); 2847 2839 return 0; 2848 2840 } ··· 2913 2905 return 0; 2914 2906 } 2915 2907 2916 - if (!folio_fast_pin_allowed(folio, flags)) { 2908 + if (!gup_fast_folio_allowed(folio, flags)) { 2917 2909 gup_put_folio(folio, refs, flags); 2918 2910 return 0; 2919 2911 } ··· 2957 2949 return 0; 2958 2950 } 2959 2951 2960 - if (!folio_fast_pin_allowed(folio, flags)) { 2952 + if (!gup_fast_folio_allowed(folio, flags)) { 2961 2953 gup_put_folio(folio, refs, flags); 2962 2954 return 0; 2963 2955 } ··· 3002 2994 return 0; 3003 2995 } 3004 2996 3005 - if (!folio_fast_pin_allowed(folio, flags)) { 2997 + if (!gup_fast_folio_allowed(folio, flags)) { 3006 2998 gup_put_folio(folio, refs, flags); 3007 2999 return 0; 3008 3000 }