#include <linux/blog/blog.h>
/* Ceph's BLOG module context */
-struct blog_module_context *ceph_blog_ctx = NULL;
+struct blog_module_context *ceph_blog_ctx;
EXPORT_SYMBOL(ceph_blog_ctx);
/* Ceph's logger - direct access to the logger from module context */
-struct blog_logger *ceph_logger = NULL;
+struct blog_logger *ceph_logger;
EXPORT_SYMBOL(ceph_logger);
/* Global client mapping state */
memset(ceph_blog_state.client_map, 0, sizeof(ceph_blog_state.client_map));
ceph_blog_state.next_client_id = 1;
ceph_blog_state.initialized = true;
-
+
pr_info("ceph: BLOG module context and client mapping initialized\n");
return 0;
}
ceph_blog_state.next_client_id = 1;
ceph_blog_state.initialized = false;
spin_unlock(&ceph_blog_state.lock);
-
+
/* Clean up module-specific BLOG context */
if (ceph_blog_ctx) {
blog_module_cleanup(ceph_blog_ctx);
ceph_blog_ctx = NULL;
ceph_logger = NULL;
}
-
+
pr_info("ceph: BLOG module context and client mapping cleaned up\n");
}
EXPORT_SYMBOL(ceph_blog_cleanup);
}
/* Use %pU to print fsid like the rest of Ceph does */
pr_info("ceph: allocating new BLOG client ID %u for fsid=%pU global_id=%llu\n",
- found_id, fsid, global_id);
-
+ found_id, fsid, global_id);
+
entry = &ceph_blog_state.client_map[found_id];
memcpy(entry->fsid, fsid, sizeof(entry->fsid));
entry->global_id = global_id;
/* Use %pU to format fsid, matching doutc and other Ceph client logging */
return snprintf(buf, size, "[%pU %llu] ",
- info->fsid, info->global_id);
+ info->fsid, info->global_id);
}
EXPORT_SYMBOL(ceph_blog_client_des_callback);
{
if (!client)
return 0;
-
- /*
+
+ /*
* No caching - ceph_blog_check_client_id has internal fast path
* that checks the provided ID first before scanning
*/
- return ceph_blog_check_client_id(0,
- client->fsid.fsid,
- client->monc.auth->global_id);
+ return ceph_blog_check_client_id(0,
+ client->fsid.fsid,
+ client->monc.auth->global_id);
}
EXPORT_SYMBOL(ceph_blog_get_client_id);
int entry_count = 0;
int ctx_count = 0;
- seq_printf(s, "Ceph BLOG Entries\n");
- seq_printf(s, "=================\n\n");
+ seq_puts(s, "Ceph BLOG Entries\n");
+ seq_puts(s, "=================\n\n");
/* Access the Ceph module's logger contexts */
if (!ceph_blog_ctx || !ceph_blog_ctx->logger) {
- seq_printf(s, "Ceph BLOG context not initialized\n");
+ seq_puts(s, "Ceph BLOG context not initialized\n");
return 0;
}
list_for_each_entry(ctx, &ceph_blog_ctx->logger->contexts, list) {
ctx_count++;
seq_printf(s, "Context %d (ID: %llu, PID: %d, Comm: %s)\n",
- ctx_count, ctx->id, ctx->pid, ctx->comm);
+ ctx_count, ctx->id, ctx->pid, ctx->comm);
seq_printf(s, " Base jiffies: %lu, Refcount: %d\n",
- ctx->base_jiffies, atomic_read(&ctx->refcount));
+ ctx->base_jiffies, atomic_read(&ctx->refcount));
/* Initialize iterator for this context's pagefrag */
blog_log_iter_init(&iter, &ctx->pf);
/* Use blog_des_entry with Ceph's client callback */
ret = blog_des_entry(ceph_blog_ctx->logger, entry, output_buf,
- sizeof(output_buf), ceph_blog_client_des_callback);
+ sizeof(output_buf), ceph_blog_client_des_callback);
if (ret < 0) {
seq_printf(s, " Entry %d: [Error deserializing: %d]\n",
- entry_count, ret);
+ entry_count, ret);
} else {
char time_buf[64];
u64 entry_jiffies = ctx->base_jiffies + entry->ts_delta;
seq_printf(s, " %s\n", output_buf);
}
}
- seq_printf(s, "\n");
+ seq_puts(s, "\n");
}
spin_unlock(&ceph_blog_ctx->logger->lock);
*/
static int blog_stats_show(struct seq_file *s, void *p)
{
- seq_printf(s, "Ceph BLOG Statistics\n");
- seq_printf(s, "====================\n\n");
+ seq_puts(s, "Ceph BLOG Statistics\n");
+ seq_puts(s, "====================\n\n");
if (!ceph_blog_ctx || !ceph_blog_ctx->logger) {
- seq_printf(s, "Ceph BLOG context not initialized\n");
+ seq_puts(s, "Ceph BLOG context not initialized\n");
return 0;
}
- seq_printf(s, "Ceph Module Logger State:\n");
+ seq_puts(s, "Ceph Module Logger State:\n");
seq_printf(s, " Total contexts allocated: %lu\n",
- ceph_blog_ctx->logger->total_contexts_allocated);
+ ceph_blog_ctx->logger->total_contexts_allocated);
seq_printf(s, " Next context ID: %llu\n", ceph_blog_ctx->logger->next_ctx_id);
seq_printf(s, " Next source ID: %u\n",
- atomic_read(&ceph_blog_ctx->logger->next_source_id));
+ atomic_read(&ceph_blog_ctx->logger->next_source_id));
- seq_printf(s, "\nAllocation Batch:\n");
+ seq_puts(s, "\nAllocation Batch:\n");
seq_printf(s, " Full magazines: %u\n", ceph_blog_ctx->logger->alloc_batch.nr_full);
seq_printf(s, " Empty magazines: %u\n", ceph_blog_ctx->logger->alloc_batch.nr_empty);
- seq_printf(s, "\nLog Batch:\n");
+ seq_puts(s, "\nLog Batch:\n");
seq_printf(s, " Full magazines: %u\n", ceph_blog_ctx->logger->log_batch.nr_full);
seq_printf(s, " Empty magazines: %u\n", ceph_blog_ctx->logger->log_batch.nr_empty);
u32 id;
int count = 0;
- seq_printf(s, "Ceph BLOG Source Locations\n");
- seq_printf(s, "===========================\n\n");
+ seq_puts(s, "Ceph BLOG Source Locations\n");
+ seq_puts(s, "===========================\n\n");
if (!ceph_blog_ctx || !ceph_blog_ctx->logger) {
- seq_printf(s, "Ceph BLOG context not initialized\n");
+ seq_puts(s, "Ceph BLOG context not initialized\n");
return 0;
}
atomic_read(&source->task_usage),
atomic_read(&source->task_bytes));
#endif
- seq_printf(s, "\n");
+ seq_puts(s, "\n");
}
seq_printf(s, "Total registered sources: %d\n", count);
int count = 0;
const struct ceph_blog_client_info *info;
- seq_printf(s, "Ceph BLOG Registered Clients\n");
- seq_printf(s, "=============================\n\n");
+ seq_puts(s, "Ceph BLOG Registered Clients\n");
+ seq_puts(s, "=============================\n\n");
for (id = 1; id < CEPH_BLOG_MAX_CLIENTS; id++) {
info = ceph_blog_get_client_info(id);
seq_printf(s, "Client ID %u:\n", id);
seq_printf(s, " FSID: %pU\n", info->fsid);
seq_printf(s, " Global ID: %llu\n", info->global_id);
- seq_printf(s, "\n");
+ seq_puts(s, "\n");
}
seq_printf(s, "Total registered clients: %d\n", count);
// SPDX-License-Identifier: GPL-2.0
/*
* Example integration code showing how Ceph uses BLOG
- *
+ *
* This demonstrates the transition from ceph_san to BLOG with preserved
* client ID mapping functionality.
*/
{
int value = 42;
const char *status = "active";
-
+
/* Using BLOG for simple logging */
CEPH_BLOG_LOG("Simple log: value=%d status=%s\n", value, status);
-
+
/* (SAN legacy macro examples removed) */
-
+
/* Traditional dout remains unchanged */
dout("Traditional dout: value=%d\n", value);
}
struct ceph_osd_request *req;
u64 offset = 0x1000;
u64 length = 0x4000;
-
+
if (!client)
return;
-
+
/* Using BLOG with client context */
- CEPH_BLOG_LOG_CLIENT(client, "OSD request: offset=%llu length=%llu\n",
+ CEPH_BLOG_LOG_CLIENT(client, "OSD request: offset=%llu length=%llu\n",
offset, length);
-
+
/* (SAN legacy macro examples removed) */
-
+
/* Traditional doutc - shows [fsid global_id] in text logs */
doutc(client, "Traditional doutc: processing request\n");
-
+
/* boutc uses BLOG internally with client context */
boutc(client, "Binary log with client: offset=%llu length=%llu\n",
offset, length);
/*
* Example 3: Demonstrating client ID mapping preservation
- *
+ *
* The client_id mapping is now handled by Ceph, not BLOG.
* This preserves the exact functionality of ceph_san_check_client_id.
*/
{
u32 client_id;
const struct ceph_blog_client_info *info;
-
+
if (!client)
return;
-
+
/* Get or allocate client ID for this Ceph client */
client_id = ceph_blog_get_client_id(client);
-
- CEPH_BLOG_LOG_CLIENT(client,
+
+ CEPH_BLOG_LOG_CLIENT(client,
"Client registered with ID %u\n", client_id);
-
+
/* The mapping is preserved in Ceph's blog_client.c */
info = ceph_blog_get_client_info(client_id);
if (info) {
/*
* Example 4: Debugfs integration
- *
+ *
* The debugfs interface uses BLOG's deserialization with Ceph's
* client callback to reconstruct the full log entries.
*/
{
/*
* Debugfs files created by ceph_blog_debugfs_init():
- *
+ *
* /sys/kernel/debug/ceph/blog/entries
* - Shows all BLOG entries with client info deserialized
* - Uses ceph_blog_client_des_callback to format [fsid gid]
- *
+ *
* /sys/kernel/debug/ceph/blog/stats
* - Shows BLOG statistics
- *
+ *
* /sys/kernel/debug/ceph/blog/sources
* - Shows all registered source locations
- *
+ *
* /sys/kernel/debug/ceph/blog/clients
* - Shows all registered Ceph clients with their mappings
- *
+ *
* /sys/kernel/debug/ceph/blog/clear
* - Write-only file to clear all BLOG entries
*/
static int __init ceph_blog_example_init(void)
{
int ret;
-
+
/* Initialize Ceph's BLOG integration */
ret = ceph_blog_init();
if (ret) {
pr_err("Failed to initialize Ceph BLOG integration: %d\n", ret);
return ret;
}
-
+
pr_info("Ceph BLOG integration example loaded\n");
-
+
/* Note: In real usage, blog_init() would be called by BLOG module
* and ceph_blog_init() would be called by Ceph FS module init
*/
-
+
return 0;
}
{
/* Clean up Ceph's BLOG integration */
ceph_blog_cleanup();
-
+
pr_info("Ceph BLOG integration example unloaded\n");
}
#endif
-#if defined(CONFIG_BLOG) || defined(CONFIG_BLOG_MODULE)
+#ifdef CONFIG_BLOG
#define bout_dbg(fmt, ...) \
do { \
CEPH_BLOG_LOG(fmt, ##__VA_ARGS__); \
/* BLOG support - max modules defined here for use by other headers */
#define BLOG_MAX_MODULES 8
-#if defined(CONFIG_BLOG) || defined(CONFIG_BLOG_MODULE)
+#ifdef CONFIG_BLOG
struct blog_tls_ctx *blog_contexts[BLOG_MAX_MODULES];
#endif
#include <linux/sched/cputime.h>
#include <linux/sched/ext.h>
#include <linux/seq_file.h>
-#if defined(CONFIG_BLOG) || defined(CONFIG_BLOG_MODULE)
+#ifdef CONFIG_BLOG
#include <linux/blog/blog.h>
#endif
#include <linux/rtmutex.h>
static inline void free_task_struct(struct task_struct *tsk)
{
-#if defined(CONFIG_BLOG) || defined(CONFIG_BLOG_MODULE)
+#ifdef CONFIG_BLOG
/* Clean up any BLOG contexts */
{
struct blog_tls_ctx *contexts[BLOG_MAX_MODULES];
if (!p)
goto fork_out;
-#if defined(CONFIG_BLOG) || defined(CONFIG_BLOG_MODULE)
+#ifdef CONFIG_BLOG
/* Initialize BLOG contexts */
{
int i;
+
for (i = 0; i < BLOG_MAX_MODULES; i++)
p->blog_contexts[i] = NULL;
}
{
if (!logger)
return;
-
+
spin_lock(&logger->lock);
list_add(&ctx->list, &logger->contexts);
logger->total_contexts_allocated++;
static void *alloc_tls_ctx(struct blog_logger *logger)
{
struct blog_tls_ctx *ctx;
-
+
if (!logger)
return NULL;
-
+
ctx = kmem_cache_alloc(logger->alloc_batch.magazine_cache,
GFP_KERNEL);
if (!ctx) {
ctx->task = NULL;
pr_debug("blog: releasing TLS context for pid %d [%s]\n", ctx->pid,
ctx->comm);
-
+
if (ctx->logger) {
blog_batch_put(&ctx->logger->log_batch, ctx);
/**
* blog_des_entry - Deserialize entry with callback
*/
-int blog_des_entry(struct blog_logger *logger, struct blog_log_entry *entry,
+int blog_des_entry(struct blog_logger *logger, struct blog_log_entry *entry,
char *output, size_t out_size, blog_client_des_fn client_cb)
{
int len = 0;
// SPDX-License-Identifier: GPL-2.0
/*
* Binary Logging Deserialization
- *
+ *
* Migrated from ceph_san_des.c with all algorithms preserved
*/
/* Parse length modifiers (l, ll, h, hh, z) */
is_long = 0;
is_long_long = 0;
-
+
if (*fmt_ptr == 'l') {
fmt_ptr++;
is_long = 1;
buf_ptr += sizeof(int);
ret = snprintf(out_ptr, remaining, "%d", val);
}
-
+
if (ret > 0) {
if (ret > remaining)
ret = remaining;
buf_ptr += sizeof(unsigned int);
ret = snprintf(out_ptr, remaining, "%u", val);
}
-
+
if (ret > 0) {
if (ret > remaining)
ret = remaining;
buf_ptr += sizeof(unsigned int);
ret = snprintf(out_ptr, remaining, hex_fmt, val);
}
-
+
if (ret > 0) {
if (ret > remaining)
ret = remaining;
case 'p': { /* Pointer */
void *ptr;
-
+
/* Check buffer bounds before reading */
if (buf_ptr + sizeof(void *) > buf_end) {
pr_err("blog_des_reconstruct (%zu): buffer overrun reading pointer\n", arg_count);
case 'c': { /* Character */
char val;
-
+
/* Check buffer bounds before reading */
if (buf_ptr + sizeof(int) > buf_end) { /* chars are promoted to int */
pr_err("blog_des_reconstruct (%zu): buffer overrun reading char\n", arg_count);
}
default:
- pr_err("blog_des_reconstruct (%zu): unsupported format specifier '%%%c'\n",
+ pr_err("blog_des_reconstruct (%zu): unsupported format specifier '%%%c'\n",
arg_count, *fmt_ptr);
return -EINVAL;
}
*
* Return: Length of formatted string, or negative error code on failure
*/
-int blog_log_reconstruct(struct blog_logger *logger, const struct blog_log_entry *entry,
+int blog_log_reconstruct(struct blog_logger *logger, const struct blog_log_entry *entry,
char *output, size_t output_size)
{
struct blog_source_info *source;
-
+
if (!entry || !output || !logger)
return -EINVAL;
-
+
/* Get source info */
source = blog_get_source_info(logger, entry->source_id);
if (!source) {
return snprintf(output, output_size, "[unknown source %u]", entry->source_id);
}
-
+
/* Reconstruct using the format string from source */
return blog_des_reconstruct(source->fmt, entry->buffer, 0, entry->len,
output, output_size);
pr_err("blog: module name is empty\n");
return NULL;
}
-
+
if (name_len >= 32) { /* sizeof(blog_module_context.name) */
pr_err("blog: module name too long: '%s' (max 31 chars)\n",
module_name);
spin_lock_irqsave(&blog_registry.lock, flags);
/* Find first free slot */
- slot = find_first_zero_bit((unsigned long *)&blog_registry.allocated_bitmap,
+ slot = find_first_zero_bit((unsigned long *)&blog_registry.allocated_bitmap,
BLOG_MAX_MODULES);
if (slot >= BLOG_MAX_MODULES) {
spin_unlock_irqrestore(&blog_registry.lock, flags);
kfree(ctx);
- pr_err("blog: no free slots available (max %d modules)\n",
+ pr_err("blog: no free slots available (max %d modules)\n",
BLOG_MAX_MODULES);
return NULL;
}
*
* Return: Buffer to write log data to, or NULL on failure
*/
-void* blog_log_ctx(struct blog_module_context *ctx, u32 source_id,
+void* blog_log_ctx(struct blog_module_context *ctx, u32 source_id,
u8 client_id, size_t needed_size)
{
struct blog_tls_ctx *tls_ctx;
// SPDX-License-Identifier: GPL-2.0
/*
* Binary Logging Page Fragment Management
- *
+ *
* Migrated from ceph_san_pagefrag.c with all algorithms preserved
*/
int blog_pagefrag_alloc(struct blog_pagefrag *pf, unsigned int n)
{
u64 offset;
- if (pf->head + n > BLOG_PAGEFRAG_SIZE) {
+
+ if (pf->head + n > BLOG_PAGEFRAG_SIZE)
return -ENOMEM; /* No space left */
- }
offset = pf->head;
pf->head += n;
pf->alloc_count++;
{
void *rc = (void *)(pf->buffer + val);
if (unlikely(pf->pages && pf->buffer != page_address(pf->pages))) {
- pr_err("blog_pagefrag_get_ptr: invalid buffer pointer %llx @ %s\n",
+ pr_err("blog_pagefrag_get_ptr: invalid buffer pointer %llx @ %s\n",
(unsigned long long)pf->buffer, current->comm);
BUG();
}