]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
secretmem: optimize page_is_secretmem()
authorMike Rapoport <rppt@linux.ibm.com>
Thu, 22 Apr 2021 06:43:27 +0000 (16:43 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 6 May 2021 01:46:48 +0000 (11:46 +1000)
Kernel test robot reported -4.2% regression of
will-it-scale.per_thread_ops due to commit "mm: introduce memfd_secret
system call to create "secret" memory areas".

The perf profile of the test indicated that the regression is caused by
page_is_secretmem() called from gup_pte_range() (inlined by
gup_pgd_range):

 27.76  +2.5  30.23       perf-profile.children.cycles-pp.gup_pgd_range
  0.00  +3.2   3.19    2%  perf-profile.children.cycles-pp.page_mapping
  0.00  +3.7   3.66    2%  perf-profile.children.cycles-pp.page_is_secretmem

Further analysis showed that the slow down happens because neither
page_is_secretmem() nor page_mapping() are not inline and moreover,
multiple page flags checks in page_mapping() involve calling
compound_head() several times for the same page.

Make page_is_secretmem() inline and replace page_mapping() with page flag
checks that do not imply page-to-head conversion.

Link: https://lkml.kernel.org/r/20210420150049.14031-3-rppt@kernel.org
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Reported-by: kernel test robot <oliver.sang@intel.com>
Cc: Hagen Paul Pfeifer <hagen@jauu.net>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christopher Lameter <cl@linux.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Elena Reshetova <elena.reshetova@intel.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: "Kirill A. Shutemov" <kirill@shutemov.name>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Palmer Dabbelt <palmerdabbelt@google.com>
Cc: Paul Walmsley <paul.walmsley@sifive.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
Cc: Roman Gushchin <guro@fb.com>
Cc: Shakeel Butt <shakeelb@google.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Tycho Andersen <tycho@tycho.ws>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
include/linux/secretmem.h
mm/secretmem.c

index 70e7db9f94fe26cab889bace3b319a2923b6c110..3b12864424a9743cd05110fd5024bc2e60043ab5 100644 (file)
@@ -4,8 +4,32 @@
 
 #ifdef CONFIG_SECRETMEM
 
+extern const struct address_space_operations secretmem_aops;
+
+static inline bool page_is_secretmem(struct page *page)
+{
+       struct address_space *mapping;
+
+       /*
+        * Using page_mapping() is quite slow because of the actual call
+        * instruction and repeated compound_head(page) inside the
+        * page_mapping() function.
+        * We know that secretmem pages are not compound and LRU so we can
+        * save a couple of cycles here.
+        */
+       if (PageCompound(page) || !PageLRU(page))
+               return false;
+
+       mapping = (struct address_space *)
+               ((unsigned long)page->mapping & ~PAGE_MAPPING_FLAGS);
+
+       if (mapping != page->mapping)
+               return false;
+
+       return page->mapping->a_ops == &secretmem_aops;
+}
+
 bool vma_is_secretmem(struct vm_area_struct *vma);
-bool page_is_secretmem(struct page *page);
 
 #else
 
index 8901acd94638fc6a1e7a37a0e4734bd01e19289e..61f1affd612210bdf777147bae0776613b8fbf16 100644 (file)
@@ -137,22 +137,12 @@ static void secretmem_freepage(struct page *page)
        clear_highpage(page);
 }
 
-static const struct address_space_operations secretmem_aops = {
+const struct address_space_operations secretmem_aops = {
        .freepage       = secretmem_freepage,
        .migratepage    = secretmem_migratepage,
        .isolate_page   = secretmem_isolate_page,
 };
 
-bool page_is_secretmem(struct page *page)
-{
-       struct address_space *mapping = page_mapping(page);
-
-       if (!mapping)
-               return false;
-
-       return mapping->a_ops == &secretmem_aops;
-}
-
 static struct vfsmount *secretmem_mnt;
 
 static struct file *secretmem_file_create(unsigned long flags)