From 8dbc761389e7379d4b7fe416fd3031c198e41b25 Mon Sep 17 00:00:00 2001 From: wangrong Date: Tue, 1 Sep 2026 14:40:32 +0800 Subject: [PATCH] fix(kernelmod): page-align ring buffer allocation for non-4K page kernels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vzalloc rounds up to whole pages, but mem_size recorded the raw header+data total. On 16 KiB/64 KiB page kernels the consumer's page-aligned mmap was larger than mem_size and got rejected. 将 ring buffer 分配大小在 vzalloc 前显式按页对齐,使分配请求、 记录的 mem_size 与用户态 mmap 映射大小保持一致,修复非 4K 页 内核上 mmap 报 "size > mem_size" 导致模块不可用的问题。 Log: 修复非4K页内核上mmap大小检查失败 PMS: BUG-374927 Influence: 修复在 Loongson 等非4K页内核上 vfs_monitor 模块 mmap 失败导致服务不可用的问题。 --- src/kernelmod/vfs_chrdev.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/kernelmod/vfs_chrdev.c b/src/kernelmod/vfs_chrdev.c index 9f1ef817..406e4d5e 100644 --- a/src/kernelmod/vfs_chrdev.c +++ b/src/kernelmod/vfs_chrdev.c @@ -64,23 +64,32 @@ static int vfs_ring_init(struct vfs_ring *ring, u32 capacity, u32 record_size) struct vfs_ringbuf_header *hdr; size_t header_size; size_t data_size; - size_t total; + size_t alloc_size; header_size = sizeof(struct vfs_ringbuf_header); data_size = (size_t)capacity * record_size; - total = header_size + data_size; + + /* Align the allocation to a whole number of pages up front. On + * kernels whose PAGE_SIZE != 4096 (e.g. Loongson 16 KiB, arm64 + * 64 KiB) the raw header+data total is not a page multiple, so + * the consumer's mmap() — which the kernel page-aligns — would + * be larger than the recorded size and get rejected with + * "size > mem_size". Page-aligning here keeps the allocation + * request, the recorded mem_size, and the consumer's mapping + * all in sync. */ + alloc_size = PAGE_ALIGN(header_size + data_size); /* vmalloc gives virtually-contiguous memory without MAX_ORDER * limits; physical pages are discontiguous, which is fine for * this SPSC ring (single-record access, no DMA). */ - ring->mem = vzalloc(total); + ring->mem = vzalloc(alloc_size); if (!ring->mem) { - mpr_err("ring_init: vzalloc fail, total=%zu (capacity=%u, record_size=%u)\n", - total, capacity, record_size); + mpr_err("ring_init: vzalloc fail, alloc_size=%zu (capacity=%u, record_size=%u)\n", + alloc_size, capacity, record_size); return -ENOMEM; } - ring->mem_size = total; + ring->mem_size = alloc_size; hdr = (struct vfs_ringbuf_header *)ring->mem; hdr->magic = VFS_RINGBUF_MAGIC;