lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <b6d9c32721a5b836a84945232d98aab1d15e3638.camel@ibm.com>
Date: Mon, 3 Nov 2025 22:37:15 +0000
From: Viacheslav Dubeyko <Slava.Dubeyko@....com>
To: "linux-mm@...ck.org" <linux-mm@...ck.org>,
        Alex Markuze
	<amarkuze@...hat.com>,
        "ceph-devel@...r.kernel.org"
	<ceph-devel@...r.kernel.org>,
        "linux-kernel@...r.kernel.org"
	<linux-kernel@...r.kernel.org>
CC: "dietmar.eggemann@....com" <dietmar.eggemann@....com>,
        "rppt@...nel.org"
	<rppt@...nel.org>,
        "lorenzo.stoakes@...cle.com" <lorenzo.stoakes@...cle.com>,
        Xiubo Li <xiubli@...hat.com>,
        "idryomov@...il.com" <idryomov@...il.com>,
        "david@...hat.com" <david@...hat.com>,
        "mgorman@...e.de" <mgorman@...e.de>, "vbabka@...e.cz" <vbabka@...e.cz>,
        "vincent.guittot@...aro.org"
	<vincent.guittot@...aro.org>,
        "akpm@...ux-foundation.org"
	<akpm@...ux-foundation.org>,
        "Liam.Howlett@...cle.com"
	<Liam.Howlett@...cle.com>,
        Ingo Molnar <mingo@...hat.com>,
        "rostedt@...dmis.org" <rostedt@...dmis.org>,
        "surenb@...gle.com"
	<surenb@...gle.com>,
        Valentin Schneider <vschneid@...hat.com>,
        "kees@...nel.org" <kees@...nel.org>,
        "peterz@...radead.org"
	<peterz@...radead.org>,
        "mhocko@...e.com" <mhocko@...e.com>,
        "bsegall@...gle.com" <bsegall@...gle.com>,
        "juri.lelli@...hat.com"
	<juri.lelli@...hat.com>
Subject: Re:  [RFC PATCH 3/5] ceph: Add BLOG scaffolding

On Fri, 2025-10-24 at 08:42 +0000, Alex Markuze wrote:
> Introduce the Ceph BLOG integration layer that enables the filesystem to
> register binary loggers and route log events through module-specific TLS
> contexts. This commit establishes the infrastructure for high-performance
> binary logging in the Ceph client without modifying existing logging calls.
> 

Frankly speaking, the kernel subsystems' integration logic requires a lot of
code. I expected that it will be much easier to integrate the BLOG
infrastructure into a particular kernel subsystem. Is it possible to move
majority of the functionality into the generalized BLOG infrastructure? I
believe that everyone will love really simple integration logic.

Thanks,
Slava. 

> **Key Components:**
> 
> **ceph_blog.h - BLOG-aware macros and interfaces:**
> - bout/boutc: Drop-in replacements for dout/doutc with identical semantics
> - CEPH_BLOG_LOG_CTX/CEPH_BLOG_LOG: Low-level logging primitives
> - Automatic fallback to traditional dout when CONFIG_BLOG is disabled
> - Type-safe parameter serialization using BLOG framework
> 
> **blog_client.c - Module registration and context management:**
> - ceph_blog_init(): Register Ceph-specific BLOG logger on module load
> - ceph_blog_exit(): Cleanup and unregister logger on module unload
> - ceph_get_tls_ctx(): Acquire per-task BLOG context for current thread
> - Client-ID to logger mapping for multi-client scenarios
> - Exported symbols for context acquisition from Ceph code paths
> 
> **Makefile integration:**
> - Conditionally build blog_client.o when CONFIG_CEPH_FS && CONFIG_BLOG
> - Clean integration with existing Ceph build system
> 
> **Design rationale:**
> The bout/boutc macros maintain the same call-site syntax as dout/doutc,
> allowing gradual migration and easy A/B testing. Log levels and subsystem
> filtering remain unchanged. The TLS context is acquired lazily on first use
> per task and recycled automatically on task exit via the BLOG lifecycle
> hooks wired in earlier commits.
> 
> No existing Ceph logging is modified in this commit. The infrastructure is
> in place but inactive until logging call sites are converted to bout/boutc
> in subsequent commits.
> 
> Signed-off-by: Alex Markuze <amarkuze@...hat.com>
> ---
>  fs/ceph/Makefile               |   2 +
>  fs/ceph/blog_client.c          | 244 +++++++++++++++++++++++++++++++++
>  include/linux/ceph/ceph_blog.h | 124 +++++++++++++++++
>  3 files changed, 370 insertions(+)
>  create mode 100644 fs/ceph/blog_client.c
>  create mode 100644 include/linux/ceph/ceph_blog.h
> 
> diff --git a/fs/ceph/Makefile b/fs/ceph/Makefile
> index 1f77ca04c426..ccb542870ab3 100644
> --- a/fs/ceph/Makefile
> +++ b/fs/ceph/Makefile
> @@ -10,6 +10,8 @@ ceph-y := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \
>  	mds_client.o mdsmap.o strings.o ceph_frag.o \
>  	debugfs.o util.o metric.o
>  
> +ceph-$(CONFIG_BLOG) += blog_client.o blog_debugfs.o
> +
>  ceph-$(CONFIG_CEPH_FSCACHE) += cache.o
>  ceph-$(CONFIG_CEPH_FS_POSIX_ACL) += acl.o
>  ceph-$(CONFIG_FS_ENCRYPTION) += crypto.o
> diff --git a/fs/ceph/blog_client.c b/fs/ceph/blog_client.c
> new file mode 100644
> index 000000000000..2d9c7e37f918
> --- /dev/null
> +++ b/fs/ceph/blog_client.c
> @@ -0,0 +1,244 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Ceph client ID management for BLOG integration
> + *
> + * Maintains mapping between Ceph's fsid/global_id and BLOG client IDs
> + */
> +
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +#include <linux/string.h>
> +#include <linux/ceph/ceph_debug.h>
> +#include <linux/ceph/libceph.h>
> +#include <linux/ceph/ceph_blog.h>
> +#include <linux/blog/blog.h>
> +
> +/* Ceph's BLOG module context */
> +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;
> +EXPORT_SYMBOL(ceph_logger);
> +
> +/* Global client mapping state */
> +static struct {
> +	struct ceph_blog_client_info client_map[CEPH_BLOG_MAX_CLIENTS];
> +	u32 next_client_id;
> +	spinlock_t lock;  /* protects client_map */
> +	bool initialized;
> +} ceph_blog_state = {
> +	.next_client_id = 1,  /* Start from 1, 0 is reserved */
> +	.lock = __SPIN_LOCK_UNLOCKED(ceph_blog_state.lock),
> +	.initialized = false,
> +};
> +
> +static bool ceph_blog_ids_match(const struct ceph_blog_client_info *entry,
> +				     const char *fsid, u64 global_id)
> +{
> +	if (!entry)
> +		return false;
> +	if (entry->global_id != global_id)
> +		return false;
> +	return !memcmp(entry->fsid, fsid, sizeof(entry->fsid));
> +}
> +
> +/**
> + * ceph_blog_init - Initialize Ceph BLOG integration
> + *
> + * Creates a module-specific BLOG context for Ceph and initializes
> + * the client ID mapping state.
> + *
> + * Return: 0 on success, negative error code on failure
> + */
> +int ceph_blog_init(void)
> +{
> +	if (ceph_blog_state.initialized)
> +		return 0;
> +
> +	/* Create Ceph's module-specific BLOG context */
> +	ceph_blog_ctx = blog_module_init("ceph");
> +	if (!ceph_blog_ctx) {
> +		pr_err("ceph: Failed to initialize BLOG module context\n");
> +		return -ENOMEM;
> +	}
> +
> +	/* Set ceph_logger for direct access to the logger */
> +	ceph_logger = ceph_blog_ctx->logger;
> +
> +	/* Initialize 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;
> +}
> +EXPORT_SYMBOL(ceph_blog_init);
> +
> +/**
> + * ceph_blog_cleanup - Clean up Ceph BLOG integration
> + *
> + * Cleans up Ceph's module-specific BLOG context and client mappings.
> + */
> +void ceph_blog_cleanup(void)
> +{
> +	if (!ceph_blog_state.initialized)
> +		return;
> +
> +	/* Clean up client mapping state */
> +	spin_lock(&ceph_blog_state.lock);
> +	memset(ceph_blog_state.client_map, 0, sizeof(ceph_blog_state.client_map));
> +	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);
> +
> +/**
> + * ceph_blog_check_client_id - Check if a client ID matches the given fsid:global_id pair
> + * @id: Client ID to check
> + * @fsid: Client FSID to compare
> + * @global_id: Client global ID to compare
> + *
> + * This preserves the exact functionality of ceph_san_check_client_id.
> + * Returns the actual ID of the pair. If the given ID doesn't match, scans for
> + * existing matches or allocates a new ID if no match is found.
> + *
> + * Return: Client ID for this fsid/global_id pair
> + */
> +u32 ceph_blog_check_client_id(u32 id, const char *fsid, u64 global_id)
> +{
> +	u32 found_id = 0;
> +	struct ceph_blog_client_info *entry;
> +
> +	if (unlikely(!ceph_blog_state.initialized)) {
> +		WARN_ON_ONCE(1);  /* Should never happen - init_ceph() initializes BLOG */
> +		return 0;  /* Drop the log entry */
> +	}
> +
> +	spin_lock(&ceph_blog_state.lock);
> +
> +	/* Reuse caller-provided hint when it still matches */
> +	if (id != 0 && id < CEPH_BLOG_MAX_CLIENTS) {
> +		entry = &ceph_blog_state.client_map[id];
> +		if (ceph_blog_ids_match(entry, fsid, global_id)) {
> +			found_id = id;
> +			goto out;
> +		}
> +	}
> +
> +	/* Search for an existing entry with matching identity */
> +	for (id = 1; id < CEPH_BLOG_MAX_CLIENTS; id++) {
> +		entry = &ceph_blog_state.client_map[id];
> +		if (ceph_blog_ids_match(entry, fsid, global_id)) {
> +			found_id = id;
> +			goto out;
> +		}
> +	}
> +
> +	/* Assign new identifier, falling back to overflow slot if exhausted */
> +	if (ceph_blog_state.next_client_id >= CEPH_BLOG_MAX_CLIENTS - 1) {
> +		found_id = CEPH_BLOG_MAX_CLIENTS - 1;
> +		entry = &ceph_blog_state.client_map[found_id];
> +	} else {
> +		found_id = ceph_blog_state.next_client_id++;
> +		entry = &ceph_blog_state.client_map[found_id];
> +	}
> +
> +	memset(entry, 0, sizeof(*entry));
> +	memcpy(entry->fsid, fsid, sizeof(entry->fsid));
> +	entry->global_id = global_id;
> +
> +	pr_info("ceph: allocating new BLOG client ID %u for fsid=%pU global_id=%llu\n",
> +		found_id, fsid, global_id);
> +
> +out:
> +	spin_unlock(&ceph_blog_state.lock);
> +	return found_id;
> +}
> +EXPORT_SYMBOL(ceph_blog_check_client_id);
> +
> +/**
> + * ceph_blog_get_client_info - Get client info for a given ID
> + * @id: Client ID
> + *
> + * Return: Client information for this ID, or NULL if invalid
> + */
> +const struct ceph_blog_client_info *ceph_blog_get_client_info(u32 id)
> +{
> +	if (!ceph_blog_state.initialized || id == 0 || id >= CEPH_BLOG_MAX_CLIENTS)
> +		return NULL;
> +	return &ceph_blog_state.client_map[id];
> +}
> +EXPORT_SYMBOL(ceph_blog_get_client_info);
> +
> +/**
> + * ceph_blog_client_des_callback - Deserialization callback for Ceph client info
> + * @buf: Output buffer
> + * @size: Buffer size
> + * @client_id: Client ID to deserialize
> + *
> + * This is the callback that BLOG will use to deserialize client information.
> + *
> + * Return: Number of bytes written to buffer
> + */
> +int ceph_blog_client_des_callback(char *buf, size_t size, u8 client_id)
> +{
> +	const struct ceph_blog_client_info *info;
> +
> +	if (!buf || !size)
> +		return -EINVAL;
> +
> +	info = ceph_blog_get_client_info(client_id);
> +	if (!info)
> +		return snprintf(buf, size, "[unknown_client_%u]", client_id);
> +
> +	/* Use %pU to format fsid, matching boutc and other Ceph client logging */
> +	return snprintf(buf, size, "[%pU %llu] ",
> +			info->fsid, info->global_id);
> +}
> +EXPORT_SYMBOL(ceph_blog_client_des_callback);
> +
> +/**
> + * ceph_blog_get_client_id - Get or allocate client ID for a Ceph client
> + * @client: Ceph client structure
> + *
> + * Return: Client ID for this client
> + */
> +u32 ceph_blog_get_client_id(struct ceph_client *client)
> +{
> +	u32 cached = 0;
> +	u32 id;
> +
> +	if (!client)
> +		return 0;
> +
> +#ifdef CONFIG_BLOG
> +	cached = READ_ONCE(client->blog_client_id);
> +#endif
> +
> +	id = ceph_blog_check_client_id(cached,
> +					 client->fsid.fsid,
> +					 client->monc.auth->global_id);
> +	if (!id)
> +		return 0;
> +
> +#ifdef CONFIG_BLOG
> +	if (READ_ONCE(client->blog_client_id) != id)
> +		WRITE_ONCE(client->blog_client_id, id);
> +#endif
> +
> +	return id;
> +}
> +EXPORT_SYMBOL(ceph_blog_get_client_id);
> diff --git a/include/linux/ceph/ceph_blog.h b/include/linux/ceph/ceph_blog.h
> new file mode 100644
> index 000000000000..0591e3f29703
> --- /dev/null
> +++ b/include/linux/ceph/ceph_blog.h
> @@ -0,0 +1,124 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Ceph integration with BLOG (Binary LOGging)
> + *
> + * Provides compatibility layer and Ceph-specific extensions
> + */
> +#ifndef CEPH_BLOG_H
> +#define CEPH_BLOG_H
> +
> +#include <linux/blog/blog.h>
> +#include <linux/blog/blog_module.h>
> +#include <linux/ceph/libceph.h>
> +
> +/* Client ID mapping structure - preserves ceph_san_client_id fields */
> +struct ceph_blog_client_info {
> +	char fsid[16];         /* Client FSID */
> +	u64 global_id;         /* Client global ID */
> +};
> +
> +/* Constants */
> +#define CEPH_BLOG_MAX_CLIENTS 256
> +
> +/* Ceph's BLOG module context */
> +extern struct blog_module_context *ceph_blog_ctx;
> +
> +/* Ceph's logger - direct access to the logger for macros */
> +extern struct blog_logger *ceph_logger;
> +
> +/* Forward declaration for ceph_client */
> +struct ceph_client;
> +
> +/* Compatibility macros for easy migration from ceph_san to BLOG */
> +#if IS_ENABLED(CONFIG_BLOG)
> +
> +/* Ceph BLOG client management functions */
> +int ceph_blog_init(void);
> +void ceph_blog_cleanup(void);
> +u32 ceph_blog_check_client_id(u32 id, const char *fsid, u64 global_id);
> +u32 ceph_blog_get_client_id(struct ceph_client *client);
> +const struct ceph_blog_client_info *ceph_blog_get_client_info(u32 id);
> +int ceph_blog_client_des_callback(char *buf, size_t size, u8 client_id);
> +
> +/*
> + * All ceph_san compatibility removed - use only BLOG with per-module contexts
> + * CEPH_SAN has been replaced entirely by BLOG per-module logging
> + */
> +
> +/*
> + * Ceph-specific logging macros - use core BLOG functions with ceph_logger
> + * Note: Only client-aware macros (doutc, boutc) store client_id,
> + * regular macros (dout, bout) do not include client information
> + */
> +#define CEPH_BLOG_LOG(fmt, ...) \
> +	do { \
> +		static u32 __source_id; \
> +		static size_t __size; \
> +		void *___buffer = NULL; \
> +		if (unlikely(!ceph_logger)) \
> +			break; \
> +		if (unlikely(__source_id == 0)) { \
> +			__source_id = blog_get_source_id(ceph_logger, \
> +				kbasename(__FILE__), __func__, __LINE__, fmt); \
> +			__size = blog_cnt(__VA_ARGS__); \
> +		} \
> +		___buffer = blog_log(ceph_logger, __source_id, 0, __size); \
> +		if (likely(___buffer)) { \
> +			void *___tmp = ___buffer; \
> +			if (__size > 0) \
> +				blog_ser(___buffer, ##__VA_ARGS__); \
> +			blog_log_commit(ceph_logger, ___buffer - ___tmp); \
> +		} \
> +	} while (0)
> +
> +#define CEPH_BLOG_LOG_CLIENT(client, fmt, ...) \
> +	do { \
> +		static u32 __source_id; \
> +		static size_t __size; \
> +		void *___buffer = NULL; \
> +		u32 __client_id; \
> +		if (unlikely(!ceph_logger)) \
> +			break; \
> +		if (unlikely(__source_id == 0)) { \
> +			__source_id = blog_get_source_id(ceph_logger, \
> +				kbasename(__FILE__), __func__, __LINE__, fmt); \
> +			__size = blog_cnt(__VA_ARGS__); \
> +		} \
> +		__client_id = ceph_blog_get_client_id(client); \
> +		___buffer = blog_log(ceph_logger, __source_id, __client_id, __size); \
> +		if (likely(___buffer)) { \
> +			void *___tmp = ___buffer; \
> +			if (__size > 0) \
> +				blog_ser(___buffer, ##__VA_ARGS__); \
> +			blog_log_commit(ceph_logger, ___buffer - ___tmp); \
> +		} \
> +	} while (0)
> +
> +/* No legacy ceph_san compatibility - use CEPH_BLOG_LOG* macros only */
> +
> +#else /* !CONFIG_BLOG */
> +
> +/* Stub macros when BLOG is not enabled */
> +#define CEPH_BLOG_LOG(fmt, ...) do {} while (0)
> +#define CEPH_BLOG_LOG_CLIENT(client, fmt, ...) do {} while (0)
> +
> +/* Stub functions should be static inline, not macros */
> +static inline int ceph_blog_init(void) { return 0; }
> +static inline void ceph_blog_cleanup(void) { }
> +static inline u32 ceph_blog_get_client_id(struct ceph_client *client) { return 0; }
> +static inline u32 ceph_blog_check_client_id(u32 id, const char *fsid, u64 global_id) { return 0; }
> +static inline const struct ceph_blog_client_info *ceph_blog_get_client_info(u32 id) { return NULL; }
> +static inline int ceph_blog_client_des_callback(char *buf, size_t size, u8 client_id) { return 0; }
> +
> +#endif /* CONFIG_BLOG */
> +
> +/* Debugfs support */
> +#ifdef CONFIG_DEBUG_FS
> +int ceph_blog_debugfs_init(struct dentry *parent);
> +void ceph_blog_debugfs_cleanup(void);
> +#else
> +static inline int ceph_blog_debugfs_init(struct dentry *parent) { return 0; }
> +static inline void ceph_blog_debugfs_cleanup(void) {}
> +#endif
> +
> +#endif /* CEPH_BLOG_H */

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ