From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2233B3DB641 for ; Thu, 24 Sep 2026 15:30:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263857; cv=none; b=D1zIJ0Yl1mfSXhgvVRzxKsHphKiPm/V6rKFRs1pyZZ/iz9F8CQNpaTlAvIxYL5kxEEwySCNWmr7AQSdRssf3w6Te96pv1NLFzMl1n9iWQQbhIbP8ck1thZI3dZm7APj58/OGkZDXvWUclfOJ+T8LugTJqdW+9oYuXj8N9wbKOGo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790263857; c=relaxed/simple; bh=rGYZudHnXB2kakW7ng20xVymOZf65arzyn8JpDXsaTc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TURZ37tYWzoakbWiebzu1SS0cRbEqw9XbeQxHcDCyMc0YI/TwOZiX1GHQsVQwl0HiuBumHHVYV5U7foHwMCEKo60I+XfNky7VOwog3BK0kk04hDVmMWe97iI3nNFU+iZ+7eCvDTRbPkY2CdjoPMv4Y584sJuLfwJaOIkWGd6rMY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=T45h7Zpi; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=VqqjnPDc; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="T45h7Zpi"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="VqqjnPDc" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1790263855; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pHt/oeY8nlOaXif4+wd1XaEmPdPd8hLUzUlRc8pfOlA=; b=T45h7ZpiNbWrFr1tXmh5067RdyXLViseBf7TSqfvgtSwdmiLv/hMG2rJqCC0Bd04YNK3HP iQ1Q4RdqCqcHpqZLI85yew1iqcVNsbtC4wYr3JcOYlO45qS5Hf9xQlTI8qMxLHN+vrKE4R tsxEly5bMeYmWSql5oiqMPW5TfhwGSk= Received: from mail-ed1-f72.google.com (mail-ed1-f72.google.com [209.85.208.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-319-4YCHN8vYPead44LxxovLHA-1; Thu, 24 Sep 2026 11:30:53 -0400 X-MC-Unique: 4YCHN8vYPead44LxxovLHA-1 X-Mimecast-MFC-AGG-ID: 4YCHN8vYPead44LxxovLHA_1790263852 Received: by mail-ed1-f72.google.com with SMTP id 4fb4d7f45d1cf-6a642d690caso3134256a12.2 for ; Thu, 24 Sep 2026 08:30:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1790263852; x=1790868652; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=pHt/oeY8nlOaXif4+wd1XaEmPdPd8hLUzUlRc8pfOlA=; b=VqqjnPDcSCqc0pVOcTDY6vLIpejVnHgc4PsJBm5h0HD1BjtpeYAvg+bRgh5WGtD6zJ oYbwXBL/K/LP6TsyMAgwq9uU0pR7jpc9SUG3XH2oNwN0313kECstMNAP0gyzrNolz158 zGllJgxFDw31NehXNPqTsNQLV+9aLwgIKp5raaRY+URFiu9dK0K1zHhWwdNc2SoDW5JM n9BeJ51+qbehL6mTTEyNbYu8mPAIxXLkG4G9teLb0pN9b9rhaVCDwV030X/bzWWAm/Lh Zu+7/lDEi7P7/QIBtNSKy74vmkuKqlpar5ERrb2R3LBYp2DAUQ5Rk/zQ12S7HHlkQlhP MtrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790263852; x=1790868652; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=pHt/oeY8nlOaXif4+wd1XaEmPdPd8hLUzUlRc8pfOlA=; b=l9uJIb9YmGItlH1sdh1SSeSPulAZBwO4K7tXAbnAyHA3VSMrPAYmq5KfZ/iZQmPx89 01pkY8SpzH5bYOCL30uSQ7vRiRkHQZPNGy2Yx1EF1Lp+1LVxKJPXgar7BKVqPfrPf7hM mSKEWCU7vJdjZ9W6Z3X350P6RdwiRLyKPdfhr3CpWCK23q+cP4gHJwEFxixexqg9SN+u DDAk/JLHJL2ZZ5lZWsJ48KbCyreIOMLK/QpBlxmpzhVD7eEr+bHU+jqrPaA/dV2fOq0a 1MvHynf7Es/kJlKPVgnz8YTX96WSIJhj0l3yIQEjF90scd+BSWveHd29UC7L8doFJ3tL JHig== X-Gm-Message-State: AFuF++nMBkF7tHE+BMuADcHg30UzaX5LrwYGGk4fSfKP+blRmfF02IHX ndtHmCpc5GOtEjDH0Ki9AWGBTayB6ZDGT6SB7AiBNF0YCfEpZCwgK19fYUatnRsfPEuuFp8ukVj QpFJ28ChhotFU144OJezTZxhPxkeIFg+BFFStaTmrfGlb80H7FBz9uKF4DQn1Gh16fcKfXACK6+ jRTj6SFsKiI0cUDmwHz23zmJ+ePOvbFhZ6Y/OZ5zBDdCGDQr+b/Q== X-Gm-Gg: AYBFou3JKhAZZpdeTYHdI4Kt9lCqgRtZItDc8tKhQnQD3XHWVgNAJaX+ifJlBFFMHOG +QZ/BitPWi4eS4lUvGr6Sz+lCKiH6b+ct11V9u5MOXevcmWlas/6ADLBCEan7jw9IVIIQUPlG1u zB9ZYpzusF3IEPTnsw4z6vgcgCzqL/w9R0PfchztF6ZYo7xNrLSk6trNcLCvcgtZ5QaSeS/gKpo BFwUgWUmCbnRAhOGF+s46cqcQmtsAl9ybrgSGu0AVwZt5BnYI8ZUVaoO/7PKkhdWXebVfWRiiS6 0JxG4IbaVjwRoBJEjeniA97hkZmRu24k3tELNF4o4NXJ3BDpRvxGJ4C+5KSuZWSAclymKK4NqiX nuXghtCGt6tbXYAR9ZGegpmYvPwjoP8S3FUShjgSS5asq/0ouKRBayuQ9UH8GU654WHENBfMcnR dWVjHl6A/HLnknKQ== X-Received: by 2002:a05:6402:11ce:b0:6aa:ad13:40bc with SMTP id 4fb4d7f45d1cf-6aac90b06a4mr2737734a12.37.1790263851752; Thu, 24 Sep 2026 08:30:51 -0700 (PDT) X-Received: by 2002:a05:6402:11ce:b0:6aa:ad13:40bc with SMTP id 4fb4d7f45d1cf-6aac90b06a4mr2737683a12.37.1790263850949; Thu, 24 Sep 2026 08:30:50 -0700 (PDT) Received: from cluster.. (4f.55.790d.ip4.static.sl-reverse.com. [13.121.85.79]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-6aab386e5b9sm3941908a12.8.2026.09.24.08.30.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 24 Sep 2026 08:30:49 -0700 (PDT) From: Alex Markuze To: ceph-devel@vger.kernel.org Cc: idryomov@gmail.com, xiubo.li@clyso.com Subject: [PATCH v7 02/14] ceph: add BLOG deserialization support Date: Thu, 24 Sep 2026 15:30:32 +0000 Message-Id: <20260924153045.994784-3-amarkuze@redhat.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260924153045.994784-1-amarkuze@redhat.com> References: <20260924153045.994784-1-amarkuze@redhat.com> Precedence: bulk X-Mailing-List: ceph-devel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Add blog_des.c implementing the binary record deserialization engine used by the debugfs read paths. Supports %d, %i, %u, %o, %x, %X, %s, %p, %c, and length modifiers (l, ll, h, hh, z). Signed-off-by: Alex Markuze --- fs/ceph/blog_des.c | 335 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 fs/ceph/blog_des.c diff --git a/fs/ceph/blog_des.c b/fs/ceph/blog_des.c new file mode 100644 index 000000000000..b83212dee856 --- /dev/null +++ b/fs/ceph/blog_des.c @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * BLOG record deserialization. + */ + +#include "blog_des.h" +#include "blog.h" +#include +#include +#include +#include +#include +#include +#include + +static inline void des_advance(int ret, char **out, size_t *remaining) +{ + if (ret > 0) { + if ((size_t)ret > *remaining) + ret = *remaining; + *out += ret; + *remaining -= ret; + } +} + +/** + * blog_des_reconstruct - Reconstructs a formatted string from serialized values + * @fmt: Format string containing % specifiers + * @buffer: Buffer containing serialized values + * @size: Size of the buffer in bytes + * @out: Buffer to store the reconstructed string + * @out_size: Size of the output buffer + */ +int blog_des_reconstruct(const char *fmt, const void *buffer, + size_t size, char *out, size_t out_size) +{ + const char *buf_start = (const char *)buffer; + const char *buf_ptr = buf_start; + const char *buf_end = buf_start + size; + const char *fmt_ptr = fmt; + char *out_ptr = out; + /* Payload budget; snprintf() is called with remaining + 1 so the + * last character that still fits is not dropped for the NUL. */ + size_t remaining = out_size - 1; + size_t arg_count = 0; + int ret; + + if (!fmt || !buffer || !out || !out_size) { + pr_err_ratelimited("blog_des_reconstruct: invalid params fmt=%p buffer=%p out=%p out_size=%zu\n", + fmt, buffer, out, out_size); + return -EINVAL; + } + + *out_ptr = '\0'; + + while (*fmt_ptr && remaining > 0) { + int is_long; + int is_long_long; + int alt_form = 0; + int dyn_width = -1; + int dyn_precision = -1; + + if (*fmt_ptr != '%') { + *out_ptr++ = *fmt_ptr++; + remaining--; + continue; + } + + fmt_ptr++; + + if (*fmt_ptr == '%') { + *out_ptr++ = '%'; + fmt_ptr++; + remaining--; + continue; + } + + /* Skip flags (-+#0 space); remember '#' for hex/octal. */ + while (*fmt_ptr && (*fmt_ptr == '-' || *fmt_ptr == '+' || *fmt_ptr == '#' || + *fmt_ptr == '0' || *fmt_ptr == ' ')) { + if (*fmt_ptr == '#') + alt_form = 1; + fmt_ptr++; + } + + /* Consume field width: digits are format-only, * is serialized */ + while (*fmt_ptr && (*fmt_ptr >= '0' && *fmt_ptr <= '9')) + fmt_ptr++; + if (*fmt_ptr == '*') { + if (buf_ptr + sizeof(int) > buf_end) + return -EBADMSG; + dyn_width = get_unaligned((int *)buf_ptr); + buf_ptr += sizeof(int); + fmt_ptr++; + } + + /* Consume precision: digits are format-only, * is serialized */ + if (*fmt_ptr == '.') { + fmt_ptr++; + while (*fmt_ptr && (*fmt_ptr >= '0' && *fmt_ptr <= '9')) + fmt_ptr++; + if (*fmt_ptr == '*') { + if (buf_ptr + sizeof(int) > buf_end) + return -EBADMSG; + dyn_precision = get_unaligned((int *)buf_ptr); + buf_ptr += sizeof(int); + fmt_ptr++; + } + } + + /* + * dyn_width: consumed from the buffer to keep offsets + * aligned; output width-padding is not implemented. + */ + (void)dyn_width; + + /* Parse length modifiers (l, ll, h, hh, z) */ + is_long = 0; + is_long_long = 0; + + if (*fmt_ptr == 'l') { + fmt_ptr++; + is_long = 1; + if (*fmt_ptr == 'l') { + fmt_ptr++; + is_long_long = 1; + is_long = 0; + } + } else if (*fmt_ptr == 'h') { + fmt_ptr++; + if (*fmt_ptr == 'h') + fmt_ptr++; + } else if (*fmt_ptr == 'z') { + fmt_ptr++; + if (sizeof(size_t) == sizeof(long long)) + is_long_long = 1; + else + is_long = 1; + } + + switch (*fmt_ptr) { + case 's': { + const char *str; + size_t str_len; + size_t out_len; + size_t max_scan_len; + + if (buf_ptr >= buf_end) { + pr_err_ratelimited("blog_des_reconstruct: string arg %zu overruns buffer (no space)\n", + arg_count); + return -EBADMSG; + } + + str = buf_ptr; + max_scan_len = buf_end - buf_ptr; + + str_len = strnlen(str, max_scan_len); + if (str_len == max_scan_len && str[str_len - 1] != '\0') { + pr_err_ratelimited("blog_des_reconstruct: unterminated string at arg %zu (fmt=%s)\n", + arg_count, fmt); + return -EBADMSG; + } + + buf_ptr += round_up(str_len + 1, 4); + if (buf_ptr > buf_end) { + pr_err_ratelimited("blog_des_reconstruct: string arg %zu overruns buffer after copy (fmt=%s)\n", + arg_count, fmt); + return -EBADMSG; + } + + out_len = str_len; + if (dyn_precision >= 0 && (size_t)dyn_precision < out_len) + out_len = (size_t)dyn_precision; + if (out_len > remaining) + out_len = remaining; + memcpy(out_ptr, str, out_len); + out_ptr += out_len; + remaining -= out_len; + break; + } + case 'd': + case 'i': { + if (is_long_long) { + long long val; + + if (buf_ptr + sizeof(long long) > buf_end) + return -EBADMSG; + val = get_unaligned((long long *)buf_ptr); + buf_ptr += sizeof(long long); + ret = snprintf(out_ptr, remaining + 1, "%lld", val); + } else if (is_long) { + long val; + + if (buf_ptr + sizeof(long) > buf_end) + return -EBADMSG; + val = get_unaligned((long *)buf_ptr); + buf_ptr += sizeof(long); + ret = snprintf(out_ptr, remaining + 1, "%ld", val); + } else { + int val; + + if (buf_ptr + sizeof(int) > buf_end) + return -EBADMSG; + val = get_unaligned((int *)buf_ptr); + buf_ptr += sizeof(int); + ret = snprintf(out_ptr, remaining + 1, "%d", val); + } + des_advance(ret, &out_ptr, &remaining); + break; + } + case 'u': { + if (is_long_long) { + unsigned long long val; + + if (buf_ptr + sizeof(unsigned long long) > buf_end) + return -EBADMSG; + val = get_unaligned((unsigned long long *)buf_ptr); + buf_ptr += sizeof(unsigned long long); + ret = snprintf(out_ptr, remaining + 1, "%llu", val); + } else if (is_long) { + unsigned long val; + + if (buf_ptr + sizeof(unsigned long) > buf_end) + return -EBADMSG; + val = get_unaligned((unsigned long *)buf_ptr); + buf_ptr += sizeof(unsigned long); + ret = snprintf(out_ptr, remaining + 1, "%lu", val); + } else { + unsigned int val; + + if (buf_ptr + sizeof(unsigned int) > buf_end) + return -EBADMSG; + val = get_unaligned((unsigned int *)buf_ptr); + buf_ptr += sizeof(unsigned int); + ret = snprintf(out_ptr, remaining + 1, "%u", val); + } + des_advance(ret, &out_ptr, &remaining); + break; + } + case 'o': + case 'x': + case 'X': { + const char *num_fmt; + + if (*fmt_ptr == 'o') + num_fmt = is_long_long ? (alt_form ? "%#llo" : "%llo") : + is_long ? (alt_form ? "%#lo" : "%lo") : + (alt_form ? "%#o" : "%o"); + else if (*fmt_ptr == 'x') + num_fmt = is_long_long ? (alt_form ? "%#llx" : "%llx") : + is_long ? (alt_form ? "%#lx" : "%lx") : + (alt_form ? "%#x" : "%x"); + else + num_fmt = is_long_long ? (alt_form ? "%#llX" : "%llX") : + is_long ? (alt_form ? "%#lX" : "%lX") : + (alt_form ? "%#X" : "%X"); + + if (is_long_long) { + unsigned long long val; + + if (buf_ptr + sizeof(unsigned long long) > buf_end) + return -EBADMSG; + val = get_unaligned((unsigned long long *)buf_ptr); + buf_ptr += sizeof(unsigned long long); + ret = snprintf(out_ptr, remaining + 1, num_fmt, val); + } else if (is_long) { + unsigned long val; + + if (buf_ptr + sizeof(unsigned long) > buf_end) + return -EBADMSG; + val = get_unaligned((unsigned long *)buf_ptr); + buf_ptr += sizeof(unsigned long); + ret = snprintf(out_ptr, remaining + 1, num_fmt, val); + } else { + unsigned int val; + + if (buf_ptr + sizeof(unsigned int) > buf_end) + return -EBADMSG; + val = get_unaligned((unsigned int *)buf_ptr); + buf_ptr += sizeof(unsigned int); + ret = snprintf(out_ptr, remaining + 1, num_fmt, val); + } + des_advance(ret, &out_ptr, &remaining); + break; + } + case 'p': { + void *ptr; + + if (buf_ptr + sizeof(void *) > buf_end) + return -EBADMSG; + + ptr = (void *)(unsigned long)get_unaligned((unsigned long *)buf_ptr); + buf_ptr += sizeof(void *); + + /* + * Skip kernel %p sub-specifiers (U, I, d, D, etc.). + * boutc does not support %p extensions; call sites + * must pre-format them with snprintf and pass %s. + */ + while (fmt_ptr[1] && isalnum(fmt_ptr[1])) + fmt_ptr++; + + ret = snprintf(out_ptr, remaining + 1, "%p", ptr); + des_advance(ret, &out_ptr, &remaining); + break; + } + case 'c': { + char val; + + if (buf_ptr + sizeof(int) > buf_end) + return -EBADMSG; + + val = (char)get_unaligned((int *)buf_ptr); + buf_ptr += sizeof(int); + + if (remaining > 0) { + *out_ptr++ = val; + remaining--; + } + break; + } + default: + pr_err_ratelimited("%s: unsupported format specifier '%%%c' at argument %zu\n", + __func__, *fmt_ptr, arg_count); + return -EINVAL; + } + + fmt_ptr++; + arg_count++; + } + + *out_ptr = '\0'; + + return out_ptr - out; +} -- 2.34.1