From 75b56e556ea415e29a13a8b7e98d302fbbec4c01 Mon Sep 17 00:00:00 2001 From: Alex Markuze Date: Mon, 17 Mar 2025 16:19:00 +0000 Subject: [PATCH] cephsan new logger --- fs/ceph/debugfs.c | 221 ++++------------- fs/ceph/super.c | 15 +- fs/ceph/super.h | 2 - include/linux/ceph/ceph_debug.h | 6 +- include/linux/ceph/ceph_san.h | 98 -------- include/linux/ceph/ceph_san_logger.h | 3 + net/ceph/Makefile | 2 +- net/ceph/ceph_san.c | 357 --------------------------- net/ceph/ceph_san_logger.c | 3 +- 9 files changed, 66 insertions(+), 641 deletions(-) delete mode 100644 include/linux/ceph/ceph_san.h delete mode 100644 net/ceph/ceph_san.c diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index f30bef4ec8460..8ae3a7b545599 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include @@ -23,86 +23,6 @@ #include "mds_client.h" #include "metric.h" -static int histogram_show(struct seq_file *s, void *p) -{ - struct ceph_san_percore_logger *pc; - size_t cpu; - u64 total_histogram[16] = {0}; - int i; - - seq_printf(s, "Ceph TLS Histogram Summary:\n"); - seq_printf(s, "%-10s %-16s\n", "Bucket", "Count"); - seq_printf(s, "-------------------------\n"); - - /* Sum up histograms from all CPUs */ - for_each_possible_cpu(cpu) { - pc = &per_cpu(ceph_san_percore, cpu); - - /* Add each CPU's histogram data to the total */ - for (i = 0; i < 16; i++) { - total_histogram[i] += pc->histogram.counters[i]; - } - } - - /* Calculate total sum for normalization */ - u64 sum = 0; - for (i = 0; i < 16; i++) { - sum += total_histogram[i]; - } - - /* Display normalized histogram with stars and percentages */ - for (i = 0; i < 16; i++) { - int stars = sum ? (total_histogram[i] * 128) / sum : 0; - u64 percent = sum ? (total_histogram[i] * 100) / sum : 0; - seq_printf(s, "%-4d [%3llu%%] ", i, percent); - while (stars-- > 0) - seq_printf(s, "*"); - seq_printf(s, "\n"); - } - - return 0; -} - -static int ceph_san_show(struct seq_file *s, void *p) -{ - struct ceph_san_percore_logger *pc; - size_t cpu; - - seq_printf(s, "Ceph SAN logs:\n"); - seq_printf(s, "%-16s %-8s %-32s\n", - "Task", "PID", "Log"); - seq_printf(s, "--------------------------------------------------------------\n"); - - for_each_possible_cpu(cpu) { - pc = &per_cpu(ceph_san_percore, cpu); - int i; - - int idx = 0; - int head_idx = pc->head_idx & (CEPH_SAN_MAX_LOGS - 1); - int tail_idx = (head_idx + 1) & (CEPH_SAN_MAX_LOGS - 1); - - for (i = tail_idx; (i & (CEPH_SAN_MAX_LOGS -1)) != head_idx; i++) { - struct timespec64 ts; - struct ceph_san_log_entry *log = &pc->logs[i & (CEPH_SAN_MAX_LOGS -1)]; - jiffies_to_timespec64(log->ts, &ts); - - if (log->ts == 0) { - continue; - } - seq_printf(s, "%zu:%lld.%09ld:%d) %-16s %-8d:%s\n", - cpu, - (long long)ts.tv_sec, - ts.tv_nsec, - idx++, - log->comm, - log->pid, - log->buf); - } - } - - return 0; -} - static int mdsmap_show(struct seq_file *s, void *p) { int i; @@ -443,104 +363,73 @@ static int status_show(struct seq_file *s, void *p) return 0; } -static int ceph_san_contexts_show(struct seq_file *s, void *p) +static int ceph_san_tls_show(struct seq_file *s, void *p) { - struct tls_ceph_san_context *ctx; - struct ceph_san_tls_logger *logger; - struct timespec64 ts; - unsigned long flags; - int count = 0; + struct ceph_san_tls_ctx *ctx; + struct ceph_san_log_iter iter; + struct ceph_san_log_entry *entry; - seq_printf(s, "All Ceph SAN TLS contexts:\n"); - seq_printf(s, "%-8s %-16s %-20s %-12s %-12s\n", - "PID", "Task", "Last Activity", "Cache Type", "Log Count"); - seq_printf(s, "--------------------------------------------------------------\n"); + /* Lock the logger to safely traverse the contexts list */ + spin_lock(&g_logger.lock); - spin_lock_irqsave(&g_ceph_san_contexts_lock, flags); + list_for_each_entry(ctx, &g_logger.contexts, list) { + /* Print context information */ + seq_printf(s, "Context: PID=%d Command=%s\n", ctx->pid, ctx->comm); - list_for_each_entry(ctx, &g_ceph_san_contexts, list) { - logger = &ctx->logger; - count++; + /* Initialize iterator for this context's pagefrag */ + ceph_san_log_iter_init(&iter, &ctx->pf); - /* Get timestamp of most recent log entry */ - int head_idx = logger->head_idx & (CEPH_SAN_MAX_LOGS - 1); - struct ceph_san_log_entry_tls *entry = &logger->logs[head_idx]; + /* Lock the pagefrag before accessing entries */ + spin_lock(&ctx->pf.lock); - if (entry->ts == 0) { - seq_printf(s, "%-8s %-16s %-20s %-12s %-12d\n", - "N/A", "N/A", "N/A", "N/A", 0); - continue; - } + /* Iterate through all log entries in this context */ + while ((entry = ceph_san_log_iter_next(&iter)) != NULL) { + if (entry->debug_poison != CEPH_SAN_LOG_ENTRY_POISON) { + seq_puts(s, " [Corrupted Entry]\n"); + continue; + } - jiffies_to_timespec64(entry->ts, &ts); + seq_printf(s, " [%llu] %s:%u: %.*s\n", + entry->ts, + entry->file, + entry->line, + entry->len, + entry->buffer); + } - seq_printf(s, "%-8d %-16s %-20lld.%09ld\n", - logger->pid, - logger->comm, - (long long)ts.tv_sec, - ts.tv_nsec); + /* Unlock the pagefrag after we're done with this context */ + spin_unlock(&ctx->pf.lock); } - spin_unlock_irqrestore(&g_ceph_san_contexts_lock, flags); - - seq_printf(s, "\nTotal contexts: %d\n", count); - + spin_unlock(&g_logger.lock); return 0; } -static int ceph_san_tls_show(struct seq_file *s, void *p) +static int ceph_san_contexts_show(struct seq_file *s, void *p) { - struct tls_ceph_san_context *ctx; - struct ceph_san_tls_logger *logger; - struct ceph_san_log_entry_tls *entry; + struct ceph_san_tls_ctx *ctx; unsigned long flags; - int count = 0; - - seq_printf(s, "All Ceph SAN TLS logs from all contexts:\n"); - seq_printf(s, "%-8s %-16s %-20s %-8s %-s\n", - "PID", "Task", "Timestamp", "Index", "Log Message"); - seq_printf(s, "-------------------------------------------------------------------------\n"); - - spin_lock_irqsave(&g_ceph_san_contexts_lock, flags); - - list_for_each_entry(ctx, &g_ceph_san_contexts, list) { - logger = &ctx->logger; - count++; - - seq_printf(s, "\n=== Context for PID %d ===\n", logger->pid); - - int idx = 0; - int head_idx = logger->head_idx & (CEPH_SAN_MAX_LOGS - 1); - int tail_idx = (head_idx + 1) & (CEPH_SAN_MAX_LOGS - 1); - for (int i = tail_idx; (i & (CEPH_SAN_MAX_LOGS - 1)) != head_idx; i++) { - struct timespec64 ts; - entry = &logger->logs[i & (CEPH_SAN_MAX_LOGS - 1)]; + /* Lock the logger to safely traverse the contexts list */ + spin_lock_irqsave(&g_logger.lock, flags); - if (entry->ts == 0 || !entry->buf) { - continue; - } + seq_puts(s, "Active TLS Contexts:\n"); + seq_puts(s, "PID Command Buffer Size\n"); + seq_puts(s, "----------------------------------------\n"); - jiffies_to_timespec64(entry->ts, &ts); - - seq_printf(s, "%-8d %-16s %lld.%09ld\n", - logger->pid, - logger->comm, - (long long)ts.tv_sec, - ts.tv_nsec); + list_for_each_entry(ctx, &g_logger.contexts, list) { + unsigned int buffer_size = ctx->pf.head - ctx->pf.tail; + if (ctx->pf.head < ctx->pf.tail) { + buffer_size = CEPHSAN_PAGEFRAG_SIZE - ctx->pf.tail + ctx->pf.head; } - seq_printf(s, "\n"); - } - - spin_unlock_irqrestore(&g_ceph_san_contexts_lock, flags); - - if (count == 0) { - seq_printf(s, "No TLS contexts found.\n"); - } else { - seq_printf(s, "\nTotal contexts: %d\n", count); + seq_printf(s, "%-8d %-15s %u bytes\n", + ctx->pid, + ctx->comm, + buffer_size); } + spin_unlock_irqrestore(&g_logger.lock, flags); return 0; } @@ -553,10 +442,8 @@ DEFINE_SHOW_ATTRIBUTE(metrics_file); DEFINE_SHOW_ATTRIBUTE(metrics_latency); DEFINE_SHOW_ATTRIBUTE(metrics_size); DEFINE_SHOW_ATTRIBUTE(metrics_caps); -DEFINE_SHOW_ATTRIBUTE(ceph_san); -DEFINE_SHOW_ATTRIBUTE(histogram); -DEFINE_SHOW_ATTRIBUTE(ceph_san_contexts); DEFINE_SHOW_ATTRIBUTE(ceph_san_tls); +DEFINE_SHOW_ATTRIBUTE(ceph_san_contexts); /* @@ -592,8 +479,6 @@ void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc) debugfs_remove(fsc->debugfs_caps); debugfs_remove(fsc->debugfs_status); debugfs_remove(fsc->debugfs_mdsc); - debugfs_remove(fsc->debugfs_cephsan); - debugfs_remove(fsc->debugfs_histogram); debugfs_remove(fsc->debugfs_cephsan_tls); debugfs_remove(fsc->debugfs_cephsan_contexts); debugfs_remove_recursive(fsc->debugfs_metrics_dir); @@ -648,17 +533,7 @@ void ceph_fs_debugfs_init(struct ceph_fs_client *fsc) fsc->client->debugfs_dir, fsc, &status_fops); - fsc->debugfs_cephsan = debugfs_create_file("cephsan", - 0444, - fsc->client->debugfs_dir, - fsc, - &ceph_san_fops); - fsc->debugfs_histogram = debugfs_create_file("histogram", - 0444, - fsc->client->debugfs_dir, - fsc, - &histogram_fops); fsc->debugfs_cephsan_tls = debugfs_create_file("cephsan_tls", 0444, @@ -666,13 +541,13 @@ void ceph_fs_debugfs_init(struct ceph_fs_client *fsc) fsc, &ceph_san_tls_fops); + /* Add the new contexts-only view */ fsc->debugfs_cephsan_contexts = debugfs_create_file("cephsan_contexts", 0444, fsc->client->debugfs_dir, fsc, &ceph_san_contexts_fops); - fsc->debugfs_metrics_dir = debugfs_create_dir("metrics", fsc->client->debugfs_dir); diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 6b5c1657febb2..5d81b65098165 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -1,8 +1,8 @@ -// SPDX-License-Identifier: GPL-2.0-only + #include "linux/mm_types.h" #include -#include +#include #include #include @@ -1639,15 +1639,18 @@ static int __init init_ceph(void) goto out; ceph_flock_init(); - ret = cephsan_init(); - ret = register_filesystem(&ceph_fs_type); + ret = ceph_san_logger_init(); if (ret) goto out_caches; + ret = register_filesystem(&ceph_fs_type); + if (ret) + goto out_logger; pr_info("loaded (mds proto %d)\n", CEPH_MDSC_PROTOCOL); return 0; - +out_logger: + ceph_san_logger_cleanup(); out_caches: destroy_caches(); out: @@ -1657,7 +1660,7 @@ out: static void __exit exit_ceph(void) { dout("exit_ceph\n"); - cephsan_cleanup(); + ceph_san_logger_cleanup(); unregister_filesystem(&ceph_fs_type); destroy_caches(); } diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 21c4d94c2a824..584a3fd15ed86 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -153,8 +153,6 @@ struct ceph_fs_client { struct dentry *debugfs_status; struct dentry *debugfs_mds_sessions; struct dentry *debugfs_metrics_dir; - struct dentry *debugfs_cephsan; - struct dentry *debugfs_histogram; struct dentry *debugfs_cephsan_contexts; struct dentry *debugfs_cephsan_tls; #endif diff --git a/include/linux/ceph/ceph_debug.h b/include/linux/ceph/ceph_debug.h index 229dbda82df93..59c35957e0238 100644 --- a/include/linux/ceph/ceph_debug.h +++ b/include/linux/ceph/ceph_debug.h @@ -6,7 +6,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include +#include #ifdef CONFIG_CEPH_LIB_PRETTYDEBUG @@ -51,9 +51,9 @@ /* * or, just wrap pr_debug */ -# define dout(fmt, ...) pr_debug(" " fmt, ##__VA_ARGS__) +# define dout(fmt, ...) CEPH_SAN_LOG(fmt, ##__VA_ARGS__) # define doutc(client, fmt, ...) \ - pr_debug(" [%pU %llu] %s: " fmt, &client->fsid, \ + CEPH_SAN_LOG(" [%pU %llu] %s: " fmt, &client->fsid, \ client->monc.auth->global_id, __func__, ##__VA_ARGS__) #endif diff --git a/include/linux/ceph/ceph_san.h b/include/linux/ceph/ceph_san.h deleted file mode 100644 index cb804baa5175f..0000000000000 --- a/include/linux/ceph/ceph_san.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef CEPHSAN_H -#define CEPHSAN_H - -#include -#include -#include -#include -#include -#include "ceph_san_pagefrag.h" - -DECLARE_PER_CPU(struct ceph_san_percore_logger, ceph_san_percore); -DECLARE_PER_CPU(struct cephsan_pagefrag, ceph_san_pagefrag); - -#ifdef CONFIG_DEBUG_FS -#define CEPH_SAN_MAX_LOGS (8192 << 2) //4MB per core -#define LOG_BUF_SIZE 256 -#define LOG_BUF_SMALL 128 - -void cephsan_cleanup(void); -int cephsan_init(void); - -void log_cephsan(char *buf); -void log_cephsan_tls(char *buf); -int cephsan_dump_all_contexts(char *buf, size_t size); - -#define CEPH_SAN_LOG(fmt, ...) do { \ - char buf[LOG_BUF_SIZE] = {0}; \ - snprintf(buf, LOG_BUF_SIZE, fmt, ##__VA_ARGS__); \ - log_cephsan(buf); \ -} while (0) - -#define CEPH_SAN_LOG_TLS(fmt, ...) do { \ - char buf[LOG_BUF_SIZE] = {0}; \ - snprintf(buf, LOG_BUF_SIZE, fmt, ##__VA_ARGS__); \ - log_cephsan_tls(buf); \ -} while (0) - -/* - * Internal definitions for Ceph SAN logs. - * These definitions are not part of the public API but are required by debugfs.c. - */ -struct ceph_san_log_entry { - char comm[TASK_COMM_LEN]; - char *buf; - u64 ts; - pid_t pid; - u32 len; -}; - -struct ceph_san_log_entry_tls { - u64 ts; - char *buf; -}; - -struct histogram { - u64 counters[32]; -}; - -struct ceph_san_percore_logger { - size_t head_idx; - struct page *pages; - struct ceph_san_log_entry *logs; - struct histogram histogram; -}; - -struct ceph_san_tls_logger { - char comm[TASK_COMM_LEN]; - pid_t pid; - size_t head_idx; - struct ceph_san_log_entry_tls logs[CEPH_SAN_MAX_LOGS]; -}; - -/* Bundled TLS context containing both logger and memory caches */ -struct tls_ceph_san_context { - u64 sig; - struct list_head list; /* For global list of contexts */ - struct ceph_san_tls_logger logger; -}; - -/* Global list of all TLS contexts and its protection lock */ -extern struct list_head g_ceph_san_contexts; -extern spinlock_t g_ceph_san_contexts_lock; - -#else /* CONFIG_DEBUG_FS */ - -#define CEPH_SAN_LOG(param) do {} while (0) -#define CEPH_SAN_LOG_TLS(param) do {} while (0) - -static inline void cephsan_cleanup(void) {} -static inline int __init cephsan_init(void) { return 0; } - -#endif /* CONFIG_DEBUG_FS */ - -#define CEPH_SAN_SET_REQ(req) do { current->journal_info = req; } while (0) -#define CEPH_SAN_RESET_REQ() do { current->journal_info = NULL; } while (0) -#define CEPH_SAN_GET_REQ() (current->journal_info) - -#endif /* CEPHSAN_H */ diff --git a/include/linux/ceph/ceph_san_logger.h b/include/linux/ceph/ceph_san_logger.h index 4ce1ed182bf32..e8614e46a51ae 100644 --- a/include/linux/ceph/ceph_san_logger.h +++ b/include/linux/ceph/ceph_san_logger.h @@ -67,4 +67,7 @@ struct ceph_san_tls_ctx *ceph_san_get_tls_ctx(void); #define CEPH_SAN_LOG(fmt, ...) \ ceph_san_log(__FILE__, __LINE__, fmt, ##__VA_ARGS__) +/* Global logger instance */ +extern struct ceph_san_logger g_logger; + #endif /* CEPH_SAN_LOGGER_H */ \ No newline at end of file diff --git a/net/ceph/Makefile b/net/ceph/Makefile index 1df96e9561fa7..c0766fd8b2cd2 100644 --- a/net/ceph/Makefile +++ b/net/ceph/Makefile @@ -10,7 +10,7 @@ libceph-y := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \ osd_client.o osdmap.o crush/crush.o crush/mapper.o crush/hash.o \ striper.o \ debugfs.o \ - ceph_san.o ceph_san_pagefrag.o ceph_san_batch.o \ + ceph_san_pagefrag.o ceph_san_batch.o ceph_san_logger.o \ auth.o auth_none.o \ crypto.o armor.o \ auth_x.o \ diff --git a/net/ceph/ceph_san.c b/net/ceph/ceph_san.c deleted file mode 100644 index 710ba1a69f5fc..0000000000000 --- a/net/ceph/ceph_san.c +++ /dev/null @@ -1,357 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -/* Use per-core TLS logger; no global list or lock needed */ -DEFINE_PER_CPU(struct ceph_san_percore_logger, ceph_san_percore); -EXPORT_SYMBOL(ceph_san_percore); - -DEFINE_PER_CPU(struct cephsan_pagefrag, ceph_san_pagefrag); - -/* Global list of all TLS contexts and its protection lock */ -LIST_HEAD(g_ceph_san_contexts); -DEFINE_SPINLOCK(g_ceph_san_contexts_lock); -EXPORT_SYMBOL(g_ceph_san_contexts); -EXPORT_SYMBOL(g_ceph_san_contexts_lock); - -/* Memory caches for log entries */ -struct kmem_cache *ceph_san_log_128_cache; -struct kmem_cache *ceph_san_log_256_cache; - -struct kmem_cache *ceph_san_tls_logger_cache; - -#define CEPH_SAN_SIG 0xDEADC0DE - -/* Release function for TLS storage */ -static void ceph_san_tls_release(void *ptr) -{ - struct tls_ceph_san_context *context = ptr; - if (!context) - return; - - if (context->sig != CEPH_SAN_SIG) { - pr_err("sig is wrong %p %llx != %llx", context, context->sig, CEPH_SAN_SIG); - return; - } - - /* Remove from global list with lock protection */ - spin_lock(&g_ceph_san_contexts_lock); - list_del(&context->list); - spin_unlock(&g_ceph_san_contexts_lock); - - /* Free all log entries */ - int head_idx = context->logger.head_idx & (CEPH_SAN_MAX_LOGS - 1); - int tail_idx = (head_idx + 1) & (CEPH_SAN_MAX_LOGS - 1); - - for (int i = tail_idx; (i & (CEPH_SAN_MAX_LOGS - 1)) != head_idx; i++) { - struct ceph_san_log_entry_tls *entry = &context->logger.logs[i & (CEPH_SAN_MAX_LOGS - 1)]; - if (entry->buf) { - if (entry->ts & 0x1) - kmem_cache_free(ceph_san_log_256_cache, entry->buf); - else - kmem_cache_free(ceph_san_log_128_cache, entry->buf); - entry->buf = NULL; - } - } - - kmem_cache_free(ceph_san_tls_logger_cache, context); -} - -static struct tls_ceph_san_context *get_cephsan_context(void) -{ - struct tls_ceph_san_context *context; - - context = current->tls.state; - if (context) - return context; - - context = kmem_cache_alloc(ceph_san_tls_logger_cache, GFP_KERNEL); - if (!context) { - pr_err("Failed to allocate TLS logger for PID %d\n", current->pid); - return NULL; - } - - context->logger.pid = current->pid; - memcpy(context->logger.comm, current->comm, TASK_COMM_LEN); - - /* Initialize list entry */ - INIT_LIST_HEAD(&context->list); - context->sig = CEPH_SAN_SIG; - - current->tls.state = context; - current->tls.release = ceph_san_tls_release; - - /* Add to global list with lock protection */ - spin_lock(&g_ceph_san_contexts_lock); - list_add(&context->list, &g_ceph_san_contexts); - spin_unlock(&g_ceph_san_contexts_lock); - - return context; -} - -void log_cephsan_tls(char *buf) -{ - /* Use the task's TLS storage */ - int len = strlen(buf); - struct tls_ceph_san_context *ctx; - struct ceph_san_tls_logger *logger; - char *new_buf; - - ctx = get_cephsan_context(); - if (!ctx) - return; - - logger = &ctx->logger; - - /* Log the message */ - int head_idx = logger->head_idx + 1 & (CEPH_SAN_MAX_LOGS - 1); - struct ceph_san_log_entry_tls *entry = &logger->logs[head_idx]; - - /* Only free and reallocate if sizes differ */ - if (!entry->buf || (entry->ts & 0x1) != (len > LOG_BUF_SMALL)) { - if (entry->buf) { - if (entry->ts & 0x1) - kmem_cache_free(ceph_san_log_256_cache, entry->buf); - else - kmem_cache_free(ceph_san_log_128_cache, entry->buf); - entry->buf = NULL; - } - - /* Allocate new buffer from appropriate cache */ - if (len <= LOG_BUF_SMALL) { - new_buf = kmem_cache_alloc(ceph_san_log_128_cache, GFP_KERNEL); - entry->ts = jiffies & ~0x1; - } else { - new_buf = kmem_cache_alloc(ceph_san_log_256_cache, GFP_KERNEL); - entry->ts = jiffies | 0x1; - } - } else { - /* Reuse existing buffer since size category hasn't changed */ - new_buf = entry->buf; - } - - if (!new_buf) - return; - - buf[len-1] = '\0'; - entry->buf = new_buf; - memcpy(entry->buf, buf, len); - - logger->head_idx = head_idx; -} - -static void log_cephsan_percore(char *buf) -{ - /* Use the per-core TLS logger */ - u64 buf_idx; - int len = strlen(buf); - struct ceph_san_percore_logger *pc = this_cpu_ptr(&ceph_san_percore); - struct cephsan_pagefrag *pf = this_cpu_ptr(&ceph_san_pagefrag); - - int head_idx = pc->head_idx + 1 & (CEPH_SAN_MAX_LOGS - 1); - int pre_len = pc->logs[head_idx].len; - - buf[len-1] = '\0'; - pc->logs[head_idx].pid = current->pid; - pc->logs[head_idx].ts = jiffies; - memcpy(pc->logs[head_idx].comm, current->comm, TASK_COMM_LEN); - - cephsan_pagefrag_free(pf, pre_len); - pc->logs[head_idx].len = 0; - - buf_idx = cephsan_pagefrag_alloc(pf, len); - if (buf_idx) { - pc->head_idx = head_idx; - pc->histogram.counters[(len >= 256) ? 31 : len >> 3]++; - pc->logs[head_idx].len = len; - pc->logs[head_idx].buf = cephsan_pagefrag_get_ptr(pf, buf_idx); - memcpy(pc->logs[head_idx].buf, buf, len); - } -} - -void log_cephsan(char *buf) -{ - log_cephsan_percore(buf); - log_cephsan_tls(buf); -} -EXPORT_SYMBOL(log_cephsan); - -/* Cleanup function to free all TLS logger objects. - * Call this at module exit to free allocated TLS loggers. - */ -void cephsan_cleanup(void) -{ - int cpu; - struct ceph_san_percore_logger *pc; - - for_each_possible_cpu(cpu) { - pc = per_cpu_ptr(&ceph_san_percore, cpu); - if (pc->pages) { - free_pages((unsigned long)pc->pages, get_order(CEPH_SAN_MAX_LOGS * sizeof(struct ceph_san_log_entry))); - pc->pages = NULL; - } - } -#if 0 - /* Let the TLS contexts cleanup lazily */ - if (ceph_san_tls_logger_cache) { - kmem_cache_destroy(ceph_san_tls_logger_cache); - ceph_san_tls_logger_cache = NULL; - } - - if (ceph_san_log_128_cache) { - kmem_cache_destroy(ceph_san_log_128_cache); - ceph_san_log_128_cache = NULL; - } - - if (ceph_san_log_256_cache) { - kmem_cache_destroy(ceph_san_log_256_cache); - ceph_san_log_256_cache = NULL; - } -#endif -} -EXPORT_SYMBOL(cephsan_cleanup); - -/* Initialize the Ceph SAN logging infrastructure. - * Call this at module init to set up the global list and lock. - */ -int cephsan_init(void) -{ - int cpu; - struct ceph_san_percore_logger *pc; - struct cephsan_pagefrag *pf; - - /* Initialize the global list */ - INIT_LIST_HEAD(&g_ceph_san_contexts); - - /* Create memory caches for log entries */ - ceph_san_log_128_cache = kmem_cache_create("ceph_san_log_128", - LOG_BUF_SMALL, - 0, SLAB_HWCACHE_ALIGN, - NULL); - if (!ceph_san_log_128_cache) - goto cleanup_128_cache; - - ceph_san_log_256_cache = kmem_cache_create("ceph_san_log_256", - LOG_BUF_SIZE, - 0, SLAB_HWCACHE_ALIGN, - NULL); - if (!ceph_san_log_256_cache) - goto cleanup_256_cache; - - ceph_san_tls_logger_cache = kmem_cache_create("ceph_san_tls_logger", - sizeof(struct tls_ceph_san_context), - 0, SLAB_HWCACHE_ALIGN, - NULL); - if (!ceph_san_tls_logger_cache) - goto cleanup_logger_cache; - - for_each_possible_cpu(cpu) { - pc = per_cpu_ptr(&ceph_san_percore, cpu); - pc->pages = alloc_pages(GFP_KERNEL, get_order(CEPH_SAN_MAX_LOGS * sizeof(struct ceph_san_log_entry))); - if (!pc->pages) { - pr_err("Failed to allocate TLS logs for CPU %d\n", cpu); - goto cleanup; - } - pc->logs = (struct ceph_san_log_entry *)page_address(pc->pages); - } - - for_each_possible_cpu(cpu) { - pf = per_cpu_ptr(&ceph_san_pagefrag, cpu); - cephsan_pagefrag_init(pf); - } - return 0; - -cleanup: - cephsan_cleanup(); - return -ENOMEM; - -cleanup_logger_cache: - kmem_cache_destroy(ceph_san_log_256_cache); - ceph_san_log_256_cache = NULL; - -cleanup_256_cache: - kmem_cache_destroy(ceph_san_log_128_cache); - ceph_san_log_128_cache = NULL; - -cleanup_128_cache: - return -ENOMEM; -} -EXPORT_SYMBOL(cephsan_init); - -/** - * cephsan_dump_all_contexts - Dump logs from all TLS contexts to a buffer - * @buf: Buffer to write logs to - * @size: Size of the buffer - * - * This function iterates through all TLS contexts in the global list and - * dumps their logs to the provided buffer. It's useful for debugging and - * crash analysis. - * - * Return: Number of bytes written to the buffer - */ -int cephsan_dump_all_contexts(char *buf, size_t size) -{ - struct tls_ceph_san_context *ctx; - struct ceph_san_tls_logger *tls; - struct ceph_san_log_entry_tls *entry; - unsigned long flags; - int len = 0; - int count = 0; - - if (!buf || size == 0) - return 0; - - len += snprintf(buf + len, size - len, - "=== Ceph SAN TLS logs from all contexts ===\n"); - - spin_lock_irqsave(&g_ceph_san_contexts_lock, flags); - - list_for_each_entry(ctx, &g_ceph_san_contexts, list) { - tls = &ctx->logger; - count++; - - if (len >= size - 1) - break; - - len += snprintf(buf + len, size - len, - "\n=== Context %d (PID %d, comm %s) ===\n", - count, tls->pid, tls->comm); - int head_idx = tls->head_idx & (CEPH_SAN_MAX_LOGS - 1); - int tail_idx = (head_idx + 1) & (CEPH_SAN_MAX_LOGS - 1); - - for (int i = tail_idx; (i & (CEPH_SAN_MAX_LOGS - 1)) != head_idx; i++) { - struct timespec64 ts; - entry = &tls->logs[i & (CEPH_SAN_MAX_LOGS - 1)]; - - if (entry->ts == 0 || !entry->buf) - continue; - - if (len >= size - 1) - break; - - jiffies_to_timespec64(entry->ts, &ts); - - len += snprintf(buf + len, size - len, - "[%lld.%09ld] : %s\n", - (long long)ts.tv_sec, - ts.tv_nsec, - entry->buf ? entry->buf : "(null)"); - } - } - - spin_unlock_irqrestore(&g_ceph_san_contexts_lock, flags); - - if (count == 0 && len < size - 1) { - len += snprintf(buf + len, size - len, "No TLS contexts found.\n"); - } else if (len < size - 1) { - len += snprintf(buf + len, size - len, "\nTotal contexts: %d\n", count); - } - - return len; -} -EXPORT_SYMBOL(cephsan_dump_all_contexts); diff --git a/net/ceph/ceph_san_logger.c b/net/ceph/ceph_san_logger.c index 9b3a8ebc57fc0..4e4461fe655d1 100644 --- a/net/ceph/ceph_san_logger.c +++ b/net/ceph/ceph_san_logger.c @@ -9,7 +9,8 @@ #define CEPH_SAN_LOG_BATCH_MAX_FULL 128 /* Global logger instance */ -static struct ceph_san_logger g_logger; +struct ceph_san_logger g_logger; +EXPORT_SYMBOL(g_logger); static void *alloc_tls_ctx(void) { -- 2.39.5