From: Alex Markuze Date: Mon, 17 Mar 2025 15:08:26 +0000 (+0000) Subject: pagefrag allocation fixups X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ca02ecf6a70fb4081bfc616ace5a60c3605fb637;p=ceph-client.git pagefrag allocation fixups --- diff --git a/include/linux/ceph/ceph_san_pagefrag.h b/include/linux/ceph/ceph_san_pagefrag.h index 2475d90fc09f..5b74172ce1a9 100644 --- a/include/linux/ceph/ceph_san_pagefrag.h +++ b/include/linux/ceph/ceph_san_pagefrag.h @@ -23,6 +23,9 @@ 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); +/* Get allocation size from pagefrag allocation result */ +u64 cephsan_pagefrag_get_alloc_size(u64 val); + #define CEPHSAN_PAGEFRAG_GET_N(val) ((val) >> 32) #endif /* CEPH_SAN_PAGEFRAG_H */ diff --git a/net/ceph/ceph_san_logger.c b/net/ceph/ceph_san_logger.c index 3bb0f7b06e84..d60af8cf82b9 100644 --- a/net/ceph/ceph_san_logger.c +++ b/net/ceph/ceph_san_logger.c @@ -120,7 +120,7 @@ void ceph_san_log(const char *file, unsigned int line, const char *fmt, ...) struct ceph_san_log_entry *entry; va_list args; u64 alloc; - int len; + int len, needed_size; ctx = ceph_san_get_tls_ctx(); if (!ctx) @@ -130,14 +130,22 @@ void ceph_san_log(const char *file, unsigned int line, const char *fmt, ...) len = vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); + needed_size = sizeof(*entry) + len + 1; /* Allocate entry from pagefrag */ //We need a spinlock here to protect printing - alloc = cephsan_pagefrag_alloc(&ctx->pf, sizeof(*entry) + len + 1); + alloc = cephsan_pagefrag_alloc(&ctx->pf, needed_size); while (!alloc) { entry = cephsan_pagefrag_get_ptr_from_tail(&ctx->pf); BUG_ON(entry->debug_poison != CEPH_SAN_LOG_ENTRY_POISON); BUG_ON(entry->len == 0); cephsan_pagefrag_free(&ctx->pf, entry->len); - alloc = cephsan_pagefrag_alloc(&ctx->pf, sizeof(*entry) + len + 1); + 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); @@ -150,7 +158,7 @@ void ceph_san_log(const char *file, unsigned int line, const char *fmt, ...) entry->ts = jiffies; entry->line = line; entry->file = file; - entry->len = len + sizeof(*entry) + 1; + entry->len = cephsan_pagefrag_get_alloc_size(alloc); } EXPORT_SYMBOL(ceph_san_log); diff --git a/net/ceph/ceph_san_pagefrag.c b/net/ceph/ceph_san_pagefrag.c index d34918044173..282b236376f6 100644 --- a/net/ceph/ceph_san_pagefrag.c +++ b/net/ceph/ceph_san_pagefrag.c @@ -52,10 +52,12 @@ EXPORT_SYMBOL(cephsan_pagefrag_init_with_buffer); */ u64 cephsan_pagefrag_alloc(struct cephsan_pagefrag *pf, unsigned int n) { + int delta = CEPHSAN_PAGEFRAG_SIZE - pf->head -n; + unsigned int prev_head = pf->head; + /* Case 1: tail > head */ if (pf->tail > pf->head) { if (pf->tail - pf->head > n) { - unsigned int prev_head = pf->head; pf->head += n; return ((u64)n << 32) | prev_head; } else { @@ -63,23 +65,21 @@ u64 cephsan_pagefrag_alloc(struct cephsan_pagefrag *pf, unsigned int n) } } /* Case 2: tail <= head */ - if (pf->head + n <= CEPHSAN_PAGEFRAG_SIZE) { + if (delta >= 0) { /* Normal allocation */ - unsigned int prev_head = pf->head; + /* make sure we have enough space to allocate next entry */ + if (unlikely(delta < 64)) { + n += delta; + pf->head = 0; + return ((u64)n << 32) | prev_head; + } pf->head += n; return ((u64)n << 32) | prev_head; } else { - /* Need to wrap around */ - if (n < pf->tail) { - pf->head = n; - n += CEPHSAN_PAGEFRAG_SIZE - pf->head; - return ((u64)n << 32) | 0; - } else { - return 0; - } + /* Need to wrap around return a partial allocation*/ + pf->head = 0; + return ((u64)delta << 32) | prev_head; } - pr_err("impossible: Not enough space in pagefrag buffer\n"); - return 0; } EXPORT_SYMBOL(cephsan_pagefrag_alloc); @@ -96,6 +96,12 @@ void *cephsan_pagefrag_get_ptr(struct cephsan_pagefrag *pf, u64 val) } EXPORT_SYMBOL(cephsan_pagefrag_get_ptr); +u64 cephsan_pagefrag_get_alloc_size(u64 val) +{ + return val >> 32; +} +EXPORT_SYMBOL(cephsan_pagefrag_get_alloc_size); + /** * cephsan_pagefrag_get_ptr_from_tail - Get buffer pointer from pagefrag tail * @pf: pagefrag allocator