| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/30 04:59 | flow | patch-triage |
3mArgs:null Results: {
"EnableConfigs": [
"SWAP",
"MEMCG",
"TRANSPARENT_HUGEPAGE",
"THP_SWAP",
"SHMEM"
],
"FocusSymbols": [
"folio_alloc_swap",
"mem_cgroup_get_folio_swap_margin",
"page_counter_margin",
"shmem_writeout"
],
"KMSANReasoning": "The patch enhances swap allocation error reporting in `folio_alloc_swap()` by distinguishing between cases where a large folio allocation failed due to folio size vs. total swap/cgroup swap exhaustion. It introduces `page_counter_margin()` and `mem_cgroup_get_folio_swap_margin()` and updates folio splitting decisions in `mm/vmscan.c` and `mm/shmem.c`.\n\nKMSAN vs KASAN Applicability:\n- Uninitialized Memory (KMSAN): All local variables (`ret`, `margin`, `m`) are explicitly initialized before use. No kernel structures or buffers are copied to user space, and no uninitialized memory reads or allocations are introduced.\n- Memory Safety \u0026 Logic (KASAN/Lockdep): Any risks in this patch revolve around cgroup swap accounting, page locking, refcounting, or control-flow logic in reclaim/writeout, which are monitored by standard MM assertions, KASAN, and Lockdep.\n\nTherefore, dedicated KMSAN fuzzing is not required.",
"NeedsKMSAN": false,
"Reasoning": "The patch modifies memory management swap allocation logic by refining error reporting in folio_alloc_swap() and adding page_counter_margin() and mem_cgroup_get_folio_swap_margin() to inspect hierarchical swap margins. This changes how large folios are split and handled during swapout in shmem_writeout() and page reclaim in shrink_folio_list() when global or memcg swap limits are reached.",
"WorthFuzzing": true
} |
| 1/1 | 2026/08/30 04:59 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 31516bd662f92816ad63537de1ee7eaf9e957cb9\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Sun Aug 30 04:59:52 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/include/linux/page_counter.h b/include/linux/page_counter.h\nindex d649b6bbbc871..07b7cb12249c7 100644\n--- a/include/linux/page_counter.h\n+++ b/include/linux/page_counter.h\n@@ -68,6 +68,7 @@ static inline unsigned long page_counter_read(struct page_counter *counter)\n \treturn atomic_long_read(\u0026counter-\u003eusage);\n }\n \n+long page_counter_margin(struct page_counter *counter);\n void page_counter_cancel(struct page_counter *counter, unsigned long nr_pages);\n void page_counter_charge(struct page_counter *counter, unsigned long nr_pages);\n bool page_counter_try_charge(struct page_counter *counter,\ndiff --git a/include/linux/swap.h b/include/linux/swap.h\nindex 0f953ed9c8630..a72ecf12c00db 100644\n--- a/include/linux/swap.h\n+++ b/include/linux/swap.h\n@@ -510,6 +510,7 @@ static inline void mem_cgroup_uncharge_swap(unsigned short id, unsigned int nr_p\n \t__mem_cgroup_uncharge_swap(id, nr_pages);\n }\n \n+long mem_cgroup_get_folio_swap_margin(struct folio *folio);\n extern long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg);\n extern bool mem_cgroup_swap_full(struct folio *folio);\n #else\n@@ -523,6 +524,11 @@ static inline void mem_cgroup_uncharge_swap(unsigned short id,\n {\n }\n \n+static inline long mem_cgroup_get_folio_swap_margin(struct folio *folio)\n+{\n+\treturn PAGE_COUNTER_MAX;\n+}\n+\n static inline long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg)\n {\n \treturn get_nr_swap_pages();\ndiff --git a/mm/memcontrol.c b/mm/memcontrol.c\nindex 4a18ee4509ab6..9a3804132c2eb 100644\n--- a/mm/memcontrol.c\n+++ b/mm/memcontrol.c\n@@ -5801,15 +5801,35 @@ long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg)\n {\n \tlong nr_swap_pages = get_nr_swap_pages();\n \n-\tif (mem_cgroup_disabled() || do_memsw_account())\n-\t\treturn nr_swap_pages;\n-\tfor (; !mem_cgroup_is_root(memcg); memcg = parent_mem_cgroup(memcg))\n-\t\tnr_swap_pages = min_t(long, nr_swap_pages,\n-\t\t\t\t READ_ONCE(memcg-\u003eswap.max) -\n-\t\t\t\t page_counter_read(\u0026memcg-\u003eswap));\n+\tif (!mem_cgroup_disabled() \u0026\u0026 !do_memsw_account())\n+\t\tnr_swap_pages = min(nr_swap_pages, page_counter_margin(\u0026memcg-\u003eswap));\n+\n \treturn nr_swap_pages;\n }\n \n+/**\n+ * mem_cgroup_get_folio_swap_margin - get a folio's memcg swap margin\n+ * @folio: folio whose memcg margin is queried\n+ *\n+ * Return: Remaining chargeable pages in the folio's memcg hierarchy.\n+ */\n+long mem_cgroup_get_folio_swap_margin(struct folio *folio)\n+{\n+\tstruct mem_cgroup *memcg;\n+\tlong margin;\n+\n+\tif (mem_cgroup_disabled() || do_memsw_account() ||\n+\t !folio_memcg_charged(folio))\n+\t\treturn PAGE_COUNTER_MAX;\n+\n+\trcu_read_lock();\n+\tmemcg = folio_memcg(folio);\n+\tmargin = page_counter_margin(\u0026memcg-\u003eswap);\n+\trcu_read_unlock();\n+\n+\treturn margin;\n+}\n+\n bool mem_cgroup_swap_full(struct folio *folio)\n {\n \tstruct mem_cgroup *memcg;\ndiff --git a/mm/page_counter.c b/mm/page_counter.c\nindex 661e0f2a5127a..450543f4b318b 100644\n--- a/mm/page_counter.c\n+++ b/mm/page_counter.c\n@@ -46,6 +46,26 @@ static void propagate_protected_usage(struct page_counter *c,\n \t}\n }\n \n+/**\n+ * page_counter_margin - remaining usable space within hierarchical limits\n+ * @counter: counter\n+ *\n+ * Return: The minimum value of max minus usage across @counter and all of\n+ * its ancestors. The value may be negative during a concurrent charge.\n+ */\n+long page_counter_margin(struct page_counter *counter)\n+{\n+\tlong margin = PAGE_COUNTER_MAX;\n+\n+\tdo {\n+\t\tlong m = READ_ONCE(counter-\u003emax) - page_counter_read(counter);\n+\n+\t\tmargin = min(margin, m);\n+\t} while ((counter = counter-\u003eparent));\n+\n+\treturn margin;\n+}\n+\n /**\n * page_counter_cancel - take pages out of the local counter\n * @counter: counter\ndiff --git a/mm/shmem.c b/mm/shmem.c\nindex de144a9a9558b..84b8e9e05973b 100644\n--- a/mm/shmem.c\n+++ b/mm/shmem.c\n@@ -1612,7 +1612,7 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,\n \tstruct shmem_inode_info *info = SHMEM_I(inode);\n \tstruct shmem_sb_info *sbinfo = SHMEM_SB(inode-\u003ei_sb);\n \tpgoff_t index;\n-\tint nr_pages;\n+\tint nr_pages, ret;\n \tbool split = false;\n \n \tif ((info-\u003eflags \u0026 SHMEM_F_LOCKED) || sbinfo-\u003enoswap)\n@@ -1693,7 +1693,8 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,\n \t\tfolio_mark_uptodate(folio);\n \t}\n \n-\tif (!folio_alloc_swap(folio)) {\n+\tret = folio_alloc_swap(folio);\n+\tif (!ret) {\n \t\tbool first_swapped = shmem_recalc_inode(inode, 0, nr_pages);\n \t\tint error;\n \n@@ -1746,7 +1747,7 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,\n \t\tswap_cache_del_folio(folio);\n \t\tgoto redirty;\n \t}\n-\tif (nr_pages \u003e 1)\n+\tif (nr_pages \u003e 1 \u0026\u0026 ret == -E2BIG)\n \t\tgoto try_split;\n redirty:\n \tfolio_mark_dirty(folio);\ndiff --git a/mm/swapfile.c b/mm/swapfile.c\nindex 51f5a525bb61c..dc0cd0cc6f626 100644\n--- a/mm/swapfile.c\n+++ b/mm/swapfile.c\n@@ -1735,7 +1735,9 @@ static int swap_dup_entries_cluster(struct swap_info_struct *si,\n * swap cache.\n *\n * Context: Caller needs to hold the folio lock.\n- * Return: Whether the folio was added to the swap cache.\n+ * Return: %0 on success, %-E2BIG if splitting the folio might allow swapout,\n+ * %-ENOSPC if no global swap space is available, or %-ENOMEM if splitting\n+ * would not help.\n */\n int folio_alloc_swap(struct folio *folio)\n {\n@@ -1747,11 +1749,11 @@ int folio_alloc_swap(struct folio *folio)\n \n \tif (order) {\n \t\t/*\n-\t\t * Reject large allocation when THP_SWAP is disabled,\n-\t\t * the caller should split the folio and try again.\n+\t\t * Reject large allocation when THP_SWAP is disabled. Check below\n+\t\t * whether splitting and retrying can make progress.\n \t\t */\n \t\tif (!IS_ENABLED(CONFIG_THP_SWAP))\n-\t\t\treturn -EAGAIN;\n+\t\t\tgoto failed;\n \n \t\t/*\n \t\t * Allocation size should never exceed cluster size\n@@ -1759,7 +1761,7 @@ int folio_alloc_swap(struct folio *folio)\n \t\t */\n \t\tif (size \u003e SWAPFILE_CLUSTER) {\n \t\t\tVM_WARN_ON_ONCE(1);\n-\t\t\treturn -EINVAL;\n+\t\t\tgoto failed;\n \t\t}\n \t}\n \n@@ -1775,13 +1777,23 @@ int folio_alloc_swap(struct folio *folio)\n \t}\n \n \t/* Need to call this even if allocation failed, for MEMCG_SWAP_FAIL. */\n-\tif (unlikely(mem_cgroup_try_charge_swap(folio)))\n+\tif (unlikely(mem_cgroup_try_charge_swap(folio))) {\n \t\tswap_cache_del_folio(folio);\n+\t\tgoto failed;\n+\t}\n \n \tif (unlikely(!folio_test_swapcache(folio)))\n-\t\treturn -ENOMEM;\n+\t\tgoto failed;\n \n \treturn 0;\n+\n+failed:\n+\tif (get_nr_swap_pages() \u003c= 0)\n+\t\treturn -ENOSPC;\n+\tif (mem_cgroup_get_folio_swap_margin(folio) \u003c= 0)\n+\t\treturn -ENOMEM;\n+\n+\treturn order ? -E2BIG : -ENOMEM;\n }\n \n /**\ndiff --git a/mm/vmscan.c b/mm/vmscan.c\nindex fdd13299a04a9..6e770a08e2880 100644\n--- a/mm/vmscan.c\n+++ b/mm/vmscan.c\n@@ -1259,6 +1259,8 @@ static unsigned int shrink_folio_list(struct list_head *folio_list,\n \t\t */\n \t\tif (folio_test_anon(folio) \u0026\u0026 folio_test_swapbacked(folio) \u0026\u0026\n \t\t\t\t!folio_test_swapcache(folio)) {\n+\t\t\tint ret;\n+\n \t\t\tif (!(sc-\u003egfp_mask \u0026 __GFP_IO))\n \t\t\t\tgoto keep_locked;\n \t\t\tif (folio_maybe_dma_pinned(folio))\n@@ -1277,11 +1279,14 @@ static unsigned int shrink_folio_list(struct list_head *folio_list,\n \t\t\t\t split_folio_to_list(folio, folio_list))\n \t\t\t\t\tgoto activate_locked;\n \t\t\t}\n-\t\t\tif (folio_alloc_swap(folio)) {\n+\t\t\tret = folio_alloc_swap(folio);\n+\t\t\tif (ret) {\n \t\t\t\tint __maybe_unused order = folio_order(folio);\n \n \t\t\t\tif (!folio_test_large(folio))\n \t\t\t\t\tgoto activate_locked_split;\n+\t\t\t\tif (ret != -E2BIG)\n+\t\t\t\t\tgoto activate_locked;\n \t\t\t\t/* Fallback to swap normal pages */\n \t\t\t\tif (split_folio_to_list(folio, folio_list))\n \t\t\t\t\tgoto activate_locked;\n"
} |
| 2/1 | 2026/08/30 04:59 | agent | patch-evaluator |
3mModel:core Args: null Results: {
"EnableConfigs": [
"SWAP",
"MEMCG",
"TRANSPARENT_HUGEPAGE",
"THP_SWAP",
"SHMEM"
],
"FocusSymbols": [
"folio_alloc_swap",
"mem_cgroup_get_folio_swap_margin",
"page_counter_margin",
"shmem_writeout"
],
"Reasoning": "The patch modifies memory management swap allocation logic by refining error reporting in folio_alloc_swap() and adding page_counter_margin() and mem_cgroup_get_folio_swap_margin() to inspect hierarchical swap margins. This changes how large folios are split and handled during swapout in shmem_writeout() and page reclaim in shrink_folio_list() when global or memcg swap limits are reached.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 31516bd662f92816ad63537de1ee7eaf9e957cb9
Author: syz-cluster <triage@syzkaller.com>
Date: Sun Aug 30 04:59:52 2026 +0000
syz-cluster: applied patch under review
diff --git a/include/linux/page_counter.h b/include/linux/page_counter.h
index d649b6bbbc871..07b7cb12249c7 100644
--- a/include/linux/page_counter.h
+++ b/include/linux/page_counter.h
@@ -68,6 +68,7 @@ static inline unsigned long page_counter_read(struct page_counter *counter)
return atomic_long_read(&counter->usage);
}
+long page_counter_margin(struct page_counter *counter);
void page_counter_cancel(struct page_counter *counter, unsigned long nr_pages);
void page_counter_charge(struct page_counter *counter, unsigned long nr_pages);
bool page_counter_try_charge(struct page_counter *counter,
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 0f953ed9c8630..a72ecf12c00db 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -510,6 +510,7 @@ static inline void mem_cgroup_uncharge_swap(unsigned short id, unsigned int nr_p
__mem_cgroup_uncharge_swap(id, nr_pages);
}
+long mem_cgroup_get_folio_swap_margin(struct folio *folio);
extern long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg);
extern bool mem_cgroup_swap_full(struct folio *folio);
#else
@@ -523,6 +524,11 @@ static inline void mem_cgroup_uncharge_swap(unsigned short id,
{
}
+static inline long mem_cgroup_get_folio_swap_margin(struct folio *folio)
+{
+ return PAGE_COUNTER_MAX;
+}
+
static inline long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg)
{
return get_nr_swap_pages();
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 4a18ee4509ab6..9a3804132c2eb 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -5801,15 +5801,35 @@ long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg)
{
long nr_swap_pages = get_nr_swap_pages();
- if (mem_cgroup_disabled() || do_memsw_account())
- return nr_swap_pages;
- for (; !mem_cgroup_is_root(memcg); memcg = parent_mem_cgroup(memcg))
- nr_swap_pages = min_t(long, nr_swap_pages,
- READ_ONCE(memcg->swap.max) -
- page_counter_read(&memcg->swap));
+ if (!mem_cgroup_disabled() && !do_memsw_account())
+ nr_swap_pages = min(nr_swap_pages, page_counter_margin(&memcg->swap));
+
return nr_swap_pages;
}
+/**
+ * mem_cgroup_get_folio_swap_margin - get a folio's memcg swap margin
+ * @folio: folio whose memcg margin is queried
+ *
+ * Return: Remaining chargeable pages in the folio's memcg hierarchy.
+ */
+long mem_cgroup_get_folio_swap_margin(struct folio *folio)
+{
+ struct mem_cgroup *memcg;
+ long margin;
+
+ if (mem_cgroup_disabled() || do_memsw_account() ||
+ !folio_memcg_charged(folio))
+ return PAGE_COUNTER_MAX;
+
+ rcu_read_lock();
+ memcg = folio_memcg(folio);
+ margin = page_counter_margin(&memcg->swap);
+ rcu_read_unlock();
+
+ return margin;
+}
+
bool mem_cgroup_swap_full(struct folio *folio)
{
struct mem_cgroup *memcg;
diff --git a/mm/page_counter.c b/mm/page_counter.c
index 661e0f2a5127a..450543f4b318b 100644
--- a/mm/page_counter.c
+++ b/mm/page_counter.c
@@ -46,6 +46,26 @@ static void propagate_protected_usage(struct page_counter *c,
}
}
+/**
+ * page_counter_margin - remaining usable space within hierarchical limits
+ * @counter: counter
+ *
+ * Return: The minimum value of max minus usage across @counter and all of
+ * its ancestors. The value may be negative during a concurrent charge.
+ */
+long page_counter_margin(struct page_counter *counter)
+{
+ long margin = PAGE_COUNTER_MAX;
+
+ do {
+ long m = READ_ONCE(counter->max) - page_counter_read(counter);
+
+ margin = min(margin, m);
+ } while ((counter = counter->parent));
+
+ return margin;
+}
+
/**
* page_counter_cancel - take pages out of the local counter
* @counter: counter
diff --git a/mm/shmem.c b/mm/shmem.c
index de144a9a9558b..84b8e9e05973b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1612,7 +1612,7 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,
struct shmem_inode_info *info = SHMEM_I(inode);
struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
pgoff_t index;
- int nr_pages;
+ int nr_pages, ret;
bool split = false;
if ((info->flags & SHMEM_F_LOCKED) || sbinfo->noswap)
@@ -1693,7 +1693,8 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,
folio_mark_uptodate(folio);
}
- if (!folio_alloc_swap(folio)) {
+ ret = folio_alloc_swap(folio);
+ if (!ret) {
bool first_swapped = shmem_recalc_inode(inode, 0, nr_pages);
int error;
@@ -1746,7 +1747,7 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,
swap_cache_del_folio(folio);
goto redirty;
}
- if (nr_pages > 1)
+ if (nr_pages > 1 && ret == -E2BIG)
goto try_split;
redirty:
folio_mark_dirty(folio);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 51f5a525bb61c..dc0cd0cc6f626 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1735,7 +1735,9 @@ static int swap_dup_entries_cluster(struct swap_info_struct *si,
* swap cache.
*
* Context: Caller needs to hold the folio lock.
- * Return: Whether the folio was added to the swap cache.
+ * Return: %0 on success, %-E2BIG if splitting the folio might allow swapout,
+ * %-ENOSPC if no global swap space is available, or %-ENOMEM if splitting
+ * would not help.
*/
int folio_alloc_swap(struct folio *folio)
{
@@ -1747,11 +1749,11 @@ int folio_alloc_swap(struct folio *folio)
if (order) {
/*
- * Reject large allocation when THP_SWAP is disabled,
- * the caller should split the folio and try again.
+ * Reject large allocation when THP_SWAP is disabled. Check below
+ * whether splitting and retrying can make progress.
*/
if (!IS_ENABLED(CONFIG_THP_SWAP))
- return -EAGAIN;
+ goto failed;
/*
* Allocation size should never exceed cluster size
@@ -1759,7 +1761,7 @@ int folio_alloc_swap(struct folio *folio)
*/
if (size > SWAPFILE_CLUSTER) {
VM_WARN_ON_ONCE(1);
- return -EINVAL;
+ goto failed;
}
}
@@ -1775,13 +1777,23 @@ int folio_alloc_swap(struct folio *folio)
}
/* Need to call this even if allocation failed, for MEMCG_SWAP_FAIL. */
- if (unlikely(mem_cgroup_try_charge_swap(folio)))
+ if (unlikely(mem_cgroup_try_charge_swap(folio))) {
swap_cache_del_folio(folio);
+ goto failed;
+ }
if (unlikely(!folio_test_swapcache(folio)))
- return -ENOMEM;
+ goto failed;
return 0;
+
+failed:
+ if (get_nr_swap_pages() <= 0)
+ return -ENOSPC;
+ if (mem_cgroup_get_folio_swap_margin(folio) <= 0)
+ return -ENOMEM;
+
+ return order ? -E2BIG : -ENOMEM;
}
/**
diff --git a/mm/vmscan.c b/mm/vmscan.c
index fdd13299a04a9..6e770a08e2880 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1259,6 +1259,8 @@ static unsigned int shrink_folio_list(struct list_head *folio_list,
*/
if (folio_test_anon(folio) && folio_test_swapbacked(folio) &&
!folio_test_swapcache(folio)) {
+ int ret;
+
if (!(sc->gfp_mask & __GFP_IO))
goto keep_locked;
if (folio_maybe_dma_pinned(folio))
@@ -1277,11 +1279,14 @@ static unsigned int shrink_folio_list(struct list_head *folio_list,
split_folio_to_list(folio, folio_list))
goto activate_locked;
}
- if (folio_alloc_swap(folio)) {
+ ret = folio_alloc_swap(folio);
+ if (ret) {
int __maybe_unused order = folio_order(folio);
if (!folio_test_large(folio))
goto activate_locked_split;
+ if (ret != -E2BIG)
+ goto activate_locked;
/* Fallback to swap normal pages */
if (split_folio_to_list(folio, folio_list))
goto activate_locked;
|
| 3/2 | 2026/08/30 04:59 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 4852 output: 26 thoughts: 580 Thoughts: **My Assessment of the Patch's Fuzzing Potential** Okay, let's break this down. My initial thought is to figure out if this patch introduces functional changes that warrant fuzzing. Right off the bat, I see the patch touches a bunch of key memory management files: `page_counter.h`, `swap.h`, `memcontrol.c`, `page_counter.c`, `shmem.c`, `swapfile.c`, and `vmscan.c`. That gets my attention immediately; anything touching the core MM is always interesting from a fuzzing perspective. Now, let's dive into the changes themselves. There's a new function, `page_counter_margin`, which looks like it calculates the remaining usable space within hierarchical limits. It's used in a refactored `mem_cgroup_get_nr_swap_pages`, and also there's a new function `mem_cgroup_get_folio_swap_margin`. Those seem related to memcg swap accounting. Then I see that `shmem_writeout` now checks the return value of `folio_alloc_swap`, and particularly the case of `nr_pages > 1 && ret == -E2BIG`. `folio_alloc_swap` seems to be the big change, altering its return values to signal more granular reasons for failure. It's not just success/failure anymore; now it returns specific error codes like `-E2BIG`, `-ENOSPC`, and `-ENOMEM`. The logic within `folio_alloc_swap` itself has been beefed up to check swap margins and memcg margins. And `shrink_folio_list` is now checking `ret` from `folio_alloc_swap` as well. The implications are clear: this patch is deeply intertwined with swap allocation, the splitting of large folios, memcg swap accounting and throttling, shmem swapout, and even page reclaim through `shrink_folio_list`. This is all core memory management, influencing execution flow in response to memory pressures and, importantly, altering error codes. Is it worth fuzzing? Absolutely. This is crucial mm logic dealing with swapout, splitting of folios under swap pressure, and memcg limits. It's definitely reachable in a standard environment (QEMU, syzkaller). The modifications to control flow and return codes in the kernel are exactly the kind of thing that fuzzing is designed to uncover subtle errors or unexpected interactions. The next step is to figure out the relevant configs and focus my symbol analysis appropriately. I need to dig into the source and identify the configurations that enable or affect this code, so I can target the fuzzing effectively. |
| 4/2 | 2026/08/30 05:00 | tool | grepper |
0mArgs:{
"Expression": "folio_alloc_swap",
"PathPrefix": "mm"
}Results: {
"Output": "mm/shmem.c=1607=int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,\n--\nmm/shmem.c-1695-\nmm/shmem.c:1696:\tret = folio_alloc_swap(folio);\nmm/shmem.c-1697-\tif (!ret) {\n--\nmm/swap.h=225=extern int swap_retry_table_alloc(swp_entry_t entry, gfp_t gfp);\n--\nmm/swap.h-233- *\nmm/swap.h:234: * folio_alloc_swap(): the entry point for a folio to be swapped\nmm/swap.h-235- * out. It allocates swap slots and pins the slots with swap cache.\n--\nmm/swap.h-245- */\nmm/swap.h:246:int folio_alloc_swap(struct folio *folio);\nmm/swap.h-247-int folio_dup_swap(struct folio *folio, struct page *page);\n--\nmm/swap.h=360=static inline struct swap_info_struct *__swap_entry_to_info(swp_entry_t entry)\n--\nmm/swap.h-364-\nmm/swap.h:365:static inline int folio_alloc_swap(struct folio *folio)\nmm/swap.h-366-{\n--\nmm/swapfile.c=90=static PLIST_HEAD(swap_active_head);\n--\nmm/swapfile.c-94- * protected with swap_avail_lock, ordered by priority.\nmm/swapfile.c:95: * This is used by folio_alloc_swap() instead of swap_active_head\nmm/swapfile.c-96- * because swap_active_head includes all swap_info_structs,\nmm/swapfile.c:97: * but folio_alloc_swap() doesn't need to look at full ones.\nmm/swapfile.c-98- * This uses its own lock instead of swap_lock because when a\n--\nmm/swapfile.c=911=static bool __swap_cluster_alloc_entries(struct swap_info_struct *si,\n--\nmm/swapfile.c-924-\t/*\nmm/swapfile.c:925:\t * All mm swap allocation starts with a folio (folio_alloc_swap),\nmm/swapfile.c-926-\t * it's also the only allocation path for large orders allocation.\n--\nmm/swapfile.c=1695=static int swap_dup_entries_cluster(struct swap_info_struct *si,\n--\nmm/swapfile.c-1730-/**\nmm/swapfile.c:1731: * folio_alloc_swap - allocate swap space for a folio\nmm/swapfile.c-1732- * @folio: folio we want to move to swap\n--\nmm/swapfile.c-1741- */\nmm/swapfile.c:1742:int folio_alloc_swap(struct folio *folio)\nmm/swapfile.c-1743-{\n--\nmm/swapfile.c=2809=static int try_to_unuse(unsigned int type)\n--\nmm/swapfile.c-2892-\t * and even shmem_writeout() could have been preempted after\nmm/swapfile.c:2893:\t * folio_alloc_swap(), temporarily hiding that swap. It's easy\nmm/swapfile.c-2894-\t * and robust (though cpu-intensive) just to keep retrying.\n--\nmm/vmscan.c=1058=static unsigned int shrink_folio_list(struct list_head *folio_list,\n--\nmm/vmscan.c-1281-\t\t\t}\nmm/vmscan.c:1282:\t\t\tret = folio_alloc_swap(folio);\nmm/vmscan.c-1283-\t\t\tif (ret) {\n--\nmm/vmscan.c-1300-\t\t\t\tcount_mthp_stat(order, MTHP_STAT_SWPOUT_FALLBACK);\nmm/vmscan.c:1301:\t\t\t\tif (folio_alloc_swap(folio))\nmm/vmscan.c-1302-\t\t\t\t\tgoto activate_locked_split;\n"
} |
| 5/2 | 2026/08/30 05:00 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 7101 output: 35 thoughts: 48 Thoughts: Okay, let's dive into this. Here's how I'd approach this task, as if these were my internal thoughts: **Investigating Swap Folio Allocation and Memcg Interaction** Right, so I need to figure out the dependencies and enabling conditions for `folio_alloc_swap` and `mem_cgroup_get_folio_swap_margin`. Given my expertise, I already know these are key functions related to how the kernel handles swapping, particularly in conjunction with memory cgroups. The logical place to start digging is the swap and memory management header files. Let's see... I'll check `include/linux/swap.h` first; often the public-facing definitions and macros are housed there. If that's not yielding the right clues, I'll switch over to `mm/swap.h`. That's where I'd expect to find the lower-level implementation details, internal data structures, and perhaps more nuanced conditional compilation logic related to enabling these features. Knowing the kernel's source layout so well, I'm confident I'll pinpoint the configuration options and dependencies quickly. Time to crack open those files and see what the code reveals! |
| 6/2 | 2026/08/30 05:00 | tool | read-file |
0mArgs:{
"File": "include/linux/swap.h",
"FirstLine": 500,
"LineCount": 40
}Results: {
"Contents": " 500:\t\tif (mem_cgroup_disabled())\n 501:\t\t\treturn 0;\n 502:\t\treturn __mem_cgroup_try_charge_swap(folio);\n 503:\t}\n 504:\t\n 505:\textern void __mem_cgroup_uncharge_swap(unsigned short id, unsigned int nr_pages);\n 506:\tstatic inline void mem_cgroup_uncharge_swap(unsigned short id, unsigned int nr_pages)\n 507:\t{\n 508:\t\tif (mem_cgroup_disabled())\n 509:\t\t\treturn;\n 510:\t\t__mem_cgroup_uncharge_swap(id, nr_pages);\n 511:\t}\n 512:\t\n 513:\tlong mem_cgroup_get_folio_swap_margin(struct folio *folio);\n 514:\textern long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg);\n 515:\textern bool mem_cgroup_swap_full(struct folio *folio);\n 516:\t#else\n 517:\tstatic inline int mem_cgroup_try_charge_swap(struct folio *folio)\n 518:\t{\n 519:\t\treturn 0;\n 520:\t}\n 521:\t\n 522:\tstatic inline void mem_cgroup_uncharge_swap(unsigned short id,\n 523:\t\t\t\t\t\t unsigned int nr_pages)\n 524:\t{\n 525:\t}\n 526:\t\n 527:\tstatic inline long mem_cgroup_get_folio_swap_margin(struct folio *folio)\n 528:\t{\n 529:\t\treturn PAGE_COUNTER_MAX;\n 530:\t}\n 531:\t\n 532:\tstatic inline long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg)\n 533:\t{\n 534:\t\treturn get_nr_swap_pages();\n 535:\t}\n 536:\t\n 537:\tstatic inline bool mem_cgroup_swap_full(struct folio *folio)\n 538:\t{\n 539:\t\treturn vm_swap_full();\n"
} |
| 7/2 | 2026/08/30 05:00 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 8033 output: 35 thoughts: 22 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Diving into `include/linux/swap.h`** Alright, let's get down to brass tacks. I'm taking a look at line 500-ish of `include/linux/swap.h`. That file is the central nervous system for how the kernel handles swapping, so I have a hunch that something interesting will be there. Given my experience, I'm expecting to find either a core data structure related to swap entry management, page table manipulations, or perhaps some key function definitions related to swap in/out operations. It could be something related to the swap cache itself. Or maybe an interesting definition of some sort. Let's dig in and see what goodies await. |
| 8/2 | 2026/08/30 05:00 | tool | read-file |
0mArgs:{
"File": "include/linux/swap.h",
"FirstLine": 470,
"LineCount": 40
}Results: {
"Contents": " 470:\t\n 471:\tstatic inline int add_swap_extent(struct swap_info_struct *sis,\n 472:\t\t\t\t\t unsigned long start_page,\n 473:\t\t\t\t\t unsigned long nr_pages, sector_t start_block)\n 474:\t{\n 475:\t\treturn -EINVAL;\n 476:\t}\n 477:\t#endif /* CONFIG_SWAP */\n 478:\t#ifdef CONFIG_MEMCG\n 479:\tvoid lru_reparent_memcg(struct mem_cgroup *memcg, struct mem_cgroup *parent, int nid);\n 480:\t#endif\n 481:\t\n 482:\t#if defined(CONFIG_SWAP) \u0026\u0026 defined(CONFIG_MEMCG) \u0026\u0026 defined(CONFIG_BLK_CGROUP)\n 483:\tvoid __folio_throttle_swaprate(struct folio *folio, gfp_t gfp);\n 484:\tstatic inline void folio_throttle_swaprate(struct folio *folio, gfp_t gfp)\n 485:\t{\n 486:\t\tif (mem_cgroup_disabled())\n 487:\t\t\treturn;\n 488:\t\t__folio_throttle_swaprate(folio, gfp);\n 489:\t}\n 490:\t#else\n 491:\tstatic inline void folio_throttle_swaprate(struct folio *folio, gfp_t gfp)\n 492:\t{\n 493:\t}\n 494:\t#endif\n 495:\t\n 496:\t#if defined(CONFIG_MEMCG) \u0026\u0026 defined(CONFIG_SWAP)\n 497:\tint __mem_cgroup_try_charge_swap(struct folio *folio);\n 498:\tstatic inline int mem_cgroup_try_charge_swap(struct folio *folio)\n 499:\t{\n 500:\t\tif (mem_cgroup_disabled())\n 501:\t\t\treturn 0;\n 502:\t\treturn __mem_cgroup_try_charge_swap(folio);\n 503:\t}\n 504:\t\n 505:\textern void __mem_cgroup_uncharge_swap(unsigned short id, unsigned int nr_pages);\n 506:\tstatic inline void mem_cgroup_uncharge_swap(unsigned short id, unsigned int nr_pages)\n 507:\t{\n 508:\t\tif (mem_cgroup_disabled())\n 509:\t\t\treturn;\n"
} |
| 9/2 | 2026/08/30 05:00 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 8908 output: 27 thoughts: 57 Thoughts: Okay, here's my take on those config options – let's see if I'm on the right track here... **Kernel Configuration Deep Dive: Memory Management** Alright, so I'm thinking about memory management, and it's clear that `CONFIG_MEMCG` (memory cgroups) and `CONFIG_SWAP` are obviously fundamental. Gotta get those right to have a usable system! But, I'm already thinking ahead, and want to consider how to optimize swapping and transparent huge pages. What's the relationship, specifically, between `CONFIG_THP_SWAP` and `CONFIG_TRANSPARENT_HUGEPAGE`? I need to clarify if having one without the other makes sense, or if their interplay is essential to get the system behaving as I expect. My next step will be to explore their interaction. |
| 10/2 | 2026/08/30 05:00 | tool | grepper |
0mArgs:{
"Expression": "config THP_SWAP",
"PathPrefix": "mm"
}Results: {
"Output": "mm/Kconfig=964=endchoice\nmm/Kconfig-965-\nmm/Kconfig:966:config THP_SWAP\nmm/Kconfig-967-\tdef_bool y\n"
} |
| 11/2 | 2026/08/30 05:00 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 9236 output: 32 thoughts: 17 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Diving into the Kernel Configuration Landscape** Okay, so I'm thinking, let's zero in on `mm/Kconfig`. I've got a hunch about something related to memory management and it's time to dig into the configuration options. My experience tells me that line 966 in `mm/Kconfig` is often a good place to start when I'm chasing something specific. Could be a feature flag, a dependency, or a default setting I'm trying to trace. Let's see what gems are hidden there and see what is available within that line of code. Time to get my hands dirty and understand this specific area of the kernel config in more detail. |
| 12/2 | 2026/08/30 05:01 | tool | read-file |
0mArgs:{
"File": "mm/Kconfig",
"FirstLine": 955,
"LineCount": 30
}Results: {
"Contents": " 955:\t\t provided by the applications.\n 956:\t\n 957:\t\tconfig TRANSPARENT_HUGEPAGE_TMPFS_HUGE_ADVISE\n 958:\t\t\tbool \"advise\"\n 959:\t\thelp\n 960:\t\t Enable hugepage allocation for the tmpfs mount exclusively when\n 961:\t\t applications supply the madvise(MADV_HUGEPAGE) hint.\n 962:\t\t This ensures that hugepages are used only in response to explicit\n 963:\t\t requests from applications.\n 964:\tendchoice\n 965:\t\n 966:\tconfig THP_SWAP\n 967:\t\tdef_bool y\n 968:\t\tdepends on ARCH_WANTS_THP_SWAP \u0026\u0026 SWAP \u0026\u0026 64BIT\n 969:\t\thelp\n 970:\t\t Swap transparent huge pages in one piece, without splitting.\n 971:\t\t XXX: For now, swap cluster backing transparent huge page\n 972:\t\t will be split after swapout.\n 973:\t\n 974:\t\t For selection by architectures with reasonable THP sizes.\n 975:\t\n 976:\tconfig NO_PAGE_MAPCOUNT\n 977:\t\tbool \"No per-page mapcount (EXPERIMENTAL)\"\n 978:\t\thelp\n 979:\t\t Do not maintain per-page mapcounts for pages part of larger\n 980:\t\t allocations, such as transparent huge pages.\n 981:\t\n 982:\t\t When this config option is enabled, some interfaces that relied on\n 983:\t\t this information will rely on less-precise per-allocation information\n 984:\t\t instead: for example, using the average per-page mapcount in such\n"
} |
| 13/2 | 2026/08/30 05:01 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 9909 output: 26 thoughts: 337 Thoughts: **Analyzing Swap and Memory Management in the Kernel** Okay, so I need to get a handle on the changes related to memory control and swap. First things first: `CONFIG_MEMCG` and `CONFIG_SWAP` in Kconfig. Gotta make sure those are properly configured. And while I'm at it, I should see if `CONFIG_SHMEM` has any bearing on this. Next, I'll need to look at the function modifications. Here's what I've got: 1. `page_counter_margin` in `mm/page_counter.c` 2. `mem_cgroup_get_folio_swap_margin` in `mm/memcontrol.c` 3. `mem_cgroup_get_nr_swap_pages` in `mm/memcontrol.c` 4. `folio_alloc_swap` in `mm/swapfile.c` 5. `shmem_writeout` in `mm/shmem.c` 6. `shrink_folio_list` in `mm/vmscan.c` Right, `shrink_folio_list` is static, which is good to know, but the others look interesting. They're non-static, so the scope and visibility are a bit different, potentially indicating more important API entrypoints. Now, to nail down the important API entrypoints for FocusSymbols, I need to identify the non-hot-path, non-static, non-inlined entrypoint functions: `folio_alloc_swap`, `mem_cgroup_get_folio_swap_margin`, `page_counter_margin`, and `mem_cgroup_get_nr_swap_pages`. These are the key functions I should be focusing on. And finally, I'll double-check `shmem_writeout` to see if it's static or exported. That detail is important for understanding its scope and use. |
| 14/2 | 2026/08/30 05:01 | tool | grepper |
0mArgs:{
"Expression": "shmem_writeout",
"PathPrefix": "mm"
}Results: {
"Output": "mm/shmem.c=47=static struct vfsmount *shm_mnt __ro_after_init;\n--\nmm/shmem.c-101-/*\nmm/shmem.c:102: * shmem_fallocate communicates with shmem_fault or shmem_writeout via\nmm/shmem.c-103- * inode-\u003ei_private (with i_rwsem making sure that it has only one user at\n--\nmm/shmem.c=414=static void shmem_free_inode(struct super_block *sb, size_t freed_ispace)\n--\nmm/shmem.c-435- *\nmm/shmem.c:436: * Return: true if swapped was incremented from 0, for shmem_writeout().\nmm/shmem.c-437- */\nmm/shmem.c=438=bool shmem_recalc_inode(struct inode *inode, long alloced, long swapped)\n--\nmm/shmem.c-451-\t * after i_mapping-\u003enrpages has already been adjusted (up or down),\nmm/shmem.c:452:\t * shmem_writeout() has to raise swapped before nrpages is lowered -\nmm/shmem.c-453-\t * to stop a racing shmem_recalc_inode() from thinking that a page has\n--\nmm/shmem.c=1556=int shmem_unuse(unsigned int type)\n--\nmm/shmem.c-1599-/**\nmm/shmem.c:1600: * shmem_writeout - Write the folio to swap\nmm/shmem.c-1601- * @ctx: swap I/O context\n--\nmm/shmem.c-1606- */\nmm/shmem.c:1607:int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,\nmm/shmem.c-1608-\t\tstruct list_head *folio_list)\n--\nmm/shmem.c-1743-\t\t * but I'm a little nervous about letting this folio out of\nmm/shmem.c:1744:\t\t * shmem_writeout() in a hybrid half-tmpfs-half-swap state\nmm/shmem.c-1745-\t\t * e.g. folio_mapping(folio) might give an unexpected answer.\n--\nmm/shmem.c=1757=int shmem_write_folio(struct folio *folio)\n--\nmm/shmem.c-1761-\nmm/shmem.c:1762:\terr = shmem_writeout(\u0026ctx, folio, NULL);\nmm/shmem.c-1763-\tswap_write_submit(\u0026ctx);\n--\nmm/shmem.c=3624=static long shmem_fallocate(struct file *file, int mode, loff_t offset,\n--\nmm/shmem.c-3760-\t\t/*\nmm/shmem.c:3761:\t\t * Inform shmem_writeout() how far we have reached.\nmm/shmem.c-3762-\t\t * No need for lock or barrier: we have the page lock.\n--\nmm/swap.h=465=extern const struct swap_ops swap_bdev_ops;\nmm/swap.h-466-\nmm/swap.h:467:int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,\nmm/swap.h-468-\t\tstruct list_head *folio_list);\n--\nmm/swapfile.c=2809=static int try_to_unuse(unsigned int type)\n--\nmm/swapfile.c-2891-\t * exit_mmap(), which proceeds at its own independent pace;\nmm/swapfile.c:2892:\t * and even shmem_writeout() could have been preempted after\nmm/swapfile.c-2893-\t * folio_alloc_swap(), temporarily hiding that swap. It's easy\n--\nmm/vmscan.c=621=static pageout_t pageout(struct swap_io_ctx *ctx, struct address_space *mapping,\n--\nmm/vmscan.c-657-\tif (shmem_mapping(mapping))\nmm/vmscan.c:658:\t\tres = shmem_writeout(ctx, folio, folio_list);\nmm/vmscan.c-659-\telse\n"
} |
| 15/2 | 2026/08/30 05:01 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 11810 output: 36 thoughts: 194 Thoughts: **My Investigation into Swap and Memory Management** Okay, so `shmem_writeout` is defined in `mm/swap.h`, and it's not a static function, which is useful to know. I need to understand its relationship to memory cgroups and swapping, so let me quickly review a few key functions: `mem_cgroup_get_folio_swap_margin`, `folio_alloc_swap`, `shmem_writeout` (of course!), `page_counter_margin`, and `mem_cgroup_get_nr_swap_pages`. These seem like the core pieces. Now, let's nail down the configuration dependencies. I'm pretty sure I can find the relevant config options in `mm/Makefile` or perhaps `include/linux/swap.h`. Specifically, I need to verify: * `SWAP`: This one's the fundamental enabler for swapfile functionality, so it's critical. * `MEMCG`: This must be the key to how memory cgroups and swap limits interact. * `SHMEM`: This should be critical since I am considering `shmem_writeout`. * And finally, I need to check either `THP_SWAP` or `TRANSPARENT_HUGEPAGE` – those are the multi-page folio swap flags that could influence all of this. To be thorough, let's quickly double-check `mm/Makefile` again, specifically for swapfile.c and memcontrol.c; I just want to make sure I haven't missed anything obvious with the config flags that govern their inclusion or behavior. |
| 16/2 | 2026/08/30 05:02 | tool | grepper |
0mArgs:{
"Expression": "swapfile\\.o|memcontrol\\.o|page_counter\\.o",
"PathPrefix": "mm"
}Results: {
"Output": "mm/Makefile=27=KCOV_INSTRUMENT_kmemleak.o := n\nmm/Makefile:28:KCOV_INSTRUMENT_memcontrol.o := n\nmm/Makefile-29-KCOV_INSTRUMENT_memcontrol-v1.o := n\n--\nmm/Makefile=76=endif\nmm/Makefile-77-\nmm/Makefile:78:obj-$(CONFIG_SWAP)\t+= page_io.o swap_state.o swapfile.o\nmm/Makefile-79-obj-$(CONFIG_ZSWAP)\t+= zswap.o\n--\nmm/Makefile=101=obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += huge_memory.o khugepaged.o\nmm/Makefile:102:obj-$(CONFIG_PAGE_COUNTER) += page_counter.o\nmm/Makefile-103-obj-$(CONFIG_LIVEUPDATE_MEMFD) += memfd_luo.o\nmm/Makefile=104=obj-$(CONFIG_MEMCG_V1) += memcontrol-v1.o\nmm/Makefile:105:obj-$(CONFIG_MEMCG) += memcontrol.o vmpressure.o\nmm/Makefile-106-ifdef CONFIG_BPF_SYSCALL\nmm/Makefile:107:obj-$(CONFIG_MEMCG) += bpf_memcontrol.o\nmm/Makefile-108-endif\n"
} |
| 17/2 | 2026/08/30 05:02 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 12740 output: 25 thoughts: 11 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Checking `CONFIG_PAGE_COUNTER`** Alright, let's dive right in. My first thought is to verify the state of `CONFIG_PAGE_COUNTER`. This variable, as we all know, is absolutely critical when we're dealing with... well, pretty much any memory management aspect. I need to quickly confirm whether it's enabled or disabled in the current configuration. Depending on its status, the implications will be immediately apparent and they'll drive the next line of thought. If it is enabled, that says a lot about the assumptions in the rest of the code, how page counters are used for tracking, and maybe how this whole thing behaves in different memory contexts. Disabling it... well that's a whole different ballgame of tradeoffs and optimizations, which will shift my focus elsewhere, possibly to custom memory management logic or specific hardware constraints. So, let me just quickly confirm, and then we'll move on. |
| 18/2 | 2026/08/30 05:02 | tool | grepper |
0mArgs:{
"Expression": "config PAGE_COUNTER",
"PathPrefix": "init"
}Results: {
"Output": "init/Kconfig=1063=if CGROUPS\ninit/Kconfig-1064-\ninit/Kconfig:1065:config PAGE_COUNTER\ninit/Kconfig-1066-\tbool\n"
} |
| 19/2 | 2026/08/30 05:02 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 13054 output: 33 thoughts: 18 Thoughts: Here's my take on those thoughts: **Peering into the Kernel Configuration Landscape** Okay, let's dive in. Based on the task at hand, I need to understand the configuration options related to whatever functionality I'm working with. A good starting point, as always, is the `init/Kconfig` file. Specifically, I'll focus my attention around line 1065. I'm hoping that this section will provide the necessary clues about the relevant configuration knobs and their dependencies. I'm expecting this area to be a central hub for defining the default kernel configuration and the different configuration options available in this section. |
| 20/2 | 2026/08/30 05:02 | tool | read-file |
0mArgs:{
"File": "init/Kconfig",
"FirstLine": 1050,
"LineCount": 40
}Results: {
"Contents": "1050:\t\tbool \"Control Group support\"\n1051:\t\tselect KERNFS\n1052:\t\thelp\n1053:\t\t This option adds support for grouping sets of processes together, for\n1054:\t\t use with process control subsystems such as Cpusets, CFS, memory\n1055:\t\t controls or device isolation.\n1056:\t\t See\n1057:\t\t\t- Documentation/scheduler/sched-design-CFS.rst\t(CFS)\n1058:\t\t\t- Documentation/admin-guide/cgroup-v1/ (features for grouping, isolation\n1059:\t\t\t\t\t\t and resource control)\n1060:\t\n1061:\t\t Say N if unsure.\n1062:\t\n1063:\tif CGROUPS\n1064:\t\n1065:\tconfig PAGE_COUNTER\n1066:\t\tbool\n1067:\t\n1068:\tconfig CGROUP_FAVOR_DYNMODS\n1069:\t\tbool \"Favor dynamic modification latency reduction by default\"\n1070:\t\thelp\n1071:\t\t This option enables the \"favordynmods\" mount option by default\n1072:\t\t which reduces the latencies of dynamic cgroup modifications such\n1073:\t\t as task migrations and controller on/offs at the cost of making\n1074:\t\t hot path operations such as forks and exits more expensive.\n1075:\t\n1076:\t\t Say N if unsure.\n1077:\t\n1078:\tconfig MEMCG\n1079:\t\tbool \"Memory controller\"\n1080:\t\tselect PAGE_COUNTER\n1081:\t\tselect EVENTFD\n1082:\t\tselect SLAB_OBJ_EXT\n1083:\t\tselect VM_EVENT_COUNTERS\n1084:\t\thelp\n1085:\t\t Provides control over the memory footprint of tasks in a cgroup.\n1086:\t\n1087:\tconfig MEMCG_NMI_UNSAFE\n1088:\t\tbool\n1089:\t\tdepends on MEMCG\n"
} |
| 21/2 | 2026/08/30 05:02 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 13777 output: 189 thoughts: 367 Thoughts: **My Assessment of the Proposed Patch** Okay, so the patch is targeting some crucial memory management areas, specifically around swap and folio allocation. From my understanding of the configurations, `MEMCG` relies on `CGROUPS`, and is a prerequisite, so that's good. We also have `SWAP` enabled, which is essential, as are `TRANSPARENT_HUGEPAGE`, `THP_SWAP`, and `SHMEM`. All the dependencies for this functionality appear to be in place. Checking the "WorthFuzzing" flag and the configuration requirements, yes, that's all inline with my expectations. This seems like a valid area to focus our efforts, given the listed `EnableConfigs`. The patch is working with folio swap allocation, memcg swap margin tracking, and shmem writeout. The key symbols that the patch specifically calls out include `folio_alloc_swap`, `mem_cgroup_get_folio_swap_margin`, `page_counter_margin`, and `shmem_writeout`, which is exactly what I would expect for a change impacting how we handle memory pressure, especially concerning swapping. Specifically, the more granular error codes from `folio_alloc_swap` for swap limits is a smart change. Returning `-E2BIG`, `-ENOSPC`, and `-ENOMEM` depending on whether a memcg or global limit is the constraint is much cleaner. Avoiding unnecessary splitting of large folios when we're hitting a limit is going to be useful under memory pressure. This is a solid update to the core memory management, and is directly impacting both swap and reclaim. Based on this review, everything appears to be in order. The patch addresses relevant areas, and the proposed changes seem accurate and well-reasoned. I'm comfortable with the current assessment. |
| 22/2 | 2026/08/30 05:03 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"SWAP",
"MEMCG",
"TRANSPARENT_HUGEPAGE",
"THP_SWAP",
"SHMEM"
],
"FocusSymbols": [
"folio_alloc_swap",
"mem_cgroup_get_folio_swap_margin",
"page_counter_margin",
"shmem_writeout"
],
"Reasoning": "The patch modifies memory management swap allocation logic by refining error reporting in folio_alloc_swap() and adding page_counter_margin() and mem_cgroup_get_folio_swap_margin() to inspect hierarchical swap margins. This changes how large folios are split and handled during swapout in shmem_writeout() and page reclaim in shrink_folio_list() when global or memcg swap limits are reached.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"SWAP",
"MEMCG",
"TRANSPARENT_HUGEPAGE",
"THP_SWAP",
"SHMEM"
],
"FocusSymbols": [
"folio_alloc_swap",
"mem_cgroup_get_folio_swap_margin",
"page_counter_margin",
"shmem_writeout"
],
"Reasoning": "The patch modifies memory management swap allocation logic by refining error reporting in folio_alloc_swap() and adding page_counter_margin() and mem_cgroup_get_folio_swap_margin() to inspect hierarchical swap margins. This changes how large folios are split and handled during swapout in shmem_writeout() and page reclaim in shrink_folio_list() when global or memcg swap limits are reached.",
"WorthFuzzing": true
} |
| 23/1 | 2026/08/30 05:03 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 24/2 | 2026/08/30 05:03 | agent | kmsan-evaluator |
0mModel:core Args: null Results: {
"KMSANReasoning": "The patch enhances swap allocation error reporting in `folio_alloc_swap()` by distinguishing between cases where a large folio allocation failed due to folio size vs. total swap/cgroup swap exhaustion. It introduces `page_counter_margin()` and `mem_cgroup_get_folio_swap_margin()` and updates folio splitting decisions in `mm/vmscan.c` and `mm/shmem.c`.\n\nKMSAN vs KASAN Applicability:\n- Uninitialized Memory (KMSAN): All local variables (`ret`, `margin`, `m`) are explicitly initialized before use. No kernel structures or buffers are copied to user space, and no uninitialized memory reads or allocations are introduced.\n- Memory Safety \u0026 Logic (KASAN/Lockdep): Any risks in this patch revolve around cgroup swap accounting, page locking, refcounting, or control-flow logic in reclaim/writeout, which are monitored by standard MM assertions, KASAN, and Lockdep.\n\nTherefore, dedicated KMSAN fuzzing is not required.",
"NeedsKMSAN": false
}Instruction: You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.
CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
a comprehensive suite of debugging tools and sanitizers, including KASAN
(out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
(locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
or page allocations) and kernel-to-user memory info-leaks.
Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.
Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.
Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
attributes, ioctl output arguments, socket options, or BPF buffers) where fields
or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
uninitialized bytes of existing buffers.
Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
dereferences, locking deadlocks, or use-after-free bugs (these are already caught
by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.
Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt: For your convenience, here is the diff of the changes:
commit 31516bd662f92816ad63537de1ee7eaf9e957cb9
Author: syz-cluster <triage@syzkaller.com>
Date: Sun Aug 30 04:59:52 2026 +0000
syz-cluster: applied patch under review
diff --git a/include/linux/page_counter.h b/include/linux/page_counter.h
index d649b6bbbc871..07b7cb12249c7 100644
--- a/include/linux/page_counter.h
+++ b/include/linux/page_counter.h
@@ -68,6 +68,7 @@ static inline unsigned long page_counter_read(struct page_counter *counter)
return atomic_long_read(&counter->usage);
}
+long page_counter_margin(struct page_counter *counter);
void page_counter_cancel(struct page_counter *counter, unsigned long nr_pages);
void page_counter_charge(struct page_counter *counter, unsigned long nr_pages);
bool page_counter_try_charge(struct page_counter *counter,
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 0f953ed9c8630..a72ecf12c00db 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -510,6 +510,7 @@ static inline void mem_cgroup_uncharge_swap(unsigned short id, unsigned int nr_p
__mem_cgroup_uncharge_swap(id, nr_pages);
}
+long mem_cgroup_get_folio_swap_margin(struct folio *folio);
extern long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg);
extern bool mem_cgroup_swap_full(struct folio *folio);
#else
@@ -523,6 +524,11 @@ static inline void mem_cgroup_uncharge_swap(unsigned short id,
{
}
+static inline long mem_cgroup_get_folio_swap_margin(struct folio *folio)
+{
+ return PAGE_COUNTER_MAX;
+}
+
static inline long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg)
{
return get_nr_swap_pages();
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 4a18ee4509ab6..9a3804132c2eb 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -5801,15 +5801,35 @@ long mem_cgroup_get_nr_swap_pages(struct mem_cgroup *memcg)
{
long nr_swap_pages = get_nr_swap_pages();
- if (mem_cgroup_disabled() || do_memsw_account())
- return nr_swap_pages;
- for (; !mem_cgroup_is_root(memcg); memcg = parent_mem_cgroup(memcg))
- nr_swap_pages = min_t(long, nr_swap_pages,
- READ_ONCE(memcg->swap.max) -
- page_counter_read(&memcg->swap));
+ if (!mem_cgroup_disabled() && !do_memsw_account())
+ nr_swap_pages = min(nr_swap_pages, page_counter_margin(&memcg->swap));
+
return nr_swap_pages;
}
+/**
+ * mem_cgroup_get_folio_swap_margin - get a folio's memcg swap margin
+ * @folio: folio whose memcg margin is queried
+ *
+ * Return: Remaining chargeable pages in the folio's memcg hierarchy.
+ */
+long mem_cgroup_get_folio_swap_margin(struct folio *folio)
+{
+ struct mem_cgroup *memcg;
+ long margin;
+
+ if (mem_cgroup_disabled() || do_memsw_account() ||
+ !folio_memcg_charged(folio))
+ return PAGE_COUNTER_MAX;
+
+ rcu_read_lock();
+ memcg = folio_memcg(folio);
+ margin = page_counter_margin(&memcg->swap);
+ rcu_read_unlock();
+
+ return margin;
+}
+
bool mem_cgroup_swap_full(struct folio *folio)
{
struct mem_cgroup *memcg;
diff --git a/mm/page_counter.c b/mm/page_counter.c
index 661e0f2a5127a..450543f4b318b 100644
--- a/mm/page_counter.c
+++ b/mm/page_counter.c
@@ -46,6 +46,26 @@ static void propagate_protected_usage(struct page_counter *c,
}
}
+/**
+ * page_counter_margin - remaining usable space within hierarchical limits
+ * @counter: counter
+ *
+ * Return: The minimum value of max minus usage across @counter and all of
+ * its ancestors. The value may be negative during a concurrent charge.
+ */
+long page_counter_margin(struct page_counter *counter)
+{
+ long margin = PAGE_COUNTER_MAX;
+
+ do {
+ long m = READ_ONCE(counter->max) - page_counter_read(counter);
+
+ margin = min(margin, m);
+ } while ((counter = counter->parent));
+
+ return margin;
+}
+
/**
* page_counter_cancel - take pages out of the local counter
* @counter: counter
diff --git a/mm/shmem.c b/mm/shmem.c
index de144a9a9558b..84b8e9e05973b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1612,7 +1612,7 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,
struct shmem_inode_info *info = SHMEM_I(inode);
struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
pgoff_t index;
- int nr_pages;
+ int nr_pages, ret;
bool split = false;
if ((info->flags & SHMEM_F_LOCKED) || sbinfo->noswap)
@@ -1693,7 +1693,8 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,
folio_mark_uptodate(folio);
}
- if (!folio_alloc_swap(folio)) {
+ ret = folio_alloc_swap(folio);
+ if (!ret) {
bool first_swapped = shmem_recalc_inode(inode, 0, nr_pages);
int error;
@@ -1746,7 +1747,7 @@ int shmem_writeout(struct swap_io_ctx *ctx, struct folio *folio,
swap_cache_del_folio(folio);
goto redirty;
}
- if (nr_pages > 1)
+ if (nr_pages > 1 && ret == -E2BIG)
goto try_split;
redirty:
folio_mark_dirty(folio);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 51f5a525bb61c..dc0cd0cc6f626 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1735,7 +1735,9 @@ static int swap_dup_entries_cluster(struct swap_info_struct *si,
* swap cache.
*
* Context: Caller needs to hold the folio lock.
- * Return: Whether the folio was added to the swap cache.
+ * Return: %0 on success, %-E2BIG if splitting the folio might allow swapout,
+ * %-ENOSPC if no global swap space is available, or %-ENOMEM if splitting
+ * would not help.
*/
int folio_alloc_swap(struct folio *folio)
{
@@ -1747,11 +1749,11 @@ int folio_alloc_swap(struct folio *folio)
if (order) {
/*
- * Reject large allocation when THP_SWAP is disabled,
- * the caller should split the folio and try again.
+ * Reject large allocation when THP_SWAP is disabled. Check below
+ * whether splitting and retrying can make progress.
*/
if (!IS_ENABLED(CONFIG_THP_SWAP))
- return -EAGAIN;
+ goto failed;
/*
* Allocation size should never exceed cluster size
@@ -1759,7 +1761,7 @@ int folio_alloc_swap(struct folio *folio)
*/
if (size > SWAPFILE_CLUSTER) {
VM_WARN_ON_ONCE(1);
- return -EINVAL;
+ goto failed;
}
}
@@ -1775,13 +1777,23 @@ int folio_alloc_swap(struct folio *folio)
}
/* Need to call this even if allocation failed, for MEMCG_SWAP_FAIL. */
- if (unlikely(mem_cgroup_try_charge_swap(folio)))
+ if (unlikely(mem_cgroup_try_charge_swap(folio))) {
swap_cache_del_folio(folio);
+ goto failed;
+ }
if (unlikely(!folio_test_swapcache(folio)))
- return -ENOMEM;
+ goto failed;
return 0;
+
+failed:
+ if (get_nr_swap_pages() <= 0)
+ return -ENOSPC;
+ if (mem_cgroup_get_folio_swap_margin(folio) <= 0)
+ return -ENOMEM;
+
+ return order ? -E2BIG : -ENOMEM;
}
/**
diff --git a/mm/vmscan.c b/mm/vmscan.c
index fdd13299a04a9..6e770a08e2880 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1259,6 +1259,8 @@ static unsigned int shrink_folio_list(struct list_head *folio_list,
*/
if (folio_test_anon(folio) && folio_test_swapbacked(folio) &&
!folio_test_swapcache(folio)) {
+ int ret;
+
if (!(sc->gfp_mask & __GFP_IO))
goto keep_locked;
if (folio_maybe_dma_pinned(folio))
@@ -1277,11 +1279,14 @@ static unsigned int shrink_folio_list(struct list_head *folio_list,
split_folio_to_list(folio, folio_list))
goto activate_locked;
}
- if (folio_alloc_swap(folio)) {
+ ret = folio_alloc_swap(folio);
+ if (ret) {
int __maybe_unused order = folio_order(folio);
if (!folio_test_large(folio))
goto activate_locked_split;
+ if (ret != -E2BIG)
+ goto activate_locked;
/* Fallback to swap normal pages */
if (split_folio_to_list(folio, folio_list))
goto activate_locked;
|
| 25/3 | 2026/08/30 05:03 | llm | kmsan-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 4849 output: 244 thoughts: 1141 Thoughts: **KMSAN Analysis of Memory Management Patch** Okay, let's break this down. The patch is centered around refining error handling and folio management related to swap operations, specifically in the context of cgroups. My immediate concern is whether this introduces any uninitialized memory vulnerabilities that would warrant KMSAN fuzzing. I need to make sure this doesn't create any kernel-to-user copies of uninitialized data, introduce uninitialized variables, or allow access to uninitialized memory through new conditional logic. I see it touches several key areas: `page_counter_margin`, `mem_cgroup_get_folio_swap_margin`, `folio_alloc_swap`, `shmem_writeout`, and `shrink_folio_list`. The core of the changes revolve around better distinguishing the reasons for a failed `folio_alloc_swap`: whether it's because of the size of the request (`-E2BIG`) or insufficient swap space (`-ENOSPC` or `-ENOMEM`). This information is then used to optimize folio splitting in the `vmscan` and `shmem` code. Looking closely at the code snippets, the variables are initialized before use. The logic involves checking return values or margins, but not reading uninitialized memory. The `page_counter_margin` calculation iterates through a hierarchy, but all intermediate variables are initialized within the loop. The return values of `folio_alloc_swap` are explicitly defined integer codes. The return value is used to decide the correct action and is checked immediately after assignment. Nothing is getting copied to userspace. No complex structures are being allocated and no conditional logic depends on an uninitialized value. I reviewed the KMSAN requirements – specifically looking for kernel-to-user copies of uninitialized structures, conditional logic based on uninitialized data, complex uninitialized structures, and any opportunities for surrounding code to access uninitialized memory. None of these apply here. There's no uninitialized memory read or leakage to user space. It seems that any potential bugs here would be classic memory management issues: logic errors, memory leaks, out-of-bounds access, or cgroup accounting bugs, which are well-covered by standard KASAN, LOCKDEP, and kernel assertions like `VM_WARN_ON_ONCE`. So, from my expert perspective, KMSAN is not necessary here. The patch focuses on improving error handling and folio management based on the swap margin and space availability. It refines the error signaling from the `folio_alloc_swap` function and uses these codes for smarter folio splitting and readahead. All the new variables are initialized, there are no kernel-to-user copies, no new allocations of uninitialized memory and no reads of uninitialized memory. Standard kernel testing is sufficient for this patch. I'll document this reasoning and submit the results to the tooling. |
| 26/3 | 2026/08/30 05:03 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch enhances swap allocation error reporting in `folio_alloc_swap()` by distinguishing between cases where a large folio allocation failed due to folio size vs. total swap/cgroup swap exhaustion. It introduces `page_counter_margin()` and `mem_cgroup_get_folio_swap_margin()` and updates folio splitting decisions in `mm/vmscan.c` and `mm/shmem.c`.\n\nKMSAN vs KASAN Applicability:\n- Uninitialized Memory (KMSAN): All local variables (`ret`, `margin`, `m`) are explicitly initialized before use. No kernel structures or buffers are copied to user space, and no uninitialized memory reads or allocations are introduced.\n- Memory Safety \u0026 Logic (KASAN/Lockdep): Any risks in this patch revolve around cgroup swap accounting, page locking, refcounting, or control-flow logic in reclaim/writeout, which are monitored by standard MM assertions, KASAN, and Lockdep.\n\nTherefore, dedicated KMSAN fuzzing is not required.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch enhances swap allocation error reporting in `folio_alloc_swap()` by distinguishing between cases where a large folio allocation failed due to folio size vs. total swap/cgroup swap exhaustion. It introduces `page_counter_margin()` and `mem_cgroup_get_folio_swap_margin()` and updates folio splitting decisions in `mm/vmscan.c` and `mm/shmem.c`.\n\nKMSAN vs KASAN Applicability:\n- Uninitialized Memory (KMSAN): All local variables (`ret`, `margin`, `m`) are explicitly initialized before use. No kernel structures or buffers are copied to user space, and no uninitialized memory reads or allocations are introduced.\n- Memory Safety \u0026 Logic (KASAN/Lockdep): Any risks in this patch revolve around cgroup swap accounting, page locking, refcounting, or control-flow logic in reclaim/writeout, which are monitored by standard MM assertions, KASAN, and Lockdep.\n\nTherefore, dedicated KMSAN fuzzing is not required.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|