From: Alex Markuze Date: Tue, 15 Apr 2025 16:26:59 +0000 (+0000) Subject: desersialize X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5f615c5c305bf67250352792c73c5b0e1d3e8457;p=ceph-client.git desersialize --- diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index 657bd6ee1214..aa5efde57d4f 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -441,10 +441,16 @@ static int ceph_san_tls_show(struct seq_file *s, void *p) continue; } - seq_printf(s, "[%d][%s][%s]:%s:%s:%u: %s\n", + seq_printf(s, "[%d][%s][%s]:%s:%s:%u: ", pid, comm, datetime_str, - source->file, source->func, source->line, - entry->buffer); + source->file, source->func, source->line); + char reconstructed_msg[256]; + int ret = ceph_san_log_reconstruct(entry, reconstructed_msg, sizeof(reconstructed_msg)); + if (ret >= 0) + seq_puts(s, reconstructed_msg); + else + seq_printf(s, "", ret); + seq_putc(s, '\n'); } /* Unlock the pagefrag after we're done with this context */ diff --git a/include/linux/ceph/ceph_san_logger.h b/include/linux/ceph/ceph_san_logger.h index bde916d2c8f9..96bac1d039a4 100644 --- a/include/linux/ceph/ceph_san_logger.h +++ b/include/linux/ceph/ceph_san_logger.h @@ -77,6 +77,9 @@ void ceph_san_log_iter_init(struct ceph_san_log_iter *iter, struct cephsan_pagef /* Get next log entry, returns NULL when no more entries */ struct ceph_san_log_entry *ceph_san_log_iter_next(struct ceph_san_log_iter *iter); +/* Reconstruct a formatted string from a log entry */ +int ceph_san_log_reconstruct(const struct ceph_san_log_entry *entry, char *output, size_t output_size); + /* Initialize the logging system */ int ceph_san_logger_init(void); diff --git a/net/ceph/ceph_san_logger.c b/net/ceph/ceph_san_logger.c index 35481971618c..3d24dbc761c8 100644 --- a/net/ceph/ceph_san_logger.c +++ b/net/ceph/ceph_san_logger.c @@ -410,3 +410,205 @@ struct ceph_san_log_entry *ceph_san_log_iter_next(struct ceph_san_log_iter *iter return entry; } EXPORT_SYMBOL(ceph_san_log_iter_next); + +/** + * ceph_san_log_reconstruct - Reconstruct a formatted string from a log entry + * @entry: Log entry containing serialized data + * @output: Buffer to write the formatted string to + * @output_size: Size of the output buffer + * + * Returns length of formatted string, or negative error code on failure + */ +int ceph_san_log_reconstruct(const struct ceph_san_log_entry *entry, char *output, size_t output_size) +{ + const struct ceph_san_source_info *info; + const char *fmt; + char *in_buffer, *out_ptr; + int ret; + size_t remaining = output_size - 1; // Reserve space for null terminator + + if (!entry || !output || output_size == 0) { + pr_err("ceph_san_log_reconstruct: invalid parameters\n"); + return -EINVAL; + } + + // Get format string from source info + info = ceph_san_get_source_info(entry->source_id); + if (!info) { + pr_err("ceph_san_log_reconstruct: source info not found for ID %u\n", entry->source_id); + return -EINVAL; + } + + fmt = info->fmt; + if (!fmt) { + pr_err("ceph_san_log_reconstruct: format string not found in source info for ID %u\n", entry->source_id); + return -EINVAL; + } + + in_buffer = entry->buffer; + out_ptr = output; + *out_ptr = '\0'; + + // Process the format string + while (*fmt && remaining > 0) { + if (*fmt != '%') { + // Copy regular characters + *out_ptr++ = *fmt++; + remaining--; + continue; + } + + fmt++; // Skip the '%' + + // Handle format specifiers + switch (*fmt) { + case '%': // Literal % + *out_ptr++ = '%'; + remaining--; + break; + + case 's': { // String + const char *str; + if (*(void **)in_buffer == NULL) { + // Inline string + str = in_buffer + sizeof(void *); + in_buffer += sizeof(void *) + strlen(str) + 1; + } else { + // Pointer to string + str = *(const char **)in_buffer; + in_buffer += sizeof(void *); + } + + size_t len = strlen(str); + if (len > remaining) + len = remaining; + + memcpy(out_ptr, str, len); + out_ptr += len; + remaining -= len; + break; + } + + case 'd': case 'i': { // Integer + int val = *(int *)in_buffer; + in_buffer += sizeof(int); + ret = snprintf(out_ptr, remaining, "%d", val); + if (ret > 0) { + if (ret > remaining) + ret = remaining; + out_ptr += ret; + remaining -= ret; + } + break; + } + + case 'u': { // Unsigned integer + unsigned int val = *(unsigned int *)in_buffer; + in_buffer += sizeof(unsigned int); + ret = snprintf(out_ptr, remaining, "%u", val); + if (ret > 0) { + if (ret > remaining) + ret = remaining; + out_ptr += ret; + remaining -= ret; + } + break; + } + + case 'x': case 'X': { // Hex + unsigned int val = *(unsigned int *)in_buffer; + in_buffer += sizeof(unsigned int); + ret = snprintf(out_ptr, remaining, (*fmt == 'x') ? "%x" : "%X", val); + if (ret > 0) { + if (ret > remaining) + ret = remaining; + out_ptr += ret; + remaining -= ret; + } + break; + } + + case 'p': { // Pointer + void *val = *(void **)in_buffer; + in_buffer += sizeof(void *); + ret = snprintf(out_ptr, remaining, "%p", val); + if (ret > 0) { + if (ret > remaining) + ret = remaining; + out_ptr += ret; + remaining -= ret; + } + break; + } + + case 'l': { // Long or long long + fmt++; + if (*fmt == 'l') { // Long long + fmt++; + if (*fmt == 'd' || *fmt == 'i') { + long long val = *(long long *)in_buffer; + in_buffer += sizeof(long long); + ret = snprintf(out_ptr, remaining, "%lld", val); + } else if (*fmt == 'u') { + unsigned long long val = *(unsigned long long *)in_buffer; + in_buffer += sizeof(unsigned long long); + ret = snprintf(out_ptr, remaining, "%llu", val); + } else if (*fmt == 'x') { + unsigned long long val = *(unsigned long long *)in_buffer; + in_buffer += sizeof(unsigned long long); + ret = snprintf(out_ptr, remaining, "%llx", val); + } else if (*fmt == 'X') { + unsigned long long val = *(unsigned long long *)in_buffer; + in_buffer += sizeof(unsigned long long); + ret = snprintf(out_ptr, remaining, "%llX", val); + } else { + pr_err("ceph_san_log_reconstruct: invalid long long format specifier '%%%c%c%c'\n", 'l', 'l', *fmt); + return -EINVAL; + } + } else { // Long + if (*fmt == 'd' || *fmt == 'i') { + long val = *(long *)in_buffer; + in_buffer += sizeof(long); + ret = snprintf(out_ptr, remaining, "%ld", val); + } else if (*fmt == 'u') { + unsigned long val = *(unsigned long *)in_buffer; + in_buffer += sizeof(unsigned long); + ret = snprintf(out_ptr, remaining, "%lu", val); + } else if (*fmt == 'x') { + unsigned long val = *(unsigned long *)in_buffer; + in_buffer += sizeof(unsigned long); + ret = snprintf(out_ptr, remaining, "%lx", val); + } else if (*fmt == 'X') { + unsigned long val = *(unsigned long *)in_buffer; + in_buffer += sizeof(unsigned long); + ret = snprintf(out_ptr, remaining, "%lX", val); + } else { + pr_err("ceph_san_log_reconstruct: invalid long format specifier '%%l%c'\n", *fmt); + return -EINVAL; + } + } + + if (ret > 0) { + if (ret > remaining) + ret = remaining; + out_ptr += ret; + remaining -= ret; + } + break; + } + + default: + // Unknown format specifier + pr_err("ceph_san_log_reconstruct: unknown format specifier '%%%c' in fmt string\n", *fmt); + return -EINVAL; + } + + fmt++; + } + + // Ensure null termination + *out_ptr = '\0'; + + return output_size - remaining - 1; +} +EXPORT_SYMBOL(ceph_san_log_reconstruct);