percpu: clean up all mappings when pcpu_map_pages() fails
authorYosry Ahmed <yosryahmed@google.com>
Mon, 11 Mar 2024 19:43:46 +0000 (19:43 +0000)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 26 Apr 2024 03:55:49 +0000 (20:55 -0700)
In pcpu_map_pages(), if __pcpu_map_pages() fails on a CPU, we call
__pcpu_unmap_pages() to clean up mappings on all CPUs where mappings were
created, but not on the CPU where __pcpu_map_pages() fails.

__pcpu_map_pages() and __pcpu_unmap_pages() are wrappers around
vmap_pages_range_noflush() and vunmap_range_noflush().  All other callers
of vmap_pages_range_noflush() call vunmap_range_noflush() when mapping
fails, except pcpu_map_pages().  The reason could be that partial mappings
may be left behind from a failed mapping attempt.

Call __pcpu_unmap_pages() for the failed CPU as well in pcpu_map_pages().

This was found by code inspection, no failures or bugs were observed.

Link: https://lkml.kernel.org/r/20240311194346.2291333-1-yosryahmed@google.com
Signed-off-by: Yosry Ahmed <yosryahmed@google.com>
Acked-by: Dennis Zhou <dennis@kernel.org>
Cc: Christoph Lameter (Ampere) <cl@linux.com>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/percpu-vm.c

index 2054c9213c43391ea58c6fd8260b52890518e9ef..cd69caf6aa8d8eded2395eb4bc4051b78ec6aa33 100644 (file)
@@ -231,10 +231,10 @@ static int pcpu_map_pages(struct pcpu_chunk *chunk,
        return 0;
 err:
        for_each_possible_cpu(tcpu) {
-               if (tcpu == cpu)
-                       break;
                __pcpu_unmap_pages(pcpu_chunk_addr(chunk, tcpu, page_start),
                                   page_end - page_start);
+               if (tcpu == cpu)
+                       break;
        }
        pcpu_post_unmap_tlb_flush(chunk, page_start, page_end);
        return err;