From nobody Mon May 11 00:45:17 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9CF66C433EF for ; Tue, 19 Apr 2022 20:32:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1357692AbiDSUfU (ORCPT ); Tue, 19 Apr 2022 16:35:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53438 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1357652AbiDSUe6 (ORCPT ); Tue, 19 Apr 2022 16:34:58 -0400 Received: from mail-qt1-x82e.google.com (mail-qt1-x82e.google.com [IPv6:2607:f8b0:4864:20::82e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A26E63C49B; Tue, 19 Apr 2022 13:32:14 -0700 (PDT) Received: by mail-qt1-x82e.google.com with SMTP id f14so4675249qtq.1; Tue, 19 Apr 2022 13:32:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lgfGsgMv5iDJepG0Wr5n+Un2iVDKg5VOEf+xgmHxDBs=; b=JW8nbUmmPCYbXEW4m/voKHCbKvfXkpVRSoFJrUIn5pEFUjB4nLho0sfwhceBtq81zn 3eybXLS5mb7U2qHd/rlY2JZxGm1GpXlx3zRbsSRzrjhVw8Ci0CLePy053yS5gitfj082 b57GRT4DOc3bK/EmH5/pKOkvunA7ur0G2rQcRS6a2x9iE4z7h6PB/BOvYe5rNVy4W0TC BDg9Ly/PgED/gMGYLbu/qtKCIYh7LthitOMRHDyqtIlzrtJHLhQOeRtwBLsHo+Yef7Eb h9nTbI0OXJi/hKhHkaWhakF54rAlATUU+7+pIIXnLMIac7YxQNFy7y5tE7HL7h65dBYM qlTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lgfGsgMv5iDJepG0Wr5n+Un2iVDKg5VOEf+xgmHxDBs=; b=M/VGOvkBOEys+EwT/LKH62aNhLoFLPRy8RVYwQwgRR0HOeEuqYseuGy7zxymBQS9Jy +c6BqyHoMNgNurhK2QKkOAKwzleXDF9Qna7Qp4AQHWAGvlN1jgbADxH7F7o0QF0xl1yR 4oI0OdpICIacEWi1EeDwu2O+YHbRXthSxGNIEi0WYvNJECRSbA4e9adWzXLpwLo2tCMP 01AbUxNxp/OOYLXVk+PtIVirz6a4rNp7y2OpomY9aOHAr9cAKMkmu7JK0vvmkAOk2S/x cLY2KGRqT5F9uSE9dOuz25k3euOUnka+U5jdP6EHpofMZFJ3dW6AXyNfJMxYfcI43vVe bzww== X-Gm-Message-State: AOAM530BUZbH2v3itXiqUxyUfiQHu77ysX62iiVrSCy8b1+/gxmC0pwR Ufm/o+z7ZdbbBNK96M1uu6ojGaZHd91A X-Google-Smtp-Source: ABdhPJwzOLM9njvXoPbdwAYdzn2qRVKdEIxLCFcg4W3glMWw6tGzQsXGOv7mbBPhAYe4bdeFwJknnQ== X-Received: by 2002:a05:622a:11c7:b0:2e1:b594:cb1d with SMTP id n7-20020a05622a11c700b002e1b594cb1dmr11796721qtk.59.1650400332455; Tue, 19 Apr 2022 13:32:12 -0700 (PDT) Received: from moria.home.lan (c-73-219-103-14.hsd1.vt.comcast.net. [73.219.103.14]) by smtp.gmail.com with ESMTPSA id e9-20020ac84e49000000b002f1fcda1ac7sm611180qtw.82.2022.04.19.13.32.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Apr 2022 13:32:11 -0700 (PDT) From: Kent Overstreet To: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Cc: Kent Overstreet , roman.gushchin@linux.dev, hannes@cmpxchg.org Subject: [PATCH 1/4] lib/printbuf: New data structure for heap-allocated strings Date: Tue, 19 Apr 2022 16:31:59 -0400 Message-Id: <20220419203202.2670193-2-kent.overstreet@gmail.com> X-Mailer: git-send-email 2.35.2 In-Reply-To: <20220419203202.2670193-1-kent.overstreet@gmail.com> References: <20220419203202.2670193-1-kent.overstreet@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This adds printbufs: simple heap-allocated strings meant for building up structured messages, for logging/procfs/sysfs and elsewhere. They've been heavily used in bcachefs for writing .to_text() functions/methods - pretty printers, which has in turn greatly improved the overall quality of error messages. Basic usage is documented in include/linux/printbuf.h. The next patches in the series are going to be using printbufs to implement a .to_text() method for shrinkers, and improving OOM reporting. Signed-off-by: Kent Overstreet --- include/linux/printbuf.h | 140 ++++++++++++++++++++ lib/Makefile | 2 +- lib/printbuf.c | 271 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 412 insertions(+), 1 deletion(-) create mode 100644 include/linux/printbuf.h create mode 100644 lib/printbuf.c diff --git a/include/linux/printbuf.h b/include/linux/printbuf.h new file mode 100644 index 0000000000..84a271446d --- /dev/null +++ b/include/linux/printbuf.h @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +/* Copyright (C) 2022 Kent Overstreet */ + +#ifndef _LINUX_PRINTBUF_H +#define _LINUX_PRINTBUF_H + +/* + * Printbufs: Simple heap allocated strings, with some features for struct= ered + * formatting. + * + * This code has provisions for use in userspace, to aid in making other c= ode + * portable between kernelspace and userspace. + * + * Basic example: + * + * struct printbuf buf =3D PRINTBUF; + * + * pr_buf(&buf, "foo=3D"); + * foo_to_text(&buf, foo); + * printk("%s", buf.buf); + * printbuf_exit(&buf); + * + * We can now write pretty printers instead of writing code that dumps + * everything to the kernel log buffer, and then those pretty-printers can= be + * used by other code that outputs to kernel log, sysfs, debugfs, etc. + * + * Memory allocation: Outputing to a printbuf may allocate memory. This + * allocation is done with GFP_KERNEL, by default: use the newer + * memalloc_*_(save|restore) functions as needed. + * + * Since no equivalent yet exists for GFP_ATOMIC/GFP_NOWAIT, memory alloca= tions + * will be done with GFP_ATOMIC if printbuf->atomic is nonzero. + * + * Memory allocation failures: We don't return errors directly, because on + * memory allocation failure we usually don't want to bail out and unwind = - we + * want to print what we've got, on a best-effort basis. But code that doe= s want + * to return -ENOMEM may check printbuf.allocation_failure. + * + * Indenting, tabstops: + * + * To aid is writing multi-line pretty printers spread across multiple + * functions, printbufs track the current indent level. + * + * pr_indent_push() and pr_indent_pop() increase and decrease the current = indent + * level, respectively. + * + * To use tabstops, set printbuf->tabstops[]; they are in units of spaces,= from + * start of line. Once set, pr_tab() will output spaces up to the next tab= stop. + * pr_tab_rjust() will also advance the current line of text up to the next + * tabstop, but it does so by shifting text since the previous tabstop up = to the + * next tabstop - right justifying it. + * + * Make sure you use pr_newline() instead of \n in the format string for i= ndent + * level and tabstops to work corretly. + * + * Output units: printbuf->units exists to tell pretty-printers how to out= put + * numbers: a raw value (e.g. directly from a superblock field), as bytes,= or as + * human readable bytes. pr_units() and pr_sectors() obey it. + * + * Other helpful functions: + * + * pr_human_readable_u64, pr_human_readable_s64: Print an integer with hum= an + * readable units. + * + * pr_time(): for printing a time_t with strftime in userspace, prints as = an + * integer number of seconds in the kernel. + * + * pr_string_option: Given an enumerated value and a string array with nam= es for + * each option, prints out the enum names with the selected one indicated = with + * square brackets. + * + * pr_bitflags: Given a bitflag and a string array with names for each bit, + * prints out the names of the selected bits. + */ + +#include + +enum printbuf_units { + PRINTBUF_UNITS_RAW, + PRINTBUF_UNITS_BYTES, + PRINTBUF_UNITS_HUMAN_READABLE, +}; + +struct printbuf { + char *buf; + unsigned size; + unsigned pos; + unsigned last_newline; + unsigned last_field; + unsigned indent; + enum printbuf_units units:8; + u8 atomic; + bool allocation_failure:1; + u8 tabstop; + u8 tabstops[4]; +}; + +#define PRINTBUF ((struct printbuf) { NULL }) + +/** + * printbuf_exit - exit a printbuf, freeing memory it owns and poisoning it + * against accidental use. + */ +static inline void printbuf_exit(struct printbuf *buf) +{ + kfree(buf->buf); + buf->buf =3D ERR_PTR(-EINTR); /* poison value */ +} + +/** + * printbuf_reset - re-use a printbuf without freeing and re-initializing = it: + */ +static inline void printbuf_reset(struct printbuf *buf) +{ + buf->pos =3D 0; + buf->last_newline =3D 0; + buf->last_field =3D 0; + buf->indent =3D 0; + buf->tabstop =3D 0; +} + +void pr_buf(struct printbuf *out, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +void pr_char(struct printbuf *buf, char c); +void pr_newline(struct printbuf *); +void pr_indent_push(struct printbuf *, unsigned); +void pr_indent_pop(struct printbuf *, unsigned); +void pr_tab(struct printbuf *); +void pr_tab_rjust(struct printbuf *); +void pr_human_readable_u64(struct printbuf *, u64); +void pr_human_readable_s64(struct printbuf *, s64); +void pr_units(struct printbuf *, s64, s64); +void pr_sectors(struct printbuf *, u64); +void pr_time(struct printbuf *, u64); +void pr_uuid(struct printbuf *, u8 *); +void pr_string_option(struct printbuf *, const char * const list[], size_t= ); +void pr_bitflags(struct printbuf *, const char * const list[], u64); + +#endif /* _LINUX_PRINTBUF_H */ diff --git a/lib/Makefile b/lib/Makefile index c588a126a3..31a3904eda 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -34,7 +34,7 @@ lib-y :=3D ctype.o string.o vsprintf.o cmdline.o \ is_single_threaded.o plist.o decompress.o kobject_uevent.o \ earlycpio.o seq_buf.o siphash.o dec_and_lock.o \ nmi_backtrace.o nodemask.o win_minmax.o memcat_p.o \ - buildid.o + buildid.o printbuf.o =20 lib-$(CONFIG_PRINTK) +=3D dump_stack.o lib-$(CONFIG_SMP) +=3D cpumask.o diff --git a/lib/printbuf.c b/lib/printbuf.c new file mode 100644 index 0000000000..1d87de787f --- /dev/null +++ b/lib/printbuf.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: LGPL-2.1+ +/* Copyright (C) 2022 Kent Overstreet */ + +#ifdef __KERNEL__ +#include +#include +#else +#define EXPORT_SYMBOL(x) +#endif + +#include +#include + +static inline size_t printbuf_remaining(struct printbuf *buf) +{ + return buf->size - buf->pos; +} + +static inline size_t printbuf_linelen(struct printbuf *buf) +{ + return buf->pos - buf->last_newline; +} + +static int printbuf_realloc(struct printbuf *out, unsigned extra) +{ + unsigned new_size; + char *buf; + + if (out->pos + extra + 1 < out->size) + return 0; + + new_size =3D roundup_pow_of_two(out->size + extra); + buf =3D krealloc(out->buf, new_size, !out->atomic ? GFP_KERNEL : GFP_ATOM= IC); + + if (!buf) { + out->allocation_failure =3D true; + return -ENOMEM; + } + + out->buf =3D buf; + out->size =3D new_size; + return 0; +} + +void pr_buf(struct printbuf *out, const char *fmt, ...) +{ + va_list args; + int len; + + do { + va_start(args, fmt); + len =3D vsnprintf(out->buf + out->pos, printbuf_remaining(out), fmt, arg= s); + va_end(args); + } while (len + 1 >=3D printbuf_remaining(out) && + !printbuf_realloc(out, len + 1)); + + len =3D min_t(size_t, len, + printbuf_remaining(out) ? printbuf_remaining(out) - 1 : 0); + out->pos +=3D len; +} +EXPORT_SYMBOL(pr_buf); + +void pr_char(struct printbuf *buf, char c) +{ + if (!printbuf_realloc(buf, 1)) { + buf->buf[buf->pos++] =3D c; + buf->buf[buf->pos] =3D 0; + } +} +EXPORT_SYMBOL(pr_char); + +void pr_newline(struct printbuf *buf) +{ + unsigned i; + + pr_char(buf, '\n'); + + buf->last_newline =3D buf->pos; + + for (i =3D 0; i < buf->indent; i++) + pr_char(buf, ' '); + + buf->last_field =3D buf->pos; + buf->tabstop =3D 0; +} +EXPORT_SYMBOL(pr_newline); + +void pr_indent_push(struct printbuf *buf, unsigned spaces) +{ + buf->indent +=3D spaces; + while (spaces--) + pr_char(buf, ' '); +} +EXPORT_SYMBOL(pr_indent_push); + +void pr_indent_pop(struct printbuf *buf, unsigned spaces) +{ + if (buf->last_newline + buf->indent =3D=3D buf->pos) { + buf->pos -=3D spaces; + buf->buf[buf->pos] =3D 0; + } + buf->indent -=3D spaces; +} +EXPORT_SYMBOL(pr_indent_pop); + +void pr_tab(struct printbuf *buf) +{ + BUG_ON(buf->tabstop > ARRAY_SIZE(buf->tabstops)); + + while (printbuf_remaining(buf) > 1 && + printbuf_linelen(buf) < buf->tabstops[buf->tabstop]) + pr_char(buf, ' '); + + buf->last_field =3D buf->pos; + buf->tabstop++; +} +EXPORT_SYMBOL(pr_tab); + +void pr_tab_rjust(struct printbuf *buf) +{ + BUG_ON(buf->tabstop > ARRAY_SIZE(buf->tabstops)); + + if (printbuf_linelen(buf) < buf->tabstops[buf->tabstop]) { + unsigned move =3D buf->pos - buf->last_field; + unsigned shift =3D buf->tabstops[buf->tabstop] - + printbuf_linelen(buf); + + printbuf_realloc(buf, shift); + + if (buf->last_field + shift + 1 < buf->size) { + move =3D min(move, buf->size - 1 - buf->last_field - shift); + + memmove(buf->buf + buf->last_field + shift, + buf->buf + buf->last_field, + move); + memset(buf->buf + buf->last_field, ' ', shift); + buf->pos +=3D shift; + buf->buf[buf->pos] =3D 0; + } + } + + buf->last_field =3D buf->pos; + buf->tabstop++; +} +EXPORT_SYMBOL(pr_tab_rjust); + +static const char si_units[] =3D "?kMGTPEZY"; + +void pr_human_readable_u64(struct printbuf *buf, u64 v) +{ + int u, t =3D 0; + + for (u =3D 0; v >=3D 1024; u++) { + t =3D v & ~(~0U << 10); + v >>=3D 10; + } + + pr_buf(buf, "%llu", v); + + /* + * 103 is magic: t is in the range [-1023, 1023] and we want + * to turn it into [-9, 9] + */ + if (u && t && v < 100 && v > -100) + pr_buf(buf, ".%i", t / 103); + if (u) + pr_char(buf, si_units[u]); +} +EXPORT_SYMBOL(pr_human_readable_u64); + +void pr_human_readable_s64(struct printbuf *buf, s64 v) +{ + if (v < 0) + pr_char(buf, '-'); + pr_human_readable_u64(buf, abs(v)); +} +EXPORT_SYMBOL(pr_human_readable_s64); + +void pr_units(struct printbuf *out, s64 raw, s64 bytes) +{ + switch (out->units) { + case PRINTBUF_UNITS_RAW: + pr_buf(out, "%llu", raw); + break; + case PRINTBUF_UNITS_BYTES: + pr_buf(out, "%llu", bytes); + break; + case PRINTBUF_UNITS_HUMAN_READABLE: + pr_human_readable_s64(out, bytes); + break; + } +} +EXPORT_SYMBOL(pr_units); + +void pr_sectors(struct printbuf *out, u64 v) +{ + pr_units(out, v, v << 9); +} +EXPORT_SYMBOL(pr_sectors); + +#ifdef __KERNEL__ + +void pr_time(struct printbuf *out, u64 time) +{ + pr_buf(out, "%llu", time); +} +EXPORT_SYMBOL(pr_time); + +void pr_uuid(struct printbuf *out, u8 *uuid) +{ + pr_buf(out, "%pUb", uuid); +} +EXPORT_SYMBOL(pr_uuid); + +#else + +#include +#include + +void pr_time(struct printbuf *out, u64 _time) +{ + char time_str[64]; + time_t time =3D _time; + struct tm *tm =3D localtime(&time); + size_t err =3D strftime(time_str, sizeof(time_str), "%c", tm); + + if (!err) + pr_buf(out, "(formatting error)"); + else + pr_buf(out, "%s", time_str); +} + +void pr_uuid(struct printbuf *out, u8 *uuid) +{ + char uuid_str[40]; + + uuid_unparse_lower(uuid, uuid_str); + pr_buf(out, uuid_str); +} + +#endif + +void pr_string_option(struct printbuf *out, + const char * const list[], + size_t selected) +{ + size_t i; + + for (i =3D 0; list[i]; i++) + pr_buf(out, i =3D=3D selected ? "[%s] " : "%s ", list[i]); +} +EXPORT_SYMBOL(pr_string_option); + +void pr_bitflags(struct printbuf *out, + const char * const list[], u64 flags) +{ + unsigned bit, nr =3D 0; + bool first =3D true; + + while (list[nr]) + nr++; + + while (flags && (bit =3D __ffs(flags)) < nr) { + if (!first) + pr_buf(out, ","); + first =3D false; + pr_buf(out, "%s", list[bit]); + flags ^=3D 1 << bit; + } +} +EXPORT_SYMBOL(pr_bitflags); --=20 2.35.2 From nobody Mon May 11 00:45:17 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 164CEC4332F for ; Tue, 19 Apr 2022 20:32:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1357666AbiDSUfG (ORCPT ); Tue, 19 Apr 2022 16:35:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53440 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1357654AbiDSUe6 (ORCPT ); Tue, 19 Apr 2022 16:34:58 -0400 Received: from mail-qk1-x72d.google.com (mail-qk1-x72d.google.com [IPv6:2607:f8b0:4864:20::72d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0A31E3C49E; Tue, 19 Apr 2022 13:32:15 -0700 (PDT) Received: by mail-qk1-x72d.google.com with SMTP id j9so7032847qkg.1; Tue, 19 Apr 2022 13:32:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=eAsTyebn2Y4pYis3+WZXuPp8TzH7j4PwV2amK3FTGx8=; b=khs60x2X71XXGoTkHhioI4BexG0UIkVMgtqev1LPBrp8sYHGVkGviBnDYmmKy13J8b PVmHKs/9xDnbDTA9nadcNVdUvzNsTviuf+zuwOlUk6wWiOiEJ8bOX93ySGVuCXz8tK7M bUfMl6IWLi9YjypNmw8tbT+hFrztpzIUEv6/UrUHRiImiAZfjZeWQEhuir7oGYCcRRA3 ulNhOLWsnuJRF/pnuEI+lAvPH3rP0KS+yJprgTaMr4hEmDwypLjxSqRYn05REIxfQP9t JDkQqJmFjbKmRUGijPkYDG3iQxNA5YpFgnXmRr1EYp6lBBE7A7TC9SZpssDgd0yRyPls YJJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=eAsTyebn2Y4pYis3+WZXuPp8TzH7j4PwV2amK3FTGx8=; b=escF5apfW4CRLFKMVRpNG5FV6vjpLyNyrJPthoiDVxtSm0UFT0t4jCgSdGqaMs1Cng m7z0CS4ssGExQxYFi5f4CoFdvJRmbGnoLk2iRsAFYlwWrab3oLHobf+aM27iRZyQwrmd ZzyuB5j+60nDYd0LexM9i7w+N9sBYNHWbErt3M3fPQyBKt8xcZJhyEpU/3k5disfnWLj nP6RlTIMmyo0vcqlgHBJfp9Pw8TWH886eluKfIJUsdlAeJuiWwjcc4wYGO5koF6LZd3R znUX/0Il0NCn5JuaWvPOQjhysOIqXKYZjapj6ocwLsd6u2BuALFvv5uD30B4Fxa+Un4A XNWQ== X-Gm-Message-State: AOAM533IZzufxRHfCT80Mi9ghaUp9yd/8WanokDEMF7sNQtFPHteznlJ Rcy6d+Y+QofP5BDuLyf6U0MOWzfur75V X-Google-Smtp-Source: ABdhPJzy77PDFL4mID+Y5nmbtwckqXAJD3A1O7H2Cv2QKmNENJFo8FIIY08mjslvWbtO3ZWiJNrtXw== X-Received: by 2002:a05:620a:31a3:b0:69e:c355:18db with SMTP id bi35-20020a05620a31a300b0069ec35518dbmr2812119qkb.752.1650400333705; Tue, 19 Apr 2022 13:32:13 -0700 (PDT) Received: from moria.home.lan (c-73-219-103-14.hsd1.vt.comcast.net. [73.219.103.14]) by smtp.gmail.com with ESMTPSA id e9-20020ac84e49000000b002f1fcda1ac7sm611180qtw.82.2022.04.19.13.32.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Apr 2022 13:32:12 -0700 (PDT) From: Kent Overstreet To: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Cc: Kent Overstreet , roman.gushchin@linux.dev, hannes@cmpxchg.org Subject: [PATCH 2/4] mm: Add a .to_text() method for shrinkers Date: Tue, 19 Apr 2022 16:32:00 -0400 Message-Id: <20220419203202.2670193-3-kent.overstreet@gmail.com> X-Mailer: git-send-email 2.35.2 In-Reply-To: <20220419203202.2670193-1-kent.overstreet@gmail.com> References: <20220419203202.2670193-1-kent.overstreet@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This adds a new callback method to shrinkers which they can use to describe anything relevant to memory reclaim about their internal state, for example object dirtyness. This uses the new printbufs to output to heap allocated strings, so that the .to_text() methods can be used both for messages logged to the console, and also sysfs/debugfs. This patch also adds shrinkers_to_text(), which reports on the top 10 shrinkers - by object count - in sorted order, to be used in OOM reporting. Signed-off-by: Kent Overstreet --- include/linux/shrinker.h | 5 +++ mm/vmscan.c | 75 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h index 76fbf92b04..b5f411768b 100644 --- a/include/linux/shrinker.h +++ b/include/linux/shrinker.h @@ -2,6 +2,8 @@ #ifndef _LINUX_SHRINKER_H #define _LINUX_SHRINKER_H =20 +struct printbuf; + /* * This struct is used to pass information from page reclaim to the shrink= ers. * We consolidate the values for easier extension later. @@ -58,10 +60,12 @@ struct shrink_control { * @flags determine the shrinker abilities, like numa awareness */ struct shrinker { + char name[32]; unsigned long (*count_objects)(struct shrinker *, struct shrink_control *sc); unsigned long (*scan_objects)(struct shrinker *, struct shrink_control *sc); + void (*to_text)(struct printbuf *, struct shrinker *); =20 long batch; /* reclaim batch size, 0 =3D default */ int seeks; /* seeks to recreate an obj */ @@ -94,4 +98,5 @@ extern int register_shrinker(struct shrinker *shrinker); extern void unregister_shrinker(struct shrinker *shrinker); extern void free_prealloced_shrinker(struct shrinker *shrinker); extern void synchronize_shrinkers(void); +void shrinkers_to_text(struct printbuf *); #endif diff --git a/mm/vmscan.c b/mm/vmscan.c index 59b14e0d69..09c483dfd3 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -50,6 +50,7 @@ #include #include #include +#include =20 #include #include @@ -702,6 +703,80 @@ void synchronize_shrinkers(void) } EXPORT_SYMBOL(synchronize_shrinkers); =20 +/** + * shrinkers_to_text - Report on shrinkers with highest usage + * + * This reports on the top 10 shrinkers, by object counts, in sorted order: + * intended to be used for OOM reporting. + */ +void shrinkers_to_text(struct printbuf *out) +{ + struct shrinker *shrinker; + struct shrinker_by_mem { + struct shrinker *shrinker; + unsigned long mem; + } shrinkers_by_mem[10]; + int i, nr =3D 0; + + if (!down_read_trylock(&shrinker_rwsem)) { + pr_buf(out, "(couldn't take shrinker lock)"); + return; + } + + list_for_each_entry(shrinker, &shrinker_list, list) { + struct shrink_control sc =3D { .gfp_mask =3D GFP_KERNEL, }; + unsigned long mem =3D shrinker->count_objects(shrinker, &sc); + + if (!mem || mem =3D=3D SHRINK_STOP || mem =3D=3D SHRINK_EMPTY) + continue; + + for (i =3D 0; i < nr; i++) + if (mem < shrinkers_by_mem[i].mem) + break; + + if (nr < ARRAY_SIZE(shrinkers_by_mem)) { + memmove(&shrinkers_by_mem[i + 1], + &shrinkers_by_mem[i], + sizeof(shrinkers_by_mem[0]) * (nr - i)); + nr++; + } else if (i) { + i--; + memmove(&shrinkers_by_mem[0], + &shrinkers_by_mem[1], + sizeof(shrinkers_by_mem[0]) * i); + } else { + continue; + } + + shrinkers_by_mem[i] =3D (struct shrinker_by_mem) { + .shrinker =3D shrinker, + .mem =3D mem, + }; + } + + for (i =3D nr - 1; i >=3D 0; --i) { + struct shrink_control sc =3D { .gfp_mask =3D GFP_KERNEL, }; + shrinker =3D shrinkers_by_mem[i].shrinker; + + if (shrinker->name[0]) + pr_buf(out, "%s", shrinker->name); + else + pr_buf(out, "%ps:", shrinker->scan_objects); + + pr_buf(out, " objects: %lu", shrinker->count_objects(shrinker, &sc)); + pr_newline(out); + + if (shrinker->to_text) { + pr_indent_push(out, 2); + shrinker->to_text(out, shrinker); + pr_indent_pop(out, 2); + pr_newline(out); + } + } + + up_read(&shrinker_rwsem); +} + #define SHRINK_BATCH 128 =20 static unsigned long do_shrink_slab(struct shrink_control *shrinkctl, --=20 2.35.2 From nobody Mon May 11 00:45:17 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 99501C433EF for ; Tue, 19 Apr 2022 20:32:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1357654AbiDSUfJ (ORCPT ); Tue, 19 Apr 2022 16:35:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53458 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1357656AbiDSUfA (ORCPT ); Tue, 19 Apr 2022 16:35:00 -0400 Received: from mail-qt1-x836.google.com (mail-qt1-x836.google.com [IPv6:2607:f8b0:4864:20::836]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7DD533C4AB; Tue, 19 Apr 2022 13:32:16 -0700 (PDT) Received: by mail-qt1-x836.google.com with SMTP id f22so3956965qtp.13; Tue, 19 Apr 2022 13:32:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hiSsrCjlwcoYpl0/USGlx4MhgXt3RiZFVish54MSnok=; b=hicipdWXgw6rsxF8UJHDR0KaJKoyeokPF5PWR6GaAgrllERYJYI/Jg9xtgvUJfkGvD eQ0Tn1RWY90G63yyb8TFRYK1YAyDoBqYZpHyMmkemad2g9WorHqYlLgIkxXqgDRyqSD3 JSI8HI1+65J/hvvAJjRj4sntggxxOZ35CeH1fwN12b0a+lmaR2pa08qEpc5yuHT97nwo rTDx3GGrEAOAeBvQJvS2x/TyS3N3gOKoY3aPUB5OcYIP/JzWx6GZP2evEsfvj0XwtP2r +AefnAe8wxhqx3vV9dqRsM92MSdMMBlq4LJeGesbsBBKRiRmTUekFCOF0vT4/ZK760CM apfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hiSsrCjlwcoYpl0/USGlx4MhgXt3RiZFVish54MSnok=; b=LzVnHLup+BREdCziZw1m6Zu//XcNS5lNP9MIrN5BXgfC252lI8e+P8sEgVFO+4gQNC Z8pA9Y1ENXKBdinou/e+cBPDX+aVNGPxZb8vg170gHqgz5vQwIuGJOXMxkNMgiRdZazV QrPZfMPuZSSGNoiPVQbMoHhdfomFNkat+Zy0PE8V6ClpEiGeDa2cqZ57Gi3MfgfFRyI7 iISek3PT+WnuQUC0R96KO4zDukM3fh0VhzDJ8/LnU724xOa/XtwWw5d8IUIIT/i1aR+/ djBcWt2mixDCMdMNEE1mDuYDGH9+8zU/tDdkg9+27D6DOtiJdren4PfFqp1WK+JDKUUP WZJA== X-Gm-Message-State: AOAM531Xp9MdrMdKbahLRAY/5IQMf6TS6i2iFckTNR6ZzMhm67rPUDwI DzzJnM1lLMHTSKH/OKcZAKCbDvR+gofB X-Google-Smtp-Source: ABdhPJygPQpglSpvnfxt1BNztNSw+CtWlN8E1Jml72FeiMubEvfSdNMiyDAjGy1m+t6bYuttfHO2lA== X-Received: by 2002:ac8:5a16:0:b0:2e1:ea00:b4e1 with SMTP id n22-20020ac85a16000000b002e1ea00b4e1mr11595006qta.329.1650400335194; Tue, 19 Apr 2022 13:32:15 -0700 (PDT) Received: from moria.home.lan (c-73-219-103-14.hsd1.vt.comcast.net. [73.219.103.14]) by smtp.gmail.com with ESMTPSA id e9-20020ac84e49000000b002f1fcda1ac7sm611180qtw.82.2022.04.19.13.32.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Apr 2022 13:32:14 -0700 (PDT) From: Kent Overstreet To: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Cc: Kent Overstreet , roman.gushchin@linux.dev, hannes@cmpxchg.org Subject: [PATCH 3/4] mm: Centralize & improve oom reporting in show_mem.c Date: Tue, 19 Apr 2022 16:32:01 -0400 Message-Id: <20220419203202.2670193-4-kent.overstreet@gmail.com> X-Mailer: git-send-email 2.35.2 In-Reply-To: <20220419203202.2670193-1-kent.overstreet@gmail.com> References: <20220419203202.2670193-1-kent.overstreet@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This patch: - Moves lib/show_mem.c to mm/show_mem.c - Changes show_mem() to always report on slab usage - Instead of reporting on all slabs, we only report on top 10 slabs, and in sorted order - Also reports on shrinkers, with the new shrinkers_to_text(). More OOM reporting can be moved to show_mem.c and improved, this patch is only a small start. Signed-off-by: Kent Overstreet --- lib/Makefile | 2 +- mm/Makefile | 2 +- mm/oom_kill.c | 23 ------------------ {lib =3D> mm}/show_mem.c | 14 +++++++++++ mm/slab.h | 6 +++-- mm/slab_common.c | 53 +++++++++++++++++++++++++++++++++++------- 6 files changed, 65 insertions(+), 35 deletions(-) rename {lib =3D> mm}/show_mem.c (78%) diff --git a/lib/Makefile b/lib/Makefile index 31a3904eda..c5041d33d0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -30,7 +30,7 @@ endif lib-y :=3D ctype.o string.o vsprintf.o cmdline.o \ rbtree.o radix-tree.o timerqueue.o xarray.o \ idr.o extable.o sha1.o irq_regs.o argv_split.o \ - flex_proportions.o ratelimit.o show_mem.o \ + flex_proportions.o ratelimit.o \ is_single_threaded.o plist.o decompress.o kobject_uevent.o \ earlycpio.o seq_buf.o siphash.o dec_and_lock.o \ nmi_backtrace.o nodemask.o win_minmax.o memcat_p.o \ diff --git a/mm/Makefile b/mm/Makefile index 70d4309c9c..97c0be12f3 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -54,7 +54,7 @@ obj-y :=3D filemap.o mempool.o oom_kill.o fadvise.o \ mm_init.o percpu.o slab_common.o \ compaction.o vmacache.o \ interval_tree.o list_lru.o workingset.o \ - debug.o gup.o mmap_lock.o $(mmu-y) + debug.o gup.o mmap_lock.o show_mem.o $(mmu-y) =20 # Give 'page_alloc' its own module-parameter namespace page-alloc-y :=3D page_alloc.o diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 832fb33037..659c7d6376 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -171,27 +171,6 @@ static bool oom_unkillable_task(struct task_struct *p) return false; } =20 -/* - * Check whether unreclaimable slab amount is greater than - * all user memory(LRU pages). - * dump_unreclaimable_slab() could help in the case that - * oom due to too much unreclaimable slab used by kernel. -*/ -static bool should_dump_unreclaim_slab(void) -{ - unsigned long nr_lru; - - nr_lru =3D global_node_page_state(NR_ACTIVE_ANON) + - global_node_page_state(NR_INACTIVE_ANON) + - global_node_page_state(NR_ACTIVE_FILE) + - global_node_page_state(NR_INACTIVE_FILE) + - global_node_page_state(NR_ISOLATED_ANON) + - global_node_page_state(NR_ISOLATED_FILE) + - global_node_page_state(NR_UNEVICTABLE); - - return (global_node_page_state_pages(NR_SLAB_UNRECLAIMABLE_B) > nr_lru); -} - /** * oom_badness - heuristic function to determine which candidate task to k= ill * @p: task struct of which task we should calculate @@ -465,8 +444,6 @@ static void dump_header(struct oom_control *oc, struct = task_struct *p) mem_cgroup_print_oom_meminfo(oc->memcg); else { show_mem(SHOW_MEM_FILTER_NODES, oc->nodemask); - if (should_dump_unreclaim_slab()) - dump_unreclaimable_slab(); } if (sysctl_oom_dump_tasks) dump_tasks(oc); diff --git a/lib/show_mem.c b/mm/show_mem.c similarity index 78% rename from lib/show_mem.c rename to mm/show_mem.c index 1c26c14ffb..c9f37f13d6 100644 --- a/lib/show_mem.c +++ b/mm/show_mem.c @@ -7,11 +7,15 @@ =20 #include #include +#include + +#include "slab.h" =20 void show_mem(unsigned int filter, nodemask_t *nodemask) { pg_data_t *pgdat; unsigned long total =3D 0, reserved =3D 0, highmem =3D 0; + struct printbuf buf =3D PRINTBUF; =20 printk("Mem-Info:\n"); show_free_areas(filter, nodemask); @@ -41,4 +45,14 @@ void show_mem(unsigned int filter, nodemask_t *nodemask) #ifdef CONFIG_MEMORY_FAILURE printk("%lu pages hwpoisoned\n", atomic_long_read(&num_poisoned_pages)); #endif + + pr_info("Unreclaimable slab info:\n"); + dump_unreclaimable_slab(&buf); + printk("%s", buf.buf); + printbuf_reset(&buf); + + printk("Shrinkers:\n"); + shrinkers_to_text(&buf); + printk("%s", buf.buf); + printbuf_exit(&buf); } diff --git a/mm/slab.h b/mm/slab.h index c7f2abc2b1..abefbf7674 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -788,10 +788,12 @@ static inline struct kmem_cache_node *get_node(struct= kmem_cache *s, int node) =20 #endif =20 +struct printbuf; + #if defined(CONFIG_SLAB) || defined(CONFIG_SLUB_DEBUG) -void dump_unreclaimable_slab(void); +void dump_unreclaimable_slab(struct printbuf *); #else -static inline void dump_unreclaimable_slab(void) +static inline void dump_unreclaimable_slab(struct printbuf *out) { } #endif diff --git a/mm/slab_common.c b/mm/slab_common.c index 23f2ab0713..cb1c548c73 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -24,6 +24,7 @@ #include #include #include +#include =20 #define CREATE_TRACE_POINTS #include @@ -1084,10 +1085,15 @@ static int slab_show(struct seq_file *m, void *p) return 0; } =20 -void dump_unreclaimable_slab(void) +void dump_unreclaimable_slab(struct printbuf *out) { struct kmem_cache *s; struct slabinfo sinfo; + struct slab_by_mem { + struct kmem_cache *s; + size_t total, active; + } slabs_by_mem[10], n; + int i, nr =3D 0; =20 /* * Here acquiring slab_mutex is risky since we don't prefer to get @@ -1097,12 +1103,11 @@ void dump_unreclaimable_slab(void) * without acquiring the mutex. */ if (!mutex_trylock(&slab_mutex)) { - pr_warn("excessive unreclaimable slab but cannot dump stats\n"); + pr_buf(out, "excessive unreclaimable slab but cannot dump stats\n"); return; } =20 - pr_info("Unreclaimable slab info:\n"); - pr_info("Name Used Total\n"); + buf->atomic++; =20 list_for_each_entry(s, &slab_caches, list) { if (s->flags & SLAB_RECLAIM_ACCOUNT) @@ -1110,11 +1115,43 @@ void dump_unreclaimable_slab(void) =20 get_slabinfo(s, &sinfo); =20 - if (sinfo.num_objs > 0) - pr_info("%-17s %10luKB %10luKB\n", s->name, - (sinfo.active_objs * s->size) / 1024, - (sinfo.num_objs * s->size) / 1024); + if (!sinfo.num_objs) + continue; + + n.s =3D s; + n.total =3D sinfo.num_objs * s->size; + n.active =3D sinfo.active_objs * s->size; + + for (i =3D 0; i < nr; i++) + if (n.total < slabs_by_mem[i].total) + break; + + if (nr < ARRAY_SIZE(slabs_by_mem)) { + memmove(&slabs_by_mem[i + 1], + &slabs_by_mem[i], + sizeof(slabs_by_mem[0]) * (nr - i)); + nr++; + } else if (i) { + i--; + memmove(&slabs_by_mem[0], + &slabs_by_mem[1], + sizeof(slabs_by_mem[0]) * i); + } else { + continue; + } + + slabs_by_mem[i] =3D n; + } + + for (i =3D nr - 1; i >=3D 0; --i) { + pr_buf(out, "%-17s total: ", slabs_by_mem[i].s->name); + pr_human_readable_u64(out, slabs_by_mem[i].total); + pr_buf(out, " active: "); + pr_human_readable_u64(out, slabs_by_mem[i].active); + pr_newline(out); } + + --buf->atomic; mutex_unlock(&slab_mutex); } =20 --=20 2.35.2 From nobody Mon May 11 00:45:17 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 20645C433EF for ; Tue, 19 Apr 2022 20:32:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1357313AbiDSUfP (ORCPT ); Tue, 19 Apr 2022 16:35:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53468 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346295AbiDSUfB (ORCPT ); Tue, 19 Apr 2022 16:35:01 -0400 Received: from mail-qk1-x736.google.com (mail-qk1-x736.google.com [IPv6:2607:f8b0:4864:20::736]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C10EA3C712; Tue, 19 Apr 2022 13:32:17 -0700 (PDT) Received: by mail-qk1-x736.google.com with SMTP id d19so6594581qko.3; Tue, 19 Apr 2022 13:32:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=OJODyF/ajH9xOJK+4CIgokrEBufAgT0uT/ipe+iH5NU=; b=QAsHvwzDiVLVrGcU+9jbXMpQHWpDKdMfj3bnaE6Fu/OB+mJ3UTI2COzzBz8F3B8PDY QR/HlbQYkvX1wLqTHtrj09BO5gbHxfopW1/9ErRgVdLGBXmwB2vh783JIEf1zL6y8m+1 gOyPOGYrhW7b1BfPzQGL9EWo3jr7z4k0QgYVP2/c2gSoJpNHts8tIk6Y+KfQW/pB83A9 g6G7mq+Ri4BnZ0etWfdnCF6WkxD2F/lCKxbTpcoRuig61gE97c4evJaj8ypBbSFuTLw/ kkfwBHq79jHa+vLZ4y9nTlceUZJ9SRnkNEyvY/hJNAx/aS7t2tOy0ZcRWyCVKI+ZBv16 9bzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=OJODyF/ajH9xOJK+4CIgokrEBufAgT0uT/ipe+iH5NU=; b=SGsGv0hsKQxs9OanlhnFHz4gJuIU2dVsKjbXpRjngA8XgDhTPXxwT68SEzswIOZVKE Dl+MNWoREFH9plFoPejlPOmi21W0FP5Ijg4K5hZ/cT0muTibqnQnyFRZPOh4CbKe2ZtI zNSCSUlSlqo1yJ5k4OYr951qESxEzrrvmfipTVscaeHmL/EKp8oHcRPkrW396i13WMEt yN6QCemunGgYujfu2LiQpFLC6gOVh2y8G9i++/73N/Ist1Y1IaRVqrPx7wyy7IoXI5OW LJSICkXjcBSF6Zsu6I2DEETwiFx9Huq6wgwisJVBEjBclGQFer34mKMzF29uXHVTUxJ9 ylBQ== X-Gm-Message-State: AOAM5302GdNpacyOHHV2jMRIIdewkluixUE/PAcUmX6fNpYU6e00BH8i COmE9DRCru05FAGIgpa3mFFmbqVKjkGO X-Google-Smtp-Source: ABdhPJwglihygmVaHV5xfkCJRJUfFCN+9TSdbuDle94mmw3wMqPZlOg/eMDWhy7vp1WF0tcR+c+hZg== X-Received: by 2002:a05:620a:4711:b0:67e:6c24:2b2b with SMTP id bs17-20020a05620a471100b0067e6c242b2bmr10987093qkb.588.1650400336592; Tue, 19 Apr 2022 13:32:16 -0700 (PDT) Received: from moria.home.lan (c-73-219-103-14.hsd1.vt.comcast.net. [73.219.103.14]) by smtp.gmail.com with ESMTPSA id e9-20020ac84e49000000b002f1fcda1ac7sm611180qtw.82.2022.04.19.13.32.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Apr 2022 13:32:15 -0700 (PDT) From: Kent Overstreet To: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Cc: Kent Overstreet , roman.gushchin@linux.dev Subject: [PATCH 4/4] bcachefs: shrinker.to_text() methods Date: Tue, 19 Apr 2022 16:32:02 -0400 Message-Id: <20220419203202.2670193-5-kent.overstreet@gmail.com> X-Mailer: git-send-email 2.35.2 In-Reply-To: <20220419203202.2670193-1-kent.overstreet@gmail.com> References: <20220419203202.2670193-1-kent.overstreet@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_cache.c | 18 +++++++++++++++--- fs/bcachefs/btree_key_cache.c | 18 +++++++++++++++--- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c index 72f0587e4d..75ef3b5462 100644 --- a/fs/bcachefs/btree_cache.c +++ b/fs/bcachefs/btree_cache.c @@ -394,6 +394,14 @@ static unsigned long bch2_btree_cache_count(struct shr= inker *shrink, return btree_cache_can_free(bc); } =20 +static void bch2_btree_cache_shrinker_to_text(struct printbuf *out, struct= shrinker *shrink) +{ + struct bch_fs *c =3D container_of(shrink, struct bch_fs, + btree_cache.shrink); + + bch2_btree_cache_to_text(out, c); +} + void bch2_fs_btree_cache_exit(struct bch_fs *c) { struct btree_cache *bc =3D &c->btree_cache; @@ -477,6 +485,7 @@ int bch2_fs_btree_cache_init(struct bch_fs *c) =20 bc->shrink.count_objects =3D bch2_btree_cache_count; bc->shrink.scan_objects =3D bch2_btree_cache_scan; + bc->shrink.to_text =3D bch2_btree_cache_shrinker_to_text; bc->shrink.seeks =3D 4; ret =3D register_shrinker(&bc->shrink); out: @@ -1147,7 +1156,10 @@ void bch2_btree_node_to_text(struct printbuf *out, s= truct bch_fs *c, =20 void bch2_btree_cache_to_text(struct printbuf *out, struct bch_fs *c) { - pr_buf(out, "nr nodes:\t\t%u\n", c->btree_cache.used); - pr_buf(out, "nr dirty:\t\t%u\n", atomic_read(&c->btree_cache.dirty)); - pr_buf(out, "cannibalize lock:\t%p\n", c->btree_cache.alloc_lock); + pr_buf(out, "nr nodes: %u", c->btree_cache.used); + pr_newline(out); + pr_buf(out, "nr dirty: %u", atomic_read(&c->btree_cache.dirty)); + pr_newline(out); + pr_buf(out, "cannibalize lock: %p", c->btree_cache.alloc_lock); + pr_newline(out); } diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c index a575189f35..32b5cb6042 100644 --- a/fs/bcachefs/btree_key_cache.c +++ b/fs/bcachefs/btree_key_cache.c @@ -711,6 +711,14 @@ void bch2_fs_btree_key_cache_init_early(struct btree_k= ey_cache *c) INIT_LIST_HEAD(&c->freed); } =20 +static void bch2_btree_key_cache_shrinker_to_text(struct printbuf *out, st= ruct shrinker *shrink) +{ + struct btree_key_cache *bc =3D + container_of(shrink, struct btree_key_cache, shrink); + + bch2_btree_key_cache_to_text(out, bc); +} + int bch2_fs_btree_key_cache_init(struct btree_key_cache *c) { int ret; @@ -724,14 +732,18 @@ int bch2_fs_btree_key_cache_init(struct btree_key_cac= he *c) c->shrink.seeks =3D 1; c->shrink.count_objects =3D bch2_btree_key_cache_count; c->shrink.scan_objects =3D bch2_btree_key_cache_scan; + c->shrink.to_text =3D bch2_btree_key_cache_shrinker_to_text; return register_shrinker(&c->shrink); } =20 void bch2_btree_key_cache_to_text(struct printbuf *out, struct btree_key_c= ache *c) { - pr_buf(out, "nr_freed:\t%zu\n", c->nr_freed); - pr_buf(out, "nr_keys:\t%lu\n", atomic_long_read(&c->nr_keys)); - pr_buf(out, "nr_dirty:\t%lu\n", atomic_long_read(&c->nr_dirty)); + pr_buf(out, "nr_freed: %zu", c->nr_freed); + pr_newline(out); + pr_buf(out, "nr_keys: %zu", atomic_long_read(&c->nr_keys)); + pr_newline(out); + pr_buf(out, "nr_dirty: %zu", atomic_long_read(&c->nr_dirty)); + pr_newline(out); } =20 void bch2_btree_key_cache_exit(void) --=20 2.35.2