From 8d9be43522804f2cd7f21b7ce153c717bacbf343 Mon Sep 17 00:00:00 2001 From: Alex Markuze Date: Tue, 15 Apr 2025 14:09:21 +0000 Subject: [PATCH] fsid cache WIP --- include/linux/ceph/ceph_debug.h | 5 +- include/linux/ceph/ceph_san_logger.h | 38 ++++++++- net/ceph/ceph_san_logger.c | 118 +++++++++++++++++++++++++++ 3 files changed, 156 insertions(+), 5 deletions(-) diff --git a/include/linux/ceph/ceph_debug.h b/include/linux/ceph/ceph_debug.h index 19d27fb4eaf2..48ebf9e2632e 100644 --- a/include/linux/ceph/ceph_debug.h +++ b/include/linux/ceph/ceph_debug.h @@ -51,10 +51,7 @@ * or, just wrap pr_debug */ # define dout(fmt, ...) CEPH_SAN_LOG(fmt, ##__VA_ARGS__) -# define doutc(__c, fmt, ...) if (__c) { CEPH_SAN_LOG(fmt, ##__VA_ARGS__); } -//# define doutc(client, fmt, ...) \ -// CEPH_SAN_LOG("[%pU:%llu] " fmt, &client->fsid, \ -// client->monc.auth->global_id, ##__VA_ARGS__) +# define doutc(client, fmt, ...) CEPH_SAN_LOG_CLIENT(client, fmt, ##__VA_ARGS__) #endif diff --git a/include/linux/ceph/ceph_san_logger.h b/include/linux/ceph/ceph_san_logger.h index cc200c639026..e7e4fecf71b5 100644 --- a/include/linux/ceph/ceph_san_logger.h +++ b/include/linux/ceph/ceph_san_logger.h @@ -14,6 +14,14 @@ #define CEPH_SAN_LOG_MAX_LEN 256 #define CEPH_SAN_LOG_ENTRY_POISON 0xDEADBEEF #define CEPH_SAN_MAX_SOURCE_IDS 4096 +#define CEPH_SAN_MAX_CLIENT_IDS 1024 + +/* Client ID cache entry */ +struct ceph_san_client_id { + char fsid[16]; /* Client FSID */ + u64 global_id; /* Client global ID */ + u32 idx; /* Index in the cache */ +}; /* Source information mapping structure */ struct ceph_san_source_info { @@ -28,6 +36,7 @@ struct ceph_san_log_entry { u64 debug_poison; /* Debug poison value */ u64 ts; /* Timestamp (jiffies) */ u32 source_id; /* ID for source file/function/line */ + u32 client_id; /* ID for client (fsid:global_id) */ unsigned int len; /* Length of the message */ char *buffer; /* Flexible array for inline buffer */ }; @@ -48,7 +57,10 @@ struct ceph_san_logger { 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 */ + struct ceph_san_client_id client_map[CEPH_SAN_MAX_CLIENT_IDS]; /* Client ID mapping */ atomic_t next_source_id; /* Next source ID to assign */ + u32 next_client_id; /* Next client ID to assign */ + spinlock_t client_lock; /* Protects client ID operations */ }; /* Iterator for log entries in a single pagefrag */ @@ -78,8 +90,14 @@ 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); +/* Check if client ID matches given fsid and global_id, returning the actual ID */ +u32 ceph_san_check_client_id(u32 id, const char *fsid, u64 global_id); + +/* Get client information for ID */ +const struct ceph_san_client_id *ceph_san_get_client_info(u32 id); + /* Log a message */ -void* ceph_san_log(u32 source_id, size_t size); +void* ceph_san_log(u32 source_id, size_t needed_size); /* Get current TLS context, creating if necessary */ struct ceph_san_tls_ctx *ceph_san_get_tls_ctx(void); @@ -100,6 +118,24 @@ struct ceph_san_tls_ctx *ceph_san_get_tls_ctx(void); } \ } while (0) +/* Helper macro for logging with client ID */ +#define CEPH_SAN_LOG_CLIENT(client, fmt, ...) \ + do { \ + static u32 __source_id = 0; \ + static u32 __client_id = 0; \ + static size_t __size = 0; \ + void *___buffer = NULL; \ + if (unlikely(__source_id == 0)) { \ + __source_id = ceph_san_get_source_id(kbasename(__FILE__), __func__, __LINE__, fmt); \ + __size = ceph_san_cnt(__VA_ARGS__); \ + } \ + __client_id = ceph_san_check_client_id(__client_id, client->fsid.fsid, client->monc.auth->global_id); \ + ___buffer = ceph_san_log(__source_id, __size); \ + if (likely(___buffer)) { \ + ceph_san_ser(___buffer, ##__VA_ARGS__);\ + } \ + } while (0) + /* Global logger instance */ extern struct ceph_san_logger g_logger; diff --git a/net/ceph/ceph_san_logger.c b/net/ceph/ceph_san_logger.c index 46127229cc32..f2ba6f7c384b 100644 --- a/net/ceph/ceph_san_logger.c +++ b/net/ceph/ceph_san_logger.c @@ -152,6 +152,124 @@ const struct ceph_san_source_info *ceph_san_get_source_info(u32 id) } EXPORT_SYMBOL(ceph_san_get_source_info); +/** + * ceph_san_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 + * + * 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. + */ +u32 ceph_san_check_client_id(u32 id, const char *fsid, u64 global_id) +{ + u32 found_id = 0; + struct ceph_san_client_id *entry; + u32 max_id; + + /* First check if the given ID matches */ + if (id != 0 && id < CEPH_SAN_MAX_CLIENT_IDS) { + entry = &g_logger.client_map[id]; + if (memcmp(entry->fsid, fsid, sizeof(entry->fsid)) == 0 && + entry->global_id == global_id) { + found_id = id; + goto out_fast; + } + } + + spin_lock(&g_logger.client_lock); + max_id = g_logger.next_client_id; + + /* Scan for existing match */ + for (id = 1; id < max_id && id < CEPH_SAN_MAX_CLIENT_IDS; id++) { + entry = &g_logger.client_map[id]; + if (memcmp(entry->fsid, fsid, sizeof(entry->fsid)) == 0 && + entry->global_id == global_id) { + found_id = id; + goto out; + } + } + + /* No match found, allocate new ID */ + found_id = ++g_logger.next_client_id; + if (found_id >= CEPH_SAN_MAX_CLIENT_IDS) { + /* If we run out of IDs, just use the first one */ + pr_warn("ceph_san_logger: client ID overflow, reusing ID 1\n"); + found_id = 1; + } + + entry = &g_logger.client_map[found_id]; + memcpy(entry->fsid, fsid, sizeof(entry->fsid)); + entry->global_id = global_id; + entry->idx = found_id; + +out: + spin_unlock(&g_logger.client_lock); +out_fast: + return found_id; +} +EXPORT_SYMBOL(ceph_san_check_client_id); + +/** + * ceph_san_get_client_id - Helper function to get or create a client ID + * @fsid: Client FSID + * @global_id: Client global ID + * + * Returns a unique ID for this client pair + */ +static u32 ceph_san_get_client_id(const char *fsid, u64 global_id) +{ + u32 id; + struct ceph_san_client_id *entry; + bool found = false; + u32 max_id; + + spin_lock(&g_logger.client_lock); + max_id = g_logger.next_client_id; + + /* First try to find existing entry */ + for (id = 1; id < max_id && id < CEPH_SAN_MAX_CLIENT_IDS; id++) { + entry = &g_logger.client_map[id]; + if (memcmp(entry->fsid, fsid, sizeof(entry->fsid)) == 0 && + entry->global_id == global_id) { + found = true; + break; + } + } + + /* If not found, allocate new ID */ + if (!found) { + id = ++g_logger.next_client_id; + if (id >= CEPH_SAN_MAX_CLIENT_IDS) { + /* If we run out of IDs, just use the first one */ + pr_warn("ceph_san_logger: client ID overflow, reusing ID 1\n"); + id = 1; + } + + entry = &g_logger.client_map[id]; + memcpy(entry->fsid, fsid, sizeof(entry->fsid)); + entry->global_id = global_id; + entry->idx = id; + } + + spin_unlock(&g_logger.client_lock); + return id; +} + +/** + * ceph_san_get_client_info - Get client info for a given ID + * @id: Client ID + * + * Returns the client information for this ID + */ +const struct ceph_san_client_id *ceph_san_get_client_info(u32 id) +{ + if (id == 0 || id >= CEPH_SAN_MAX_CLIENT_IDS) + return NULL; + return &g_logger.client_map[id]; +} +EXPORT_SYMBOL(ceph_san_get_client_info); + /** * ceph_san_log - Log a message * @source_id: Source ID for this location -- 2.47.3