percpu_pagelist_high_fraction_sysctl_handler()是/proc/sys/vm/percpu_pagelist_high_fraction的 sysctl 处理函数,用于控制 PCP(Per-CPU Pages)缓存的high水位上限。它是 Mel Gorman 在 2021 年引入的、替代旧percpu_pagelist_fraction的新接口 。核心作用与背景旧percpu_pagelist_fraction同时调整pcp->batch和pcp->high,虽然能减少zone->lock竞争,但增大的batch会在 PCP 补充时增加分配延迟 。新接口只调整pcp->high,保持batch不变,从而在降低锁竞争的同时不损害分配延迟 。percpu_pagelist_high_fraction的含义是:每个 zone 中,所有 per-CPU 页链表能缓存的最大页数比例。这个上限会按在线 CPU 数量均分 。核心实现与近期修复2025 年底的一个补丁使读操作变为无锁,解决了内存下线期间读取该文件可能阻塞在pcp_batch_high_lock上导致 hung task 警告的问题 。修复后的逻辑如下:static int percpu_pagelist_high_fraction_sysctl_handler(const struct ctl_table *table, int write, void *buffer, size_t *length, loff_t *ppos) { int old_percpu_pagelist_high_fraction; int ret; /* 读操作无锁,直接返回 */ if (!write) return proc_dointvec_minmax(table, write, buffer, length, ppos); mutex_lock(&pcp_batch_high_lock); old_percpu_pagelist_high_fraction = percpu_pagelist_high_fraction; ret = proc_dointvec_minmax(table, write, buffer, length, ppos); if (ret < 0) goto out; /* 没有变化则直接退出 */ if (percpu_pagelist_high_fraction == old_percpu_pagelist_high_fraction) goto out; /* 更新所有 populated zone 的 PCP 配置 */ for_each_populated_zone(zone) { unsigned int cpu; for_each_possible_cpu(cpu) pageset_set_high_and_batch(zone, per_cpu_ptr(zone->pageset, cpu)); } out: mutex_unlock(&pcp_batch_high_lock); return ret; }参数语义与边界最小值为 8:表示单个 PCP 最多缓存 1/8 的 zone 页数。初始值为 0:表示使用内核默认策略(基于 zone 低水位线和在线 CPU 数计算)。写入 0会恢复默认行为 。与 PCP 自动调节的关系在 2023 年引入 PCPhigh自动调节机制后,percpu_pagelist_high_fraction的角色发生了变化:它不再直接固定pcp->high,而是作为自动调节的上界(high_max)参考值。pcp->high可以在high_min(基于低水位线)和high_max(基于该 fraction)之间动态变化。
percpu_pagelist_high_fraction_sysctl_handler()是/proc/sys/vm/percpu_pagelist_high_fraction的 sysctl 处理函数,用于控制 PCP(Per-CPU Pages)缓存的high水位上限。它是 Mel Gorman 在 2021 年引入的、替代旧percpu_pagelist_fraction的新接口 。核心作用与背景旧percpu_pagelist_fraction同时调整pcp->batch和pcp->high,虽然能减少zone->lock竞争,但增大的batch会在 PCP 补充时增加分配延迟 。新接口只调整pcp->high,保持batch不变,从而在降低锁竞争的同时不损害分配延迟 。percpu_pagelist_high_fraction的含义是:每个 zone 中,所有 per-CPU 页链表能缓存的最大页数比例。这个上限会按在线 CPU 数量均分 。核心实现与近期修复2025 年底的一个补丁使读操作变为无锁,解决了内存下线期间读取该文件可能阻塞在pcp_batch_high_lock上导致 hung task 警告的问题 。修复后的逻辑如下:static int percpu_pagelist_high_fraction_sysctl_handler(const struct ctl_table *table, int write, void *buffer, size_t *length, loff_t *ppos) { int old_percpu_pagelist_high_fraction; int ret; /* 读操作无锁,直接返回 */ if (!write) return proc_dointvec_minmax(table, write, buffer, length, ppos); mutex_lock(&pcp_batch_high_lock); old_percpu_pagelist_high_fraction = percpu_pagelist_high_fraction; ret = proc_dointvec_minmax(table, write, buffer, length, ppos); if (ret < 0) goto out; /* 没有变化则直接退出 */ if (percpu_pagelist_high_fraction == old_percpu_pagelist_high_fraction) goto out; /* 更新所有 populated zone 的 PCP 配置 */ for_each_populated_zone(zone) { unsigned int cpu; for_each_possible_cpu(cpu) pageset_set_high_and_batch(zone, per_cpu_ptr(zone->pageset, cpu)); } out: mutex_unlock(&pcp_batch_high_lock); return ret; }参数语义与边界最小值为 8:表示单个 PCP 最多缓存 1/8 的 zone 页数。初始值为 0:表示使用内核默认策略(基于 zone 低水位线和在线 CPU 数计算)。写入 0会恢复默认行为 。与 PCP 自动调节的关系在 2023 年引入 PCPhigh自动调节机制后,percpu_pagelist_high_fraction的角色发生了变化:它不再直接固定pcp->high,而是作为自动调节的上界(high_max)参考值。pcp->high可以在high_min(基于低水位线)和high_max(基于该 fraction)之间动态变化。