struct ceph_san_tls_ctx *ctx;
struct ceph_san_log_iter iter;
struct ceph_san_log_entry *entry;
+ const struct ceph_san_source_info *source;
/* Lock the logger to safely traverse the contexts list */
spin_lock(&g_logger.lock);
list_for_each_entry(ctx, &g_logger.contexts, list) {
-
/* Initialize iterator for this context's pagefrag */
ceph_san_log_iter_init(&iter, &ctx->pf);
int pid = ctx->pid;
char datetime_str[32];
jiffies_to_formatted_time(entry->ts, datetime_str, sizeof(datetime_str));
- seq_printf(s, "[%d][%s][%s]:%s:%s:%u: %.*s",
- pid,
- comm,
- datetime_str,
- entry->file,
- entry->func,
- entry->line,
- entry->len,
+ /* Get source information for this ID */
+ source = ceph_san_get_source_info(entry->source_id);
+ if (!source) {
+ seq_printf(s, "[%d][%s][%s]:[Unknown Source ID %u]: %s\n",
+ pid, comm, datetime_str, entry->source_id, entry->buffer);
+ continue;
+ }
+
+ seq_printf(s, "[%d][%s][%s]:%s:%s:%u: %s\n",
+ pid, comm, datetime_str,
+ source->file, source->func, source->line,
entry->buffer);
}
/* Maximum length of a log entry buffer */
#define CEPH_SAN_LOG_MAX_LEN 256
#define CEPH_SAN_LOG_ENTRY_POISON 0xDEADBEEF
+#define CEPH_SAN_MAX_SOURCE_IDS 4096
+
+/* Source information mapping structure */
+struct ceph_san_source_info {
+ const char *file;
+ const char *func;
+ unsigned int line;
+};
+
/* Log entry structure */
struct ceph_san_log_entry {
u64 debug_poison; /* Debug poison value */
u64 ts; /* Timestamp (jiffies) */
- unsigned int line; /* Line number */
+ u32 source_id; /* ID for source file/function/line */
unsigned int len; /* Length of the message */
- const char *file; /* Source file */
- const char *func; /* Source function */
- char *buffer; /* Flexible array for inline buffer */
+ char *buffer; /* Flexible array for inline buffer */
};
/* TLS context structure */
spinlock_t lock; /* Protects contexts list */
struct ceph_san_batch alloc_batch; /* Batch for allocating new entries */
struct ceph_san_batch log_batch; /* Batch for storing log entries */
+ struct ceph_san_source_info source_map[CEPH_SAN_MAX_SOURCE_IDS]; /* Source info mapping */
+ atomic_t next_source_id; /* Next source ID to assign */
};
/* Iterator for log entries in a single pagefrag */
/* Clean up the logging system */
void ceph_san_logger_cleanup(void);
+/* Get or create source ID */
+u32 ceph_san_get_source_id(const char *file, const char *func, unsigned int line);
+
+/* Get source information for ID */
+const struct ceph_san_source_info *ceph_san_get_source_info(u32 id);
+
/* Log a message */
-void ceph_san_log(const char *file, const char *func, unsigned int line, const char *fmt, ...);
+void ceph_san_log(u32 source_id, const char *fmt, ...);
/* Get current TLS context, creating if necessary */
struct ceph_san_tls_ctx *ceph_san_get_tls_ctx(void);
/* Helper macro for logging */
#define CEPH_SAN_LOG(fmt, ...) \
- ceph_san_log(kbasename(__FILE__), __func__, __LINE__, fmt, ##__VA_ARGS__)
+ do { \
+ static u32 __source_id = 0; \
+ if (__source_id == 0) { \
+ __source_id = ceph_san_get_source_id(kbasename(__FILE__), __func__, __LINE__); \
+ } \
+ ceph_san_log(__source_id, fmt, ##__VA_ARGS__); \
+ } while (0)
/* Global logger instance */
extern struct ceph_san_logger g_logger;
#ifndef CEPH_SAN_SER_H
#define CEPH_SAN_SER_H
-#include <stddef.h>
-#include <stdarg.h>
-
#define ___ceph_san_concat(__a, __b) __a ## __b
#define ___ceph_san_apply(__fn, __n) ___ceph_san_concat(__fn, __n)
EXPORT_SYMBOL(ceph_san_get_tls_ctx);
/**
- * ceph_san_log - Log a message
+ * ceph_san_get_source_id - Get or create a source ID for the given location
* @file: Source file name
+ * @func: Function name
* @line: Line number
+ *
+ * Returns a unique ID for this source location
+ */
+u32 ceph_san_get_source_id(const char *file, const char *func, unsigned int line)
+{
+ u32 id = atomic_inc_return(&g_logger.next_source_id);
+
+ if (id >= CEPH_SAN_MAX_SOURCE_IDS) {
+ /* If we run out of IDs, just use the first one */
+ pr_warn("ceph_san_logger: source ID overflow, reusing ID 1\n");
+ id = 1;
+ }
+
+ /* Store the source information in the global map */
+ g_logger.source_map[id].file = file;
+ g_logger.source_map[id].func = func;
+ g_logger.source_map[id].line = line;
+
+ return id;
+}
+EXPORT_SYMBOL(ceph_san_get_source_id);
+
+/**
+ * ceph_san_get_source_info - Get source info for a given ID
+ * @id: Source ID
+ *
+ * Returns the source information for this ID
+ */
+const struct ceph_san_source_info *ceph_san_get_source_info(u32 id)
+{
+ if (id == 0 || id >= CEPH_SAN_MAX_SOURCE_IDS)
+ return NULL;
+ return &g_logger.source_map[id];
+}
+EXPORT_SYMBOL(ceph_san_get_source_info);
+
+/**
+ * ceph_san_log - Log a message
+ * @source_id: Source ID for this location
* @fmt: Format string
*
* Logs a message to the current TLS context's log buffer
*/
-void ceph_san_log(const char *file, const char *func, unsigned int line, const char *fmt, ...)
+void ceph_san_log(u32 source_id, const char *fmt, ...)
{
/* Format the message into local buffer first */
char buf[256];
/* Fill in entry details */
entry->debug_poison = CEPH_SAN_LOG_ENTRY_POISON;
entry->ts = jiffies;
- entry->line = line;
- entry->file = file;
- entry->func = func;
+ entry->source_id = source_id;
if (unlikely(cephsan_pagefrag_is_wraparound(alloc))) {
entry->buffer = cephsan_pagefrag_get_ptr(&ctx->pf, 0);
} else {
/* Initialize global state */
INIT_LIST_HEAD(&g_logger.contexts);
spin_lock_init(&g_logger.lock);
+ atomic_set(&g_logger.next_source_id, 0);
/* Initialize allocation batch */
ret = ceph_san_batch_init(&g_logger.alloc_batch);
return entry;
}
-EXPORT_SYMBOL(ceph_san_log_iter_next);
\ No newline at end of file
+EXPORT_SYMBOL(ceph_san_log_iter_next);