From 2d39b6ecbca8ec343f16d8307013c800c74f8d47 Mon Sep 17 00:00:00 2001 From: Alex Markuze Date: Tue, 18 Mar 2025 19:35:02 +0000 Subject: [PATCH] better wrapparound handling --- include/linux/ceph/ceph_san_pagefrag.h | 1 + net/ceph/ceph_san_logger.c | 13 +++++-------- net/ceph/ceph_san_pagefrag.c | 27 +++++++++++++++++++++++--- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/include/linux/ceph/ceph_san_pagefrag.h b/include/linux/ceph/ceph_san_pagefrag.h index 85248b851b643..fc7e08246dc54 100644 --- a/include/linux/ceph/ceph_san_pagefrag.h +++ b/include/linux/ceph/ceph_san_pagefrag.h @@ -25,6 +25,7 @@ void cephsan_pagefrag_free(struct cephsan_pagefrag *pf, unsigned int n); void cephsan_pagefrag_deinit(struct cephsan_pagefrag *pf); void cephsan_pagefrag_reset(struct cephsan_pagefrag *pf); void *cephsan_pagefrag_get_ptr(struct cephsan_pagefrag *pf, u64 val); +bool cephsan_pagefrag_is_wraparound(u64 val); /* Get allocation size from pagefrag allocation result */ u64 cephsan_pagefrag_get_alloc_size(u64 val); diff --git a/net/ceph/ceph_san_logger.c b/net/ceph/ceph_san_logger.c index 0c43c38b2e387..70c86d2af5ed2 100644 --- a/net/ceph/ceph_san_logger.c +++ b/net/ceph/ceph_san_logger.c @@ -147,13 +147,6 @@ void ceph_san_log(const char *file, const char *func, unsigned int line, const c BUG_ON(entry->len == 0); cephsan_pagefrag_free(&ctx->pf, entry->len); alloc = cephsan_pagefrag_alloc(&ctx->pf, needed_size); - //In case we hit the wrap around, we may get a partial allocation that should be marked as used - if (alloc && cephsan_pagefrag_get_alloc_size(alloc) < needed_size) { - entry = cephsan_pagefrag_get_ptr(&ctx->pf, alloc); - memset(entry->buffer, 0, sizeof(entry->buffer)); - entry->len = cephsan_pagefrag_get_alloc_size(alloc); - alloc = 0; - } } entry = cephsan_pagefrag_get_ptr(&ctx->pf, alloc); @@ -163,7 +156,11 @@ void ceph_san_log(const char *file, const char *func, unsigned int line, const c entry->line = line; entry->file = file; entry->func = func; - entry->buffer = (char *)(entry + 1); + if (unlikely(cephsan_pagefrag_is_wraparound(alloc))) { + entry->buffer = cephsan_pagefrag_get_ptr(&ctx->pf, 0); + } else { + entry->buffer = (char *)(entry + 1); + } entry->len = cephsan_pagefrag_get_alloc_size(alloc); spin_unlock(&ctx->pf.lock); diff --git a/net/ceph/ceph_san_pagefrag.c b/net/ceph/ceph_san_pagefrag.c index 80d34d0458546..416f969810cb9 100644 --- a/net/ceph/ceph_san_pagefrag.c +++ b/net/ceph/ceph_san_pagefrag.c @@ -78,9 +78,13 @@ u64 cephsan_pagefrag_alloc(struct cephsan_pagefrag *pf, unsigned int n) pf->head += n; return ((u64)n << 32) | prev_head; } else { - /* Need to wrap around return a partial allocation*/ - pf->head = 0; - return ((u64)delta << 32) | prev_head; + if (pf->tail > n) { + /* Need to wrap around return a partial allocation*/ + pf->head = n; + return ((u64)(delta + n) << 32) | prev_head; + } else { + return 0; + } } } EXPORT_SYMBOL(cephsan_pagefrag_alloc); @@ -104,6 +108,23 @@ u64 cephsan_pagefrag_get_alloc_size(u64 val) } EXPORT_SYMBOL(cephsan_pagefrag_get_alloc_size); +/** + * cephsan_pagefrag_is_wraparound - Check if allocation wraps around buffer end + * @val: Return value from cephsan_pagefrag_alloc + * + * Checks if the allocation represented by @val wraps around the end of the + * pagefrag buffer by verifying if alloc_size + address > CEPHSAN_PAGEFRAG_SIZE. + * + * Return: true if allocation wraps around, false otherwise + */ +bool cephsan_pagefrag_is_wraparound(u64 val) +{ + u32 addr = val & 0xFFFFFFFF; + u32 size = val >> 32; + return (addr + size) > CEPHSAN_PAGEFRAG_SIZE; +} +EXPORT_SYMBOL(cephsan_pagefrag_is_wraparound); + /** * cephsan_pagefrag_get_ptr_from_tail - Get buffer pointer from pagefrag tail * @pf: pagefrag allocator -- 2.39.5