diff mbox series

[v3,2/2] secretmem: optimize page_is_secretmem()

Message ID 20210420150049.14031-3-rppt@kernel.org (mailing list archive)
State New, archived
Headers show
Series secretmem: optimize page_is_secretmem() | expand

Commit Message

Mike Rapoport April 20, 2021, 3 p.m. UTC
From: Mike Rapoport <rppt@linux.ibm.com>

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.

Reported-by: kernel test robot <oliver.sang@intel.com>
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
---
 include/linux/secretmem.h | 26 +++++++++++++++++++++++++-
 mm/secretmem.c            | 12 +-----------
 2 files changed, 26 insertions(+), 12 deletions(-)

Comments

Matthew Wilcox May 7, 2021, 3:01 p.m. UTC | #1
On Tue, Apr 20, 2021 at 06:00:49PM +0300, Mike Rapoport wrote:
> +	mapping = (struct address_space *)
> +		((unsigned long)page->mapping & ~PAGE_MAPPING_FLAGS);
> +
> +	if (mapping != page->mapping)
> +		return false;
> +
> +	return page->mapping->a_ops == &secretmem_aops;

... why do you go back to page->mapping here?

	return mapping->a_ops == &secretmem_aops
Mike Rapoport May 8, 2021, 5:51 p.m. UTC | #2
<shakeelb@google.com>,Shuah Khan <shuah@kernel.org>,Thomas Gleixner <tglx@linutronix.de>,Tycho Andersen <tycho@tycho.ws>,Will Deacon <will@kernel.org>,Yury Norov <yury.norov@gmail.com>,linux-api@vger.kernel.org,linux-arch@vger.kernel.org,linux-arm-kernel@lists.infradead.org,linux-fsdevel@vger.kernel.org,linux-mm@kvack.org,linux-kernel@vger.kernel.org,linux-kselftest@vger.kernel.org,linux-nvdimm@lists.01.org,linux-riscv@lists.infradead.org,x86@kernel.org,kernel test robot <oliver.sang@intel.com>
From: Mike Rapoport <rppt@kernel.org>
Message-ID: <48E0FD56-6084-48B0-A59C-D2E2BF40DDA2@kernel.org>



On May 7, 2021 6:01:44 PM GMT+03:00, Matthew Wilcox <willy@infradead.org> wrote:
>On Tue, Apr 20, 2021 at 06:00:49PM +0300, Mike Rapoport wrote:
>> +	mapping = (struct address_space *)
>> +		((unsigned long)page->mapping & ~PAGE_MAPPING_FLAGS);
>> +
>> +	if (mapping != page->mapping)
>> +		return false;
>> +
>> +	return page->mapping->a_ops == &secretmem_aops;
>
>... why do you go back to page->mapping here?
>
>	return mapping->a_ops == &secretmem_aops

Ok
diff mbox series

Patch

diff --git a/include/linux/secretmem.h b/include/linux/secretmem.h
index 907a6734059c..b842b38cbeb1 100644
--- a/include/linux/secretmem.h
+++ b/include/linux/secretmem.h
@@ -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);
 bool secretmem_active(void);
 
 #else
diff --git a/mm/secretmem.c b/mm/secretmem.c
index 3b1ba3991964..0bcd15e1b549 100644
--- a/mm/secretmem.c
+++ b/mm/secretmem.c
@@ -151,22 +151,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)