#include <linux/ktime.h>
#include <linux/ceph/libceph.h>
-#include <linux/ceph/ceph_san.h>
+#include <linux/ceph/ceph_san_logger.h>
#include <linux/ceph/mon_client.h>
#include <linux/ceph/auth.h>
#include <linux/ceph/debugfs.h>
#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;
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;
}
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);
/*
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);
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,
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);
-// SPDX-License-Identifier: GPL-2.0-only
+
#include "linux/mm_types.h"
#include <linux/ceph/ceph_debug.h>
-#include <linux/ceph/ceph_san.h>
+#include <linux/ceph/ceph_san_logger.h>
#include <linux/backing-dev.h>
#include <linux/ctype.h>
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:
static void __exit exit_ceph(void)
{
dout("exit_ceph\n");
- cephsan_cleanup();
+ ceph_san_logger_cleanup();
unregister_filesystem(&ceph_fs_type);
destroy_caches();
}
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
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/string.h>
-#include <linux/ceph/ceph_san.h>
+#include <linux/ceph/ceph_san_logger.h>
#ifdef CONFIG_CEPH_LIB_PRETTYDEBUG
/*
* 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
+++ /dev/null
-#ifndef CEPHSAN_H
-#define CEPHSAN_H
-
-#include <linux/types.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#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 */
#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
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 \
+++ /dev/null
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <linux/jiffies.h>
-#include <linux/ceph/ceph_san.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-
-/* 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);
#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)
{