]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
pagefrag allocation fixups
authorAlex Markuze <amarkuze@redhat.com>
Mon, 17 Mar 2025 15:08:26 +0000 (15:08 +0000)
committerAlex Markuze <amarkuze@redhat.com>
Mon, 17 Mar 2025 15:08:26 +0000 (15:08 +0000)
include/linux/ceph/ceph_san_pagefrag.h
net/ceph/ceph_san_logger.c
net/ceph/ceph_san_pagefrag.c

index 2475d90fc09fbd84606660fc513273f052f28d4f..5b74172ce1a9b5469b2a16044e52960efc37593d 100644 (file)
@@ -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 */
index 3bb0f7b06e840013a7ccf80e3921802ceef5e536..d60af8cf82b92e498bd9455c3490a2d60085a351 100644 (file)
@@ -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);
 
index d34918044173c67ffb805746ef63132605aa8651..282b236376f613cb87cfff0f3c3c39db4c8019a3 100644 (file)
@@ -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