From nobody Mon Feb 9 23:31:37 2026 Received: from mail-yb1-f170.google.com (mail-yb1-f170.google.com [209.85.219.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3B19014375D for ; Wed, 25 Dec 2024 08:09:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735114165; cv=none; b=QrztQ+17GwoVYwdJia+ZfT+N8bOzcHvyJhWTYmRSjD/Lob7mQanZbz6lqQUnN6SXyVQgn4xfbsSSeusDt5zAzBK1Um3fGbCXQscyLgJFWbZ49QmQweYFBzEPiD2aiRSfrIGcpg9K3jDh48+7IaGGX0pHMU+LTzoAGCGCcWONhXA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735114165; c=relaxed/simple; bh=S5dwTuJR9fQFwoMp1dbkpD1JhTGdmr4uekvMvp7DmzA=; h=MIME-Version:From:Date:Message-ID:Subject:To:Cc:Content-Type; b=lt/Fr6vnPA7YEeTm5CQ77Oa0aORCWAB4zsmtfl0gGocfgnkw2WkBpvJBn6nSoQOFymAUyjOHhIlfmcIoSJKHPpnkEnjQhAvyVQEGYGBAXGbAx5wk35VO38Llnzik6ZStvDHf3FeTRXKuNLs8FhMYrF7x8TYQjjNf4wfjAb2Fc4c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hfZ++4ip; arc=none smtp.client-ip=209.85.219.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hfZ++4ip" Received: by mail-yb1-f170.google.com with SMTP id 3f1490d57ef6-e3c8ae3a3b2so4900957276.0 for ; Wed, 25 Dec 2024 00:09:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1735114163; x=1735718963; darn=vger.kernel.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=I5RJDQoHtZ3t4AYT7GLBqeRBAtJgELgJvtSO/falmXk=; b=hfZ++4ipGtF87b1YaUJBqc0Ik25KBK/QysVw1rronV97aehJD038YA+hrQ+jxRbjeM y3kgG9dfdnOIvNYLyS135KdEhk+Q0dVng/xfW02Q86zgFqfo2qTGpRZLZpcntGK5OtnT hN4Kht4Yy9+8CX+oPFFVYNzE6lizDtt4Vtc5CPPydlLTjQtJzwFn/N/a8eYCbQUSMKpj /GRnTD++8LeKEGxSch5RWxkqhtVFQNfNmbk4KMw9x/FeMi/xrpwQ/YpVPejMfAP2a6NK n4ySvL3ceHvdO/D2+yPNMLOuTy+0HooT1d3j+6EQES5q7l7IR/capGsOmYE3BU32UHKp 37+g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1735114163; x=1735718963; h=content-transfer-encoding:cc:to:subject:message-id:date:from :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=I5RJDQoHtZ3t4AYT7GLBqeRBAtJgELgJvtSO/falmXk=; b=BKDqkAxZGdUR0aNopgrY1E47ambKLSsYoBSlzDUM226fMnIHGDrJVxqQai57ljljn9 5nzCmhuCHACNnv2VrEEcBYno7O9xG3MH4mYJJ3xq/uHB84EKzagcJbJsmD+MdpXcEi6m TERCKITHpnXOc2v4H0MYG/FgOwDtJO1AROWVWO3oHqjPNMO3JZrWGoWNZc/OxM4I9Iyy pPJNjLARO4n6G/Q+pG2JwAXmBq8H+7kYfXFXrM75Hpk7mZsLCd0LprTgyOk0afoMbs7/ Ytf4rhc1EABy8JDeaMbJp4n2qRhVv1BuAEE71nDDsYGmiReZbH1kyoI18uhPEj4x9gku GfHQ== X-Forwarded-Encrypted: i=1; AJvYcCUbDTgdejDxU5IH+BDf3OFhxSgd9yH4oS6YDJQag2HR1w4NczGH+elt49K9yQ41M2cJ+0T51n9qkr0c7pU=@vger.kernel.org X-Gm-Message-State: AOJu0YxclkUPgvL/wNG364QtDYlM1hTQvkPW90ssTxzX074o7hBCYqGz 6Z+65mz8qZn55QMqZVnNfc9ZLK8uZ2FDhATzBH2k/tsOTKVBTfJ2o5/rHuh5Xz3tqYo4+waARsY AaqX8iUFIUxrtMmfdaiwNwaiAZmtWncS3Z0aBEQ== X-Gm-Gg: ASbGncsx63MGZ+jyIcgmkmAsbgSFfKCppkroJ00gUMj+FpF8TEi4etM9dxUV4TXJSs/ vr4OdBndWgdvDXgmrOv/mnAfOm0H9KqRacuYVzMI= X-Google-Smtp-Source: AGHT+IEO22SHxxKY8sn59okYEevvhOeq+mcb/gj0nCDxxgIsuTnY6LudvxThZor19wniGJ/a7r1htnvV8f0oGztpXMA= X-Received: by 2002:a05:690c:9986:b0:6ef:79d1:2f69 with SMTP id 00721157ae682-6f3f8213f2fmr163950257b3.31.1735114163118; Wed, 25 Dec 2024 00:09:23 -0800 (PST) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Weikang Guo Date: Wed, 25 Dec 2024 16:09:12 +0800 Message-ID: Subject: Potential Double Scanning of struct page Physical Memory by kmemleak To: Catalin Marinas , Andrew Morton Cc: Linux Memory Management List , linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Dear Catalin and Andrew, I hope this message finds you well. While reviewing the implementation of kmemleak, I noticed a potential issue where the physical memory occupied by struct page may be scanned twice by kmemleak. To verify this hypothesis, I added some logging to the code, and I would like to discuss my findings with you. Below are the details of my environment, the logic I used, and the relevant log output. Test Platform: Architecture: ARM64 Platform: qemu branch: local branch based on V6.12 defconfig=EF=BC=9A use defconfig with CONFIG_KMEMLEAK open Problem Description: When CONFIG_SPARSEMEM is enabled, the memory for `struct page`objects in the sections is allocated via `sparse_buffer` using the `memblock_alloc_xxx` interface. Since memblock does not explicitly specify `MEMBLOCK_ALLOC_NOLEAKTRACE`, kmemleak will treat the memory as a gray object with mincount=3D0. In other words, the physical memory occupied by `struct page` will be scanned by kmemleak as a gray object during the scan thread. Additionally, kmemleak also traverses and scans valid struct page objects in the zone . As a result, the physical memory occupied by struct page may end up being scanned twice by scan thread. Logging Added: To investigate further, I added the following logs: Logs for the memory allocated for `struct page` objects through sparse memb= lock. diff --git a/mm/sparse.c b/mm/sparse.c index 3174b3ca3e9e..f2465b394344 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -362,6 +362,9 @@ static void __init sparse_buffer_init(unsigned long size, int nid) */ sparsemap_buf =3D memmap_alloc(size, section_map_size(), addr, nid,= true); sparsemap_buf_end =3D sparsemap_buf + size; + pr_info("sparse buf alloc VA: [0x%08lx: 0x%08lx] to PA: \ + [0x%08lx: 0x%08lx]\n",sparsemap_buf, sparsemap_buf_end, + virt_to_phys(sparsemap_buf), virt_to_phys(sparsemap_buf_end= )); #ifndef CONFIG_SPARSEMEM_VMEMMAP memmap_boot_pages_add(DIV_ROUND_UP(size, PAGE_SIZE)); #endif Logs to show the mapping between VMEMAP VA and PA. diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index c0388b2e959d..f1a312f2a281 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -342,6 +342,8 @@ int __meminit vmemmap_populate_hugepages(unsigned long start, unsigned long end, p =3D vmemmap_alloc_block_buf(PMD_SIZE, node, altma= p); if (p) { + pr_info("=3D=3D=3D=3D vmemap 2M: VA:0x%08lx= to PA:0x%08lx \n", + start, virt_to_phys(p)); vmemmap_set_pmd(pmd, p, node, addr, next); continue; } else if (altmap) { Logs showing the memblock and struct page objects scanned by kmemleak. diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 0efa41d77bcc..a803825dcb18 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1529,7 +1529,10 @@ static void scan_object(struct kmemleak_object *obje= ct) (void *)object->pointer; void *end =3D start + object->size; void *next; - + if (object->flags & OBJECT_PHYS) { + pr_info("=3D=3D=3D=3D=3D=3D=3D scan memblock OBJECT_PHYS:[0x%08lx:0x%08lx]\n", + start, end); + } do { next =3D min(start + MAX_SCAN_SIZE, end); scan_block(start, next, object); @@ -1677,6 +1680,8 @@ static void kmemleak_scan(void) * Struct page scanning for each node. */ for_each_populated_zone(zone) { + static int print_scan_page =3D 0; + unsigned long start_pfn =3D zone->zone_start_pfn; unsigned long end_pfn =3D zone_end_pfn(zone); unsigned long pfn; @@ -1696,6 +1701,14 @@ static void kmemleak_scan(void) /* only scan if page is in use */ if (page_count(page) =3D=3D 0) continue; + + + if (print_scan_page =3D=3D 0) { + pr_info("=3D=3D=3D=3D=3D=3D=3D scan page [0x%08lx:0x%08lx] \n", + page, page+1); + print_scan_page++; + } + scan_block(page, page + 1, NULL); } } The log output is as follows: [ 0.000000] sparse buf alloc VA: [0xffff39253b600000: 0xffff39253f600000] to PA: [0x13b600000: 0x13f600000] [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee451000000 to PA:0x13b60= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee451200000 to PA:0x13b80= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee451400000 to PA:0x13ba0= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee451600000 to PA:0x13bc0= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee451800000 to PA:0x13be0= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee451a00000 to PA:0x13c00= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee451c00000 to PA:0x13c20= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee451e00000 to PA:0x13c40= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee452000000 to PA:0x13c60= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee452200000 to PA:0x13c80= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee452400000 to PA:0x13ca0= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee452600000 to PA:0x13cc0= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee452800000 to PA:0x13ce0= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee452a00000 to PA:0x13d00= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee452c00000 to PA:0x13d20= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee452e00000 to PA:0x13d40= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee453000000 to PA:0x13d60= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee453200000 to PA:0x13d80= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee453400000 to PA:0x13da0= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee453600000 to PA:0x13dc0= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee453800000 to PA:0x13de0= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee453a00000 to PA:0x13e00= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee453c00000 to PA:0x13e20= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee453e00000 to PA:0x13e40= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee454000000 to PA:0x13e60= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee454200000 to PA:0x13e80= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee454400000 to PA:0x13ea0= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee454600000 to PA:0x13ec0= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee454800000 to PA:0x13ee0= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee454a00000 to PA:0x13f00= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee454c00000 to PA:0x13f20= 0000 [ 0.000000] =3D=3D=3D=3D vmemap 2M: VA:0xfffffee454e00000 to PA:0x13f40= 0000 [ 62.480979] kmemleak: =3D=3D=3D=3D=3D=3D=3D scan page [0xfffffee451008400:0xfffffee451008440] [ 62.705876] kmemleak: =3D=3D=3D=3D=3D=3D=3D scan memblock OBJECT_PHYS:[0xffff39253b600000:0xffff39253f600000] scan_page: VMEMAP VA is [ 0xfffffee451008400 - 0xfffffee451008440] scan_page=EF=BC=9AReal PA is [0x13b608400 - 0x13b608440] scan OBJECT_PHYS: VA is [0xffff39253b600000:0xffff39253f600000] scan OBJECT_PHYS: PA is [0x13b600000:0x13f600000] The first record page `0x13b608400` was scanned twice Could you please help confirm whether this issue exists and if it could lead to any unintended consequences? I would appreciate any insights or suggestions you may have. Possible solution: Specify `MEMBLOCK_ALLOC_NOLEAKTRACE` when alloc `struct page memory` Thank you for your time and assistance. Best regards, Guo