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

fs/proc/task_mmu: add fast paths to get/clear PAGE_IS_WRITTEN flag

Adding fast code paths to handle specifically only get and/or clear
operation of PAGE_IS_WRITTEN, increases its performance by 0-35%. The
results of some test cases are given below:

Test-case-1
t1 = (Get + WP) time
t2 = WP time
t1 t2
Without this patch: 140-170mcs 90-115mcs
With this patch: 110mcs 80mcs
Worst case diff: 35% faster 30% faster

Test-case-2
t3 = atomic Get and WP
t3
Without this patch: 120-140mcs
With this patch: 100-110mcs
Worst case diff: 21% faster

Link: https://lkml.kernel.org/r/20230821141518.870589-4-usama.anjum@collabora.com
Signed-off-by: Muhammad Usama Anjum <usama.anjum@collabora.com>
Cc: Alex Sierra <alex.sierra@amd.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andrei Vagin <avagin@gmail.com>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Gustavo A. R. Silva <gustavoars@kernel.org>
Cc: "Liam R. Howlett" <Liam.Howlett@oracle.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Michal Miroslaw <emmir@google.com>
Cc: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Cc: Mike Rapoport (IBM) <rppt@kernel.org>
Cc: Nadav Amit <namit@vmware.com>
Cc: Pasha Tatashin <pasha.tatashin@soleen.com>
Cc: Paul Gofman <pgofman@codeweavers.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Yang Shi <shy828301@gmail.com>
Cc: Yun Zhou <yun.zhou@windriver.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Muhammad Usama Anjum and committed by
Andrew Morton
12f6b01a 52526ca7

+36
+36
fs/proc/task_mmu.c
··· 2145 2145 return 0; 2146 2146 } 2147 2147 2148 + if (!p->vec_out) { 2149 + /* Fast path for performing exclusive WP */ 2150 + for (addr = start; addr != end; pte++, addr += PAGE_SIZE) { 2151 + if (pte_uffd_wp(ptep_get(pte))) 2152 + continue; 2153 + make_uffd_wp_pte(vma, addr, pte); 2154 + if (!flush_end) 2155 + start = addr; 2156 + flush_end = addr + PAGE_SIZE; 2157 + } 2158 + goto flush_and_return; 2159 + } 2160 + 2161 + if (!p->arg.category_anyof_mask && !p->arg.category_inverted && 2162 + p->arg.category_mask == PAGE_IS_WRITTEN && 2163 + p->arg.return_mask == PAGE_IS_WRITTEN) { 2164 + for (addr = start; addr < end; pte++, addr += PAGE_SIZE) { 2165 + unsigned long next = addr + PAGE_SIZE; 2166 + 2167 + if (pte_uffd_wp(ptep_get(pte))) 2168 + continue; 2169 + ret = pagemap_scan_output(p->cur_vma_category | PAGE_IS_WRITTEN, 2170 + p, addr, &next); 2171 + if (next == addr) 2172 + break; 2173 + if (~p->arg.flags & PM_SCAN_WP_MATCHING) 2174 + continue; 2175 + make_uffd_wp_pte(vma, addr, pte); 2176 + if (!flush_end) 2177 + start = addr; 2178 + flush_end = next; 2179 + } 2180 + goto flush_and_return; 2181 + } 2182 + 2148 2183 for (addr = start; addr != end; pte++, addr += PAGE_SIZE) { 2149 2184 unsigned long categories = p->cur_vma_category | 2150 2185 pagemap_page_category(p, vma, addr, ptep_get(pte)); ··· 2203 2168 flush_end = next; 2204 2169 } 2205 2170 2171 + flush_and_return: 2206 2172 if (flush_end) 2207 2173 flush_tlb_range(vma, start, addr); 2208 2174