From patchwork Thu Apr 21 23:48:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Overstreet X-Patchwork-Id: 12822566 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4A047C433FE for ; Thu, 21 Apr 2022 23:48:47 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id D530F6B0074; Thu, 21 Apr 2022 19:48:46 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id CDC888D0001; Thu, 21 Apr 2022 19:48:46 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id B077A6B0078; Thu, 21 Apr 2022 19:48:46 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (relay.hostedemail.com [64.99.140.27]) by kanga.kvack.org (Postfix) with ESMTP id 997306B0074 for ; Thu, 21 Apr 2022 19:48:46 -0400 (EDT) Received: from smtpin23.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 6BC59602B6 for ; Thu, 21 Apr 2022 23:48:46 +0000 (UTC) X-FDA: 79382528652.23.0A7C740 Received: from mail-qk1-f181.google.com (mail-qk1-f181.google.com [209.85.222.181]) by imf20.hostedemail.com (Postfix) with ESMTP id DCA741C002A for ; Thu, 21 Apr 2022 23:48:44 +0000 (UTC) Received: by mail-qk1-f181.google.com with SMTP id s70so4755807qke.8 for ; Thu, 21 Apr 2022 16:48:45 -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=HnKbyKSoxnnhHUla82G+r44n6xKnHl/lyquu70quAWvEGruswnnMwJVrbtkYeWAGaS lXo1884Mu/n97iJ5ppuIoGSLA8Lx2yq8g4SA61iceqgIE/uHZpYDgZDSz44jhm7qc/V0 UMi0uQQXaUtdJaDEe+CLU/x/ngyaAt9yZE8HV7bunAF9d31kUd56empFtZ65SGbFffQQ cEUUcOKXjlXbcACC94P3DYR9nqm7TTBMtqDCwd3mP1ie2bpBDiyHWVvK62IpDcIKlNz+ oCX42OTFko8ueeliHHMPuv7eQRpipnDUrdp1mqmh002tbmlWAv4QLX2SmxYkOpaCSUhP y+bA== 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=DeobDYFun2D89FplHvt6Y0GemG2aFN/6Ejs9w8DUaRu3sgbHHnNF2n/4vxXPJU2m4b zvKwPkS/M9aKg1toWbaydvpZ9s9xR8PCgFktBxRcD4wy9VwRRanR3621ba4uAb5ZZ+5v m/ehZSqJA/rxWRjeMp9Pjyw7e0SdAHrAPv6KX+lMN/M4oLw7dAHMVURaxtc8TPJN30sT 8wARjqH1Q7Vo7Vc6AApx2QbIKRumE7QUXXF6IUwK4GXlS8ZtAf6c/5dlRSdHrdzC6wPI sKa2vACuzIBOvqiyfv4p5kHNYcvC8UPZ9VbsYwcGZHE4rwHC7kDFwWfRsUYTUwz2Z/bu daWA== X-Gm-Message-State: AOAM533i8lyN1aHq5EJii7lGoAetTKBam+N+7ljfQ4fxQPrdJ35CgtlR wSQUNjAuNTkwzI/HK1xAwA== X-Google-Smtp-Source: ABdhPJwCLQbUskjoObbtdir9+Ze+XkJzhwquJQAmJ0+tc6epSJ7UNq8IznwqjL85GmEsdyt0hu3l0g== X-Received: by 2002:a05:620a:d8d:b0:67b:e95:2975 with SMTP id q13-20020a05620a0d8d00b0067b0e952975mr1193551qkl.115.1650584925172; Thu, 21 Apr 2022 16:48:45 -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 a1-20020a05622a02c100b002f342ccc1c5sm287372qtx.72.2022.04.21.16.48.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Apr 2022 16:48:44 -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: Thu, 21 Apr 2022 19:48:25 -0400 Message-Id: <20220421234837.3629927-2-kent.overstreet@gmail.com> X-Mailer: git-send-email 2.35.2 In-Reply-To: <20220421234837.3629927-1-kent.overstreet@gmail.com> References: <20220421234837.3629927-1-kent.overstreet@gmail.com> MIME-Version: 1.0 Authentication-Results: imf20.hostedemail.com; dkim=pass header.d=gmail.com header.s=20210112 header.b=HnKbyKSo; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf20.hostedemail.com: domain of kent.overstreet@gmail.com designates 209.85.222.181 as permitted sender) smtp.mailfrom=kent.overstreet@gmail.com X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: DCA741C002A X-Stat-Signature: 74qqzt8bwqpge8rat8meanqbwoqrw91e X-HE-Tag: 1650584924-771543 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: 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 structered + * formatting. + * + * This code has provisions for use in userspace, to aid in making other code + * portable between kernelspace and userspace. + * + * Basic example: + * + * struct printbuf buf = PRINTBUF; + * + * pr_buf(&buf, "foo="); + * 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 allocations + * 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 does 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 tabstop. + * 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 indent + * level and tabstops to work corretly. + * + * Output units: printbuf->units exists to tell pretty-printers how to output + * 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 human + * 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 names 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 = 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 = 0; + buf->last_newline = 0; + buf->last_field = 0; + buf->indent = 0; + buf->tabstop = 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 := 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 lib-$(CONFIG_PRINTK) += dump_stack.o lib-$(CONFIG_SMP) += 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 = roundup_pow_of_two(out->size + extra); + buf = krealloc(out->buf, new_size, !out->atomic ? GFP_KERNEL : GFP_ATOMIC); + + if (!buf) { + out->allocation_failure = true; + return -ENOMEM; + } + + out->buf = buf; + out->size = new_size; + return 0; +} + +void pr_buf(struct printbuf *out, const char *fmt, ...) +{ + va_list args; + int len; + + do { + va_start(args, fmt); + len = vsnprintf(out->buf + out->pos, printbuf_remaining(out), fmt, args); + va_end(args); + } while (len + 1 >= printbuf_remaining(out) && + !printbuf_realloc(out, len + 1)); + + len = min_t(size_t, len, + printbuf_remaining(out) ? printbuf_remaining(out) - 1 : 0); + out->pos += len; +} +EXPORT_SYMBOL(pr_buf); + +void pr_char(struct printbuf *buf, char c) +{ + if (!printbuf_realloc(buf, 1)) { + buf->buf[buf->pos++] = c; + buf->buf[buf->pos] = 0; + } +} +EXPORT_SYMBOL(pr_char); + +void pr_newline(struct printbuf *buf) +{ + unsigned i; + + pr_char(buf, '\n'); + + buf->last_newline = buf->pos; + + for (i = 0; i < buf->indent; i++) + pr_char(buf, ' '); + + buf->last_field = buf->pos; + buf->tabstop = 0; +} +EXPORT_SYMBOL(pr_newline); + +void pr_indent_push(struct printbuf *buf, unsigned spaces) +{ + buf->indent += 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 == buf->pos) { + buf->pos -= spaces; + buf->buf[buf->pos] = 0; + } + buf->indent -= 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 = 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 = buf->pos - buf->last_field; + unsigned shift = buf->tabstops[buf->tabstop] - + printbuf_linelen(buf); + + printbuf_realloc(buf, shift); + + if (buf->last_field + shift + 1 < buf->size) { + move = 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 += shift; + buf->buf[buf->pos] = 0; + } + } + + buf->last_field = buf->pos; + buf->tabstop++; +} +EXPORT_SYMBOL(pr_tab_rjust); + +static const char si_units[] = "?kMGTPEZY"; + +void pr_human_readable_u64(struct printbuf *buf, u64 v) +{ + int u, t = 0; + + for (u = 0; v >= 1024; u++) { + t = v & ~(~0U << 10); + v >>= 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 = _time; + struct tm *tm = localtime(&time); + size_t err = 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 = 0; list[i]; i++) + pr_buf(out, i == 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 = 0; + bool first = true; + + while (list[nr]) + nr++; + + while (flags && (bit = __ffs(flags)) < nr) { + if (!first) + pr_buf(out, ","); + first = false; + pr_buf(out, "%s", list[bit]); + flags ^= 1 << bit; + } +} +EXPORT_SYMBOL(pr_bitflags); From patchwork Thu Apr 21 23:48:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Overstreet X-Patchwork-Id: 12822567 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id E0B55C433F5 for ; Thu, 21 Apr 2022 23:48:48 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 7D5006B0075; Thu, 21 Apr 2022 19:48:48 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 70EA06B0078; Thu, 21 Apr 2022 19:48:48 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 4C4756B007B; Thu, 21 Apr 2022 19:48:48 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (relay.hostedemail.com [64.99.140.27]) by kanga.kvack.org (Postfix) with ESMTP id 3C2BB6B0075 for ; Thu, 21 Apr 2022 19:48:48 -0400 (EDT) Received: from smtpin21.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay12.hostedemail.com (Postfix) with ESMTP id DC5F112015D for ; Thu, 21 Apr 2022 23:48:47 +0000 (UTC) X-FDA: 79382528694.21.1AE2EC8 Received: from mail-qk1-f180.google.com (mail-qk1-f180.google.com [209.85.222.180]) by imf29.hostedemail.com (Postfix) with ESMTP id 3799F12001D for ; Thu, 21 Apr 2022 23:48:46 +0000 (UTC) Received: by mail-qk1-f180.google.com with SMTP id d198so4742587qkc.12 for ; Thu, 21 Apr 2022 16:48:47 -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=OOmnTYCAoQCRnBz8ZGchOn9i8U2hOeNPorJb87M3/pnKbf8r4wczk8AvZCUmTkG3mo xGWgYzNqWvYNey8z+NvJMhfgd1eg+nk1HGXrD25zDFPAUgk72Sa+LB7v6gfUO57Dvvme PUKAn+DVRz1g0IvpX6xC/IKenendQESOW7zlAWGHCNmpC2LVNI+AasWrGx5DlnqpEhuH GBs/HApRFPWfFJP9NkeR/a/P7ve/PSSxLMXaBDwU6FpPrKr9LlUltYvmFz5OWhNH5XKG T9QQFV9TmX/Y3Wc645Fpqp/Pqb4neHuqNYITdF61bPOzKiNfbMor6CQBRbRA0xBGNKNF hC3g== 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=sMCJ1W/3aamY/jDMibP4/rLeV3OJo1n8DKYOmLFTOSQ4dV51hdHcduWCFczmY73Cae LB5tuMGrkUq61EZFSxffbnYhXOPQ7MirCRIsHdBVA8SksKrrYSo2Q+/ge0J3z7/8Segw +6ggVkrlYygKZlllJrtcbcBJRzXA2SCAvF5bk7X9m31XMIX/s/14pFcs70meRdClnAVl luxjksPwkaTNc3DOIG2TKZxmMwI4any4YPquXjlQhFglNsLoN6bOM1Z4BfXVmtbrSZjx ZYFM0AAkIuRwFpspmU49Hu+6XQqHW1xT+bsNyKyJD8cUVighx1JrTN/yYoZ493bW5nGT lOhA== X-Gm-Message-State: AOAM532xIWUOWkL1FT8KkS8ACPaRx5Wk2132yF1d9mpsWR7htEmTdcBr cQX2a0iwaeVHhWYazB8GvA== X-Google-Smtp-Source: ABdhPJznB8ohPd49EoVGQUtsW/9dkOtNQzD1SuXVh4IxjthK+x2h94gl7xGMY9HG+LZtHfOVU1TYjw== X-Received: by 2002:a05:620a:4001:b0:69e:d9cf:d957 with SMTP id h1-20020a05620a400100b0069ed9cfd957mr1185369qko.678.1650584926675; Thu, 21 Apr 2022 16:48:46 -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 a1-20020a05622a02c100b002f342ccc1c5sm287372qtx.72.2022.04.21.16.48.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Apr 2022 16:48:46 -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: Thu, 21 Apr 2022 19:48:26 -0400 Message-Id: <20220421234837.3629927-3-kent.overstreet@gmail.com> X-Mailer: git-send-email 2.35.2 In-Reply-To: <20220421234837.3629927-1-kent.overstreet@gmail.com> References: <20220421234837.3629927-1-kent.overstreet@gmail.com> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: 3799F12001D X-Stat-Signature: 6srfod6r415xqpwuyxfdwunr9eeed38u Authentication-Results: imf29.hostedemail.com; dkim=pass header.d=gmail.com header.s=20210112 header.b=OOmnTYCA; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf29.hostedemail.com: domain of kent.overstreet@gmail.com designates 209.85.222.180 as permitted sender) smtp.mailfrom=kent.overstreet@gmail.com X-HE-Tag: 1650584926-654372 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: 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 +struct printbuf; + /* * This struct is used to pass information from page reclaim to the shrinkers. * 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 *); long batch; /* reclaim batch size, 0 = 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 #include #include @@ -702,6 +703,80 @@ void synchronize_shrinkers(void) } EXPORT_SYMBOL(synchronize_shrinkers); +/** + * 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 = 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 = { .gfp_mask = GFP_KERNEL, }; + unsigned long mem = shrinker->count_objects(shrinker, &sc); + + if (!mem || mem == SHRINK_STOP || mem == SHRINK_EMPTY) + continue; + + for (i = 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] = (struct shrinker_by_mem) { + .shrinker = shrinker, + .mem = mem, + }; + } + + for (i = nr - 1; i >= 0; --i) { + struct shrink_control sc = { .gfp_mask = GFP_KERNEL, }; + shrinker = 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 static unsigned long do_shrink_slab(struct shrink_control *shrinkctl, From patchwork Thu Apr 21 23:48:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Overstreet X-Patchwork-Id: 12822568 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF90CC433FE for ; Thu, 21 Apr 2022 23:48:50 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 452A46B0078; Thu, 21 Apr 2022 19:48:50 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 38CF86B007B; Thu, 21 Apr 2022 19:48:50 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 16A406B007D; Thu, 21 Apr 2022 19:48:49 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (relay.hostedemail.com [64.99.140.25]) by kanga.kvack.org (Postfix) with ESMTP id DBB9D6B0078 for ; Thu, 21 Apr 2022 19:48:49 -0400 (EDT) Received: from smtpin21.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id A4368602BA for ; Thu, 21 Apr 2022 23:48:49 +0000 (UTC) X-FDA: 79382528778.21.F749AE6 Received: from mail-qk1-f179.google.com (mail-qk1-f179.google.com [209.85.222.179]) by imf21.hostedemail.com (Postfix) with ESMTP id 934621C002B for ; Thu, 21 Apr 2022 23:48:47 +0000 (UTC) Received: by mail-qk1-f179.google.com with SMTP id j9so4771041qkg.1 for ; Thu, 21 Apr 2022 16:48:48 -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=RhU5SczM7MVxuNqxZsysmmyBQLNaVLb/iEEH6obfC/a+trx9CedfZtJBll0IWekfih tuXO0eYVjBPdozagT3PrGnVNP8+XjxRjuR9WLfymxj+0Xua835Q13Gw8Lpni5Io2OEmI b1bn/4zKQFkNEU3LLPoUKMFik3eBOJePUJ1x6G2jrK6itl1IAIa4rl7ySv4bP4evNGXT AErbwlrchxqc9UBwE2MEpLDhgcphNu5M1F4hviCtf/mrA9756zSZ5wseB6rbk2SwIL2t 6ukPAOCy90+zZIZfiWPuyhv9GPPVm9C3ICs5PJhv6LFGh3/qIz6/ZNt8Eq04DVVBw3OO nwKg== 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=62oqAJ4PSxJ3AymWXmVyEcVBwOOXFA9bBwvpX9ggHFoIpglnkjIENAVCXXwdHtbxR5 MxIOB2kBaojTr5/Irdt8ikPjSgX5ScvC2d5XnaSLwpckhlIrecvJPQ3HhdqbkSf0dxIF Yzaa+0ux0IvraLBt58ZgkWRRD0A1lLME4aTSuLYcE2C0SR9U5Lh0AyJm0Kbv+lkmqQwd SoS3vAhKgnib61aAPSA2CuF8dqpY0hJ6l4q7iU9BOMgVDXmaLdWEW2LPGrGqlDFQQ7y9 Y3saEAs5MKEeP5qpwTBed3afBiqpuQolYMDT8E16DLAZkwoLaUZ10xyOT0xdr8yiTAic whsg== X-Gm-Message-State: AOAM530mhnOagvsx7q/RqxF53P79iynbT1pezw2JB7mMoLq0Q+E7RJVt k6N0H+MiFCr7pSR0CV+t7aTkwtLdiv/F X-Google-Smtp-Source: ABdhPJzdKXxkO6fb4T06NqccHoQlgynEHMHYXfdQlfuIRpxfcMHi3GVv+ul+UsxLxNvOJg/4zsKRuA== X-Received: by 2002:a05:620a:4504:b0:69e:eb76:1d83 with SMTP id t4-20020a05620a450400b0069eeb761d83mr1211556qkp.92.1650584928386; Thu, 21 Apr 2022 16:48:48 -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 a1-20020a05622a02c100b002f342ccc1c5sm287372qtx.72.2022.04.21.16.48.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Apr 2022 16:48:47 -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: Thu, 21 Apr 2022 19:48:27 -0400 Message-Id: <20220421234837.3629927-4-kent.overstreet@gmail.com> X-Mailer: git-send-email 2.35.2 In-Reply-To: <20220421234837.3629927-1-kent.overstreet@gmail.com> References: <20220421234837.3629927-1-kent.overstreet@gmail.com> MIME-Version: 1.0 Authentication-Results: imf21.hostedemail.com; dkim=pass header.d=gmail.com header.s=20210112 header.b=RhU5SczM; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf21.hostedemail.com: domain of kent.overstreet@gmail.com designates 209.85.222.179 as permitted sender) smtp.mailfrom=kent.overstreet@gmail.com X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 934621C002B X-Stat-Signature: ak1d3zxt1sm3ka6ebdb5hebdiz3jrzi8 X-HE-Tag: 1650584927-500309 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: 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 => mm}/show_mem.c | 14 +++++++++++ mm/slab.h | 6 +++-- mm/slab_common.c | 53 +++++++++++++++++++++++++++++++++++------- 6 files changed, 65 insertions(+), 35 deletions(-) rename {lib => 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 := 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 := 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) # Give 'page_alloc' its own module-parameter namespace page-alloc-y := 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; } -/* - * 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 = 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 kill * @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 @@ #include #include +#include + +#include "slab.h" void show_mem(unsigned int filter, nodemask_t *nodemask) { pg_data_t *pgdat; unsigned long total = 0, reserved = 0, highmem = 0; + struct printbuf buf = PRINTBUF; 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) #endif +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 #define CREATE_TRACE_POINTS #include @@ -1084,10 +1085,15 @@ static int slab_show(struct seq_file *m, void *p) return 0; } -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 = 0; /* * 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; } - pr_info("Unreclaimable slab info:\n"); - pr_info("Name Used Total\n"); + buf->atomic++; list_for_each_entry(s, &slab_caches, list) { if (s->flags & SLAB_RECLAIM_ACCOUNT) @@ -1110,11 +1115,43 @@ void dump_unreclaimable_slab(void) get_slabinfo(s, &sinfo); - 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 = s; + n.total = sinfo.num_objs * s->size; + n.active = sinfo.active_objs * s->size; + + for (i = 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] = n; + } + + for (i = nr - 1; i >= 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); } From patchwork Thu Apr 21 23:48:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Overstreet X-Patchwork-Id: 12822569 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 41695C433EF for ; Thu, 21 Apr 2022 23:48:52 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 22F476B007B; Thu, 21 Apr 2022 19:48:51 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 1E10C6B007D; Thu, 21 Apr 2022 19:48:51 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 009016B007E; Thu, 21 Apr 2022 19:48:50 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (relay.a.hostedemail.com [64.99.140.24]) by kanga.kvack.org (Postfix) with ESMTP id E4EE96B007B for ; Thu, 21 Apr 2022 19:48:50 -0400 (EDT) Received: from smtpin16.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay12.hostedemail.com (Postfix) with ESMTP id B8CFC120132 for ; Thu, 21 Apr 2022 23:48:50 +0000 (UTC) X-FDA: 79382528820.16.C67F7E8 Received: from mail-qk1-f169.google.com (mail-qk1-f169.google.com [209.85.222.169]) by imf21.hostedemail.com (Postfix) with ESMTP id C94FC1C0024 for ; Thu, 21 Apr 2022 23:48:48 +0000 (UTC) Received: by mail-qk1-f169.google.com with SMTP id e128so4760910qkd.7 for ; Thu, 21 Apr 2022 16:48:50 -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=iMIgPJ5erku/7c7HhXsIctg1kxrza0LuvC2QEIAcGT7wBu0OauFCACWenk2xffUDR8 XvSO6KpoUrlwK8MsoRjIvhQGG3zVynFJa5Gw7Fnwvxb3RBVaVSIlGsbNQsUo5Ggj+g2m F3zt7/xN30ltoNSguXjheaeHJTLuicb+L99c5ETzfEAHShhj8+y7XTpzRhK1h/NwV1jP 1RdSjlkCUTKXhQ+pScjWL/hQfIrvKW6R9iBUMiwKnX/QQ4H696tdz7Sf3PD2st3851z7 hwHwA2cDiSaz5zzTGDVOXyaBFkRTNpPOx/O+/F4tLvIWQswTUThlV4CaqLNTB+5KykNb ovFQ== 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=nddjw3lCYw4CJd1F53YJq3vCVJh0H/fs05BjuSlEUT+IWjpr8HBqFyKoA4T6Pi7RKF 4Q7eUc/JOBCeEQm3H6Tm4cd3lWjOq19mruYxDK0iXt4GJ1CIhmR2E8m3JQiv/Qw/Nroe yktid9/ukaxuvNGj/D1hMVjpD9TyPo77c/EFTNi96bjoJxy8m468hqWT25eYSAGhQOn1 8/2byAKa3KMm2vDZbwDp7HCRXz+eGlarIa5BTRElEesyuur2YZM+/lOqr5/9/E6ADLRY F5cJutrBUhe1Kw+T6c9b7avTYDdmZvEtMuAvvCfTy/wfSJZ5IO5RI2COD2FesEEk55Br sqHg== X-Gm-Message-State: AOAM530i+ernEPS7yPq1mBDoPymbl1FKQhRUGmH54d+7PX9v+Yw4dnq3 FCWWju26Jtjq+Q0Z8GvdGDZ4aVPr0VKi X-Google-Smtp-Source: ABdhPJxI32XeTa41Ms2HZb8peaWuFEExEtNfe16DFYhZQ/thdpSwM/dy7gUZcuantPPXtVlOJX7YeA== X-Received: by 2002:a05:620a:4488:b0:69e:bf0f:42be with SMTP id x8-20020a05620a448800b0069ebf0f42bemr1112891qkp.663.1650584929641; Thu, 21 Apr 2022 16:48:49 -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 a1-20020a05622a02c100b002f342ccc1c5sm287372qtx.72.2022.04.21.16.48.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Apr 2022 16:48:49 -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: Thu, 21 Apr 2022 19:48:28 -0400 Message-Id: <20220421234837.3629927-5-kent.overstreet@gmail.com> X-Mailer: git-send-email 2.35.2 In-Reply-To: <20220421234837.3629927-1-kent.overstreet@gmail.com> References: <20220421234837.3629927-1-kent.overstreet@gmail.com> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: C94FC1C0024 X-Stat-Signature: x4ps47tqxh3jznyk8k8radg1gwki7heg Authentication-Results: imf21.hostedemail.com; dkim=pass header.d=gmail.com header.s=20210112 header.b=iMIgPJ5e; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf21.hostedemail.com: domain of kent.overstreet@gmail.com designates 209.85.222.169 as permitted sender) smtp.mailfrom=kent.overstreet@gmail.com X-HE-Tag: 1650584928-805271 X-Bogosity: Ham, tests=bogofilter, spamicity=0.013318, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: 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 shrinker *shrink, return btree_cache_can_free(bc); } +static void bch2_btree_cache_shrinker_to_text(struct printbuf *out, struct shrinker *shrink) +{ + struct bch_fs *c = 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 = &c->btree_cache; @@ -477,6 +485,7 @@ int bch2_fs_btree_cache_init(struct bch_fs *c) bc->shrink.count_objects = bch2_btree_cache_count; bc->shrink.scan_objects = bch2_btree_cache_scan; + bc->shrink.to_text = bch2_btree_cache_shrinker_to_text; bc->shrink.seeks = 4; ret = register_shrinker(&bc->shrink); out: @@ -1147,7 +1156,10 @@ void bch2_btree_node_to_text(struct printbuf *out, struct bch_fs *c, 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_key_cache *c) INIT_LIST_HEAD(&c->freed); } +static void bch2_btree_key_cache_shrinker_to_text(struct printbuf *out, struct shrinker *shrink) +{ + struct btree_key_cache *bc = + 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_cache *c) c->shrink.seeks = 1; c->shrink.count_objects = bch2_btree_key_cache_count; c->shrink.scan_objects = bch2_btree_key_cache_scan; + c->shrink.to_text = bch2_btree_key_cache_shrinker_to_text; return register_shrinker(&c->shrink); } void bch2_btree_key_cache_to_text(struct printbuf *out, struct btree_key_cache *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); } void bch2_btree_key_cache_exit(void) From patchwork Thu Apr 21 23:48:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Overstreet X-Patchwork-Id: 12822574 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id D3B7BC3527C for ; Thu, 21 Apr 2022 23:49:02 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 0CFEA6B0082; Thu, 21 Apr 2022 19:49:01 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id EFE566B0083; Thu, 21 Apr 2022 19:49:00 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D02698D0001; Thu, 21 Apr 2022 19:49:00 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (relay.a.hostedemail.com [64.99.140.24]) by kanga.kvack.org (Postfix) with ESMTP id B2B5E6B0082 for ; Thu, 21 Apr 2022 19:49:00 -0400 (EDT) Received: from smtpin21.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 8D218202A1 for ; Thu, 21 Apr 2022 23:49:00 +0000 (UTC) X-FDA: 79382529240.21.2F78093 Received: from mail-qv1-f53.google.com (mail-qv1-f53.google.com [209.85.219.53]) by imf02.hostedemail.com (Postfix) with ESMTP id B03628002A for ; Thu, 21 Apr 2022 23:48:58 +0000 (UTC) Received: by mail-qv1-f53.google.com with SMTP id b17so4860087qvp.6 for ; Thu, 21 Apr 2022 16:48:59 -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=gx/pEzK/Si3DJxK25M0+mRodztZR2hxnPp00eWVAa1k=; b=Md/LjYEF9f+pRuz8KZH8oR8ODzAl6LE1NdwDO9B7yhhTbHjC1XjY6StBiio3j2Nvo1 JelKkMUZhH6wK9SIieCBlHRjkPiXecMX7lbXfg/XqFWogYyaitQ4MdWK8BXZq7mkhu1O OFnyhM+ibntll36tPPZSueMUXCwouOzvP6eHH1utH55G/gzIVvvomUfh32hDdsmMbf5j ior9XaGlQzyXxpuadInYd2sY51uzIco7yCLiu8jNyncc1IUMQD2y1/lU0BMZz4BOsCG/ YfI4zjIBitflaOo7HONdKt45CVTiopIOyKsTTpjmD6y0c5WL8ulhg5/2E53m0J0N/wOI +Qdw== 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=gx/pEzK/Si3DJxK25M0+mRodztZR2hxnPp00eWVAa1k=; b=B7JToyvFHG0GG6akJ8PKgwA+28+EIvx7J7Xc4iDXNaWFApiF2G7KQxGGYHqMxaKGAL 1Vgb3h6Bw1oGzSlCklg3cuJmCv76gwCWxDdzL0I3HGunnevbJi65f26Y8wVfpZqyV/h1 x8l7iENca9TALfNKRoCWm326EKzgP2bg6m6o6S9jvKw1f0mqtTbN+tRxQFeobP5dfJKk InAFDv6uI+9T3bdCK2iy4WfGoMJMOZNfdxJEidr5AW6M24l0KUP2wQ8hCcZ3Pe+Ao0AJ OQ/XyngCfJ8OAw7Jkf4givnNiOVGvcUmeXs6lHeJQ+ImsJ3jTnB548Zw2LAdZM9OCv8c CPsw== X-Gm-Message-State: AOAM5323OJb6vyyrQRnSIzz0yvU6e44IIx1OEUHQVBVm22AyT5nJKrbG ty+0MLfeulz8VX+T9ymFfg== X-Google-Smtp-Source: ABdhPJy1nyPXDBoL0+vXyPBBH/+kX8pkeabBh3Ms+kkb3pWns3FlAR3mANJ7k+SatBCK1YhmRDDm8g== X-Received: by 2002:a05:6214:262c:b0:446:3464:57cd with SMTP id gv12-20020a056214262c00b00446346457cdmr1758402qvb.89.1650584939257; Thu, 21 Apr 2022 16:48:59 -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 a1-20020a05622a02c100b002f342ccc1c5sm287372qtx.72.2022.04.21.16.48.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Apr 2022 16:48:58 -0700 (PDT) From: Kent Overstreet To: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Cc: Kent Overstreet , hch@lst.de, hannes@cmpxchg.org, akpm@linux-foundation.org, linux-clk@vger.kernel.org, linux-tegra@vger.kernel.org, linux-input@vger.kernel.org, roman.gushchin@linux.dev Subject: [PATCH v2 5/8] mm: Add a .to_text() method for shrinkers Date: Thu, 21 Apr 2022 19:48:34 -0400 Message-Id: <20220421234837.3629927-11-kent.overstreet@gmail.com> X-Mailer: git-send-email 2.35.2 In-Reply-To: <20220421234837.3629927-1-kent.overstreet@gmail.com> References: <20220421234837.3629927-1-kent.overstreet@gmail.com> MIME-Version: 1.0 Authentication-Results: imf02.hostedemail.com; dkim=pass header.d=gmail.com header.s=20210112 header.b="Md/LjYEF"; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf02.hostedemail.com: domain of kent.overstreet@gmail.com designates 209.85.219.53 as permitted sender) smtp.mailfrom=kent.overstreet@gmail.com X-Rspam-User: X-Rspamd-Server: rspam08 X-Rspamd-Queue-Id: B03628002A X-Stat-Signature: oax8zr7c1f4emitpuuahsriy55zx4mcf X-HE-Tag: 1650584938-667401 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: 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 | 78 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 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 +struct printbuf; + /* * This struct is used to pass information from page reclaim to the shrinkers. * 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 *); long batch; /* reclaim batch size, 0 = 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..905bc23800 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -702,6 +703,83 @@ void synchronize_shrinkers(void) } EXPORT_SYMBOL(synchronize_shrinkers); +void shrinker_to_text(struct printbuf *out, struct shrinker *shrinker) +{ + struct shrink_control sc = { .gfp_mask = GFP_KERNEL, }; + + 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); + } +} + +/** + * 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 = 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 = { .gfp_mask = GFP_KERNEL, }; + unsigned long mem = shrinker->count_objects(shrinker, &sc); + + if (!mem || mem == SHRINK_STOP || mem == SHRINK_EMPTY) + continue; + + for (i = 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] = (struct shrinker_by_mem) { + .shrinker = shrinker, + .mem = mem, + }; + } + + for (i = nr - 1; i >= 0; --i) + shrinker_to_text(out, shrinkers_by_mem[i].shrinker); + + up_read(&shrinker_rwsem); +} + #define SHRINK_BATCH 128 static unsigned long do_shrink_slab(struct shrink_control *shrinkctl, From patchwork Thu Apr 21 23:48:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Overstreet X-Patchwork-Id: 12822575 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2A98C433FE for ; Thu, 21 Apr 2022 23:49:04 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 38ECA6B0083; Thu, 21 Apr 2022 19:49:02 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 315BE6B0085; Thu, 21 Apr 2022 19:49:02 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 16A028D0001; Thu, 21 Apr 2022 19:49:02 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (relay.hostedemail.com [64.99.140.26]) by kanga.kvack.org (Postfix) with ESMTP id F3CB66B0083 for ; Thu, 21 Apr 2022 19:49:01 -0400 (EDT) Received: from smtpin10.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id CD1042021E for ; Thu, 21 Apr 2022 23:49:01 +0000 (UTC) X-FDA: 79382529282.10.ECDBB20 Received: from mail-qv1-f48.google.com (mail-qv1-f48.google.com [209.85.219.48]) by imf29.hostedemail.com (Postfix) with ESMTP id 4A510120018 for ; Thu, 21 Apr 2022 23:49:00 +0000 (UTC) Received: by mail-qv1-f48.google.com with SMTP id e17so4860362qvj.11 for ; Thu, 21 Apr 2022 16:49:01 -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=FeM5bqJiQrm2rh3JILkdt+BZf3iQXt3DndJ5kJUH6VM=; b=n/KPNGWJXcs0GJJTYwzELGdDRU26YZeN+AFBdrfivcUmDTFgoEKIyrauqulst14dH0 VIawqwx2mO79s0OxciEEIzbn1FvG1bH8bG3uS1fw7LT5ALzrMm7yM+uw93vItLfT2nW0 6vW0ixWFbUjKGZzE54v1t/I3Bb56898l1K1XBAcQabLQzanStxI9UkxPRziU7gkhloaO BPYvgr1vJyyfoY4JXraylWH6PYW9y9v+u6E5dvL1U4gTfbVtPd5b01hz0ZuIgSBkAYal 2vHqlPuenxkKGGJ237DRh/3jonP/A8fdnfy/nV7yUnNdSgA4uOcGoslhIzZ4kevfjAKu LBBA== 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=FeM5bqJiQrm2rh3JILkdt+BZf3iQXt3DndJ5kJUH6VM=; b=knXEtoXNJghPQnRin04IuXoRYUwj0IsH0u+dQQmXgBRT2q/OHHZONCv8CzsiUCg9Qt 06vIIP2W9fc3TJDA+D+sNV1vGF+aJkc7dKpPkOop0r/wwIDx2i75Dez3az9Rd+OXTFc5 A9Dk6M9iBaBPRwUgaiaLIYbd68neTh6lC7xVYbmDJg287maEsqewzto3HLu8cAxhNmJS LGHdocLa4U5sA13sxIrzXlOhl5/tvOMp7W7uTvij5xdA/MiyMkFeO+vqP5l4Aes9X5tx aT2/7Sl4cDw6QbWx3cbVPbQ9OyogwR1I4IPcyrDjDlUnMuxm/knwDXx6aL0D1nXeSg2b FYvg== X-Gm-Message-State: AOAM532tNW3p6WkdR/e3kCAgQOIPL+5QFcQtMFPA8C37KT1GvDT5yft1 eBmOO6sSnnRP6n93RZrCUg== X-Google-Smtp-Source: ABdhPJwIwwSIi9BX9ueYR8W3xLzPDKzGU08fb3TSCEvxc7eNfeoVsUdKsvEsHwvgXeKxMCM8QFg4Jg== X-Received: by 2002:a05:6214:3006:b0:444:2fa9:9849 with SMTP id ke6-20020a056214300600b004442fa99849mr1462717qvb.101.1650584940771; Thu, 21 Apr 2022 16:49:00 -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 a1-20020a05622a02c100b002f342ccc1c5sm287372qtx.72.2022.04.21.16.48.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Apr 2022 16:49:00 -0700 (PDT) From: Kent Overstreet To: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Cc: Kent Overstreet , hch@lst.de, hannes@cmpxchg.org, akpm@linux-foundation.org, linux-clk@vger.kernel.org, linux-tegra@vger.kernel.org, linux-input@vger.kernel.org, roman.gushchin@linux.dev Subject: [PATCH v2 6/8] mm: Count requests to free & nr freed per shrinker Date: Thu, 21 Apr 2022 19:48:35 -0400 Message-Id: <20220421234837.3629927-12-kent.overstreet@gmail.com> X-Mailer: git-send-email 2.35.2 In-Reply-To: <20220421234837.3629927-1-kent.overstreet@gmail.com> References: <20220421234837.3629927-1-kent.overstreet@gmail.com> MIME-Version: 1.0 X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: 4A510120018 X-Stat-Signature: bzek71cmaq9zmdkyza1qbzh6dwjuiziq Authentication-Results: imf29.hostedemail.com; dkim=pass header.d=gmail.com header.s=20210112 header.b="n/KPNGWJ"; spf=pass (imf29.hostedemail.com: domain of kent.overstreet@gmail.com designates 209.85.219.48 as permitted sender) smtp.mailfrom=kent.overstreet@gmail.com; dmarc=pass (policy=none) header.from=gmail.com X-Rspam-User: X-HE-Tag: 1650584940-811425 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: The next step in this patch series for improving debugging of shrinker related issues: keep counts of number of objects we request to free vs. actually freed, and prints them in shrinker_to_text(). Shrinkers won't necessarily free all objects requested for a variety of reasons, but if the two counts are wildly different something is likely amiss. Signed-off-by: Kent Overstreet --- include/linux/shrinker.h | 3 +++ mm/vmscan.c | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h index b5f411768b..12967748f9 100644 --- a/include/linux/shrinker.h +++ b/include/linux/shrinker.h @@ -79,6 +79,9 @@ struct shrinker { #endif /* objs pending delete, per node */ atomic_long_t *nr_deferred; + + atomic_long_t objects_requested_to_free; + atomic_long_t objects_freed; }; #define DEFAULT_SEEKS 2 /* A good number if you don't know better. */ diff --git a/mm/vmscan.c b/mm/vmscan.c index 905bc23800..12562546a7 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -711,16 +711,22 @@ void shrinker_to_text(struct printbuf *out, struct shrinker *shrinker) pr_buf(out, "%s", shrinker->name); else pr_buf(out, "%ps:", shrinker->scan_objects); + pr_newline(out); + pr_indent_push(out, 2); - pr_buf(out, " objects: %lu", shrinker->count_objects(shrinker, &sc)); + pr_buf(out, "objects: %lu", shrinker->count_objects(shrinker, &sc)); + pr_newline(out); + pr_buf(out, "requested to free: %lu", atomic_long_read(&shrinker->objects_requested_to_free)); + pr_newline(out); + pr_buf(out, "objects freed: %lu", atomic_long_read(&shrinker->objects_freed)); 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); } + + pr_indent_pop(out, 2); } /** @@ -846,12 +852,16 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl, unsigned long ret; unsigned long nr_to_scan = min(batch_size, total_scan); + atomic_long_add(nr_to_scan, &shrinker->objects_requested_to_free); + shrinkctl->nr_to_scan = nr_to_scan; shrinkctl->nr_scanned = nr_to_scan; ret = shrinker->scan_objects(shrinker, shrinkctl); if (ret == SHRINK_STOP) break; + freed += ret; + atomic_long_add(ret, &shrinker->objects_freed); count_vm_events(SLABS_SCANNED, shrinkctl->nr_scanned); total_scan -= shrinkctl->nr_scanned; From patchwork Thu Apr 21 23:48:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Overstreet X-Patchwork-Id: 12822576 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05FABC433FE for ; Thu, 21 Apr 2022 23:49:07 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id DC7146B0085; Thu, 21 Apr 2022 19:49:03 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id D29808D0001; Thu, 21 Apr 2022 19:49:03 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id B05DC6B0088; Thu, 21 Apr 2022 19:49:03 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (relay.hostedemail.com [64.99.140.26]) by kanga.kvack.org (Postfix) with ESMTP id A09266B0085 for ; Thu, 21 Apr 2022 19:49:03 -0400 (EDT) Received: from smtpin16.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 6862A20738 for ; Thu, 21 Apr 2022 23:49:03 +0000 (UTC) X-FDA: 79382529366.16.F66099A Received: from mail-qk1-f175.google.com (mail-qk1-f175.google.com [209.85.222.175]) by imf05.hostedemail.com (Postfix) with ESMTP id 22AA510002C for ; Thu, 21 Apr 2022 23:48:59 +0000 (UTC) Received: by mail-qk1-f175.google.com with SMTP id s70so4756177qke.8 for ; Thu, 21 Apr 2022 16:49:02 -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=OX+ZZxfUCa6AeznhtMYBa3lbAYkGql05KEYmpApGJvc=; b=fWoFdNFoTzuTeyd37gJBh3UEJqZnL5c7olLDqlVchiUDB4EfzgpzArPgDksaoxFYSV lFcwfvuY2O4d+01Q5Zj7FApRfnsx10MrvqIQjieDrYqKS8oTMogkpDCLe6b+tIvGeoDg oZ25deodeMYYdcb4msCQZ95tNwqLOpZL1GqFWlCJbzyzHA0RXWkB1OWPmvNGxWqOFk0Z NMobe8u2+R7aXU1cBxhn6C/5a3nl/GRTkhDG3IY39MAnvrmCeWGVgd8OH0FEk9JXcTV+ sT/ZRPNX+2nh2YnvFSNMks5fpzsFDvBjYXVsugVKFszq5lRjdggcfrPmLI1vTlpoRedw R7eg== 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=OX+ZZxfUCa6AeznhtMYBa3lbAYkGql05KEYmpApGJvc=; b=GLPy2ZQqrMAcabJOJYn5+KpdbjLC/t1XIEAOS6Pyo6WrlU6d/VSh402WAtqUfcysJI Tb85QkD27Ndt/7gOUNnrR0ufZaugKEhww7aBjskRuWnEIcSqNzBIqHqL+XsjdYiu7Cud ov/e24om65wbVkE96Usvm5RBlNdwZrsufO7raUCwT9x2wjxqyIoOWJHbxbjv5S/mwVpK d9nYsIxQMqkjAwz7LeGBDbZocltPB5lgvHznorzyiSgJm2la5Hkxa2dkere3Qa4GlsSq NYvo84GFMJnDDzUOWEr2OZDKrwBZ96AQ8zXc8CH4e4hgUHwmPj/KD0iAOF5cxI4gAEs/ RYow== X-Gm-Message-State: AOAM533mig9ANq+X+NDREo7znmtOBMiOxbqHUjwJaYsLMaZvLUM6U+wJ mkkol358LVUaKjmCUJ0o8g== X-Google-Smtp-Source: ABdhPJy4AfRMSM5fE/ShUTn41jLAMSbQ5zXgowJp+WmfgN33q5UIkYcEB9ug5C7qJVU5PFjSL7Hzbg== X-Received: by 2002:a05:620a:2805:b0:67d:5c7e:c43a with SMTP id f5-20020a05620a280500b0067d5c7ec43amr1216746qkp.84.1650584942298; Thu, 21 Apr 2022 16:49:02 -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 a1-20020a05622a02c100b002f342ccc1c5sm287372qtx.72.2022.04.21.16.49.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Apr 2022 16:49:01 -0700 (PDT) From: Kent Overstreet To: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Cc: Kent Overstreet , hch@lst.de, hannes@cmpxchg.org, akpm@linux-foundation.org, linux-clk@vger.kernel.org, linux-tegra@vger.kernel.org, linux-input@vger.kernel.org, roman.gushchin@linux.dev Subject: [PATCH v2 7/8] mm: Move lib/show_mem.c to mm/ Date: Thu, 21 Apr 2022 19:48:36 -0400 Message-Id: <20220421234837.3629927-13-kent.overstreet@gmail.com> X-Mailer: git-send-email 2.35.2 In-Reply-To: <20220421234837.3629927-1-kent.overstreet@gmail.com> References: <20220421234837.3629927-1-kent.overstreet@gmail.com> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Queue-Id: 22AA510002C X-Stat-Signature: qyh6sjw5txms4jehjo5q5zmpsemnegdx Authentication-Results: imf05.hostedemail.com; dkim=pass header.d=gmail.com header.s=20210112 header.b=fWoFdNFo; spf=pass (imf05.hostedemail.com: domain of kent.overstreet@gmail.com designates 209.85.222.175 as permitted sender) smtp.mailfrom=kent.overstreet@gmail.com; dmarc=pass (policy=none) header.from=gmail.com X-Rspamd-Server: rspam01 X-HE-Tag: 1650584939-482615 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: show_mem.c is really mm specific, and the next patch in the series is going to require mm/slab.h, so let's move it before doing more work on it. Signed-off-by: Kent Overstreet Acked-by: Michal Hocko --- lib/Makefile | 2 +- mm/Makefile | 2 +- {lib => mm}/show_mem.c | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename {lib => mm}/show_mem.c (100%) 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 := 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 := 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) # Give 'page_alloc' its own module-parameter namespace page-alloc-y := page_alloc.o diff --git a/lib/show_mem.c b/mm/show_mem.c similarity index 100% rename from lib/show_mem.c rename to mm/show_mem.c From patchwork Thu Apr 21 23:48:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kent Overstreet X-Patchwork-Id: 12822577 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 46AFCC433FE for ; Thu, 21 Apr 2022 23:49:09 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 8E8726B0087; Thu, 21 Apr 2022 19:49:05 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 84AD66B0088; Thu, 21 Apr 2022 19:49:05 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 64EE86B0089; Thu, 21 Apr 2022 19:49:05 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (relay.hostedemail.com [64.99.140.28]) by kanga.kvack.org (Postfix) with ESMTP id 47B8E6B0087 for ; Thu, 21 Apr 2022 19:49:05 -0400 (EDT) Received: from smtpin08.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 17498226B9 for ; Thu, 21 Apr 2022 23:49:05 +0000 (UTC) X-FDA: 79382529450.08.D7C6AA7 Received: from mail-qk1-f177.google.com (mail-qk1-f177.google.com [209.85.222.177]) by imf24.hostedemail.com (Postfix) with ESMTP id D4F2F18002F for ; Thu, 21 Apr 2022 23:49:02 +0000 (UTC) Received: by mail-qk1-f177.google.com with SMTP id c1so4736334qkf.13 for ; Thu, 21 Apr 2022 16:49:04 -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=aaKcIjNjF3IwQgxs7vyEXb42UUHeDaL+RKW940GYuHE=; b=a0tjhmKMatzGt0SztAxbHSgi9tkuoq0b0Avq27VcC+kWC+951h6K4afxy78BlImIme 8hwewDxQUByXhjBpdf3GRogZFMXghbYddWPYGObWHaKwar6ZutgSnbKNT7F3FZLqk7wN iZppyKJc9qP3jlBDtQPTyi/5r/om31TNT0840qZqtz+vuCG6AlUZg0IcBuGtOpb3ubGg NNKJgJqrfumSUdnk3c04fo5WdiHypYP0u2zJ040DG42b0Ps/eBSB7PE57jCggeofy1rQ bctqg3CeHEwk/dvoUnReNkmfYLTGm+Cqm1k45E9NSblGTm2QEP4vBQwsNvO+VemICgy1 gcCQ== 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=aaKcIjNjF3IwQgxs7vyEXb42UUHeDaL+RKW940GYuHE=; b=D0Ic5Od1QA0EdhfympkO7/NseqewMfJrieRAwSbjQrnnuwTwbR4TBv9eYeJdBRs8Dk 33uRMKQIQOe8lnMnNVEkzYUKuCeFvbFVvhnzanbLBDLFHGPNsZkgzpa92zq2ZbCb/dP3 0dxxXeA+G2jf8fc/CRdUpB2F5GUTZ1vviQpb1TbD+47XNDdPkRP1V7PHeDiyyHygLDFY LXmymOm7xxSXAW3i8ixWmO5VMVe+OW9J8EDKTsjzhav6lOQ5DxcSDbbTblwQPymAciFH +wtOy7w+0Bw3VanDqMbnrQEHzBZ4mZEuzxPcD/25UEVx7t+PdYSMLRS0+/q3CdP1Wu5K Sg8g== X-Gm-Message-State: AOAM531CN2ndklwnohjZqu3GqrlgxyR5aB+Na7COZN7wUj/Jbc4oeiQP OxDYHftQ/8Wph4LkxBRT3A== X-Google-Smtp-Source: ABdhPJwtXpdd8XMsi8NfAgNi48EgWOzVYdEawLNA8H89/n1HqY3g/ULD/amWov5SbJzrqfz2xmZ8eQ== X-Received: by 2002:a05:620a:bd5:b0:67d:15ed:2fcd with SMTP id s21-20020a05620a0bd500b0067d15ed2fcdmr1185692qki.81.1650584943898; Thu, 21 Apr 2022 16:49:03 -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 a1-20020a05622a02c100b002f342ccc1c5sm287372qtx.72.2022.04.21.16.49.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Apr 2022 16:49:03 -0700 (PDT) From: Kent Overstreet To: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Cc: Kent Overstreet , hch@lst.de, hannes@cmpxchg.org, akpm@linux-foundation.org, linux-clk@vger.kernel.org, linux-tegra@vger.kernel.org, linux-input@vger.kernel.org, roman.gushchin@linux.dev Subject: [PATCH v2 8/8] mm: Centralize & improve oom reporting in show_mem.c Date: Thu, 21 Apr 2022 19:48:37 -0400 Message-Id: <20220421234837.3629927-14-kent.overstreet@gmail.com> X-Mailer: git-send-email 2.35.2 In-Reply-To: <20220421234837.3629927-1-kent.overstreet@gmail.com> References: <20220421234837.3629927-1-kent.overstreet@gmail.com> MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam11 X-Rspamd-Queue-Id: D4F2F18002F X-Stat-Signature: oixapiy74eton9g6nfc7ag7b7ioaz173 Authentication-Results: imf24.hostedemail.com; dkim=pass header.d=gmail.com header.s=20210112 header.b=a0tjhmKM; spf=pass (imf24.hostedemail.com: domain of kent.overstreet@gmail.com designates 209.85.222.177 as permitted sender) smtp.mailfrom=kent.overstreet@gmail.com; dmarc=pass (policy=none) header.from=gmail.com X-HE-Tag: 1650584942-116883 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: This patch: - 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(). Shrinkers need to be included in OOM/allocation failure reporting because they're responsible for memory reclaim - if a shrinker isn't giving up its memory, we need to know which one and why. More OOM reporting can be moved to show_mem.c and improved, this patch is only a start. New example output on OOM/memory allocation failure: 00177 Mem-Info: 00177 active_anon:13706 inactive_anon:32266 isolated_anon:16 00177 active_file:1653 inactive_file:1822 isolated_file:0 00177 unevictable:0 dirty:0 writeback:0 00177 slab_reclaimable:6242 slab_unreclaimable:11168 00177 mapped:3824 shmem:3 pagetables:1266 bounce:0 00177 kernel_misc_reclaimable:0 00177 free:4362 free_pcp:35 free_cma:0 00177 Node 0 active_anon:54824kB inactive_anon:129064kB active_file:6612kB inactive_file:7288kB unevictable:0kB isolated(anon):64kB isolated(file):0kB mapped:15296kB dirty:0kB writeback:0kB shmem:12kB writeback_tmp:0kB kernel_stack:3392kB pagetables:5064kB all_unreclaimable? no 00177 DMA free:2232kB boost:0kB min:88kB low:108kB high:128kB reserved_highatomic:0KB active_anon:2924kB inactive_anon:6596kB active_file:428kB inactive_file:384kB unevictable:0kB writepending:0kB present:15992kB managed:15360kB mlocked:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB 00177 lowmem_reserve[]: 0 426 426 426 00177 DMA32 free:15092kB boost:5836kB min:8432kB low:9080kB high:9728kB reserved_highatomic:0KB active_anon:52196kB inactive_anon:122392kB active_file:6176kB inactive_file:7068kB unevictable:0kB writepending:0kB present:507760kB managed:441816kB mlocked:0kB bounce:0kB free_pcp:72kB local_pcp:0kB free_cma:0kB 00177 lowmem_reserve[]: 0 0 0 0 00177 DMA: 284*4kB (UM) 53*8kB (UM) 21*16kB (U) 11*32kB (U) 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 2248kB 00177 DMA32: 2765*4kB (UME) 375*8kB (UME) 57*16kB (UM) 5*32kB (U) 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 15132kB 00177 4656 total pagecache pages 00177 1031 pages in swap cache 00177 Swap cache stats: add 6572399, delete 6572173, find 488603/3286476 00177 Free swap = 509112kB 00177 Total swap = 2097148kB 00177 130938 pages RAM 00177 0 pages HighMem/MovableOnly 00177 16644 pages reserved 00177 Unreclaimable slab info: 00177 9p-fcall-cache total: 8.25 MiB active: 8.25 MiB 00177 kernfs_node_cache total: 2.15 MiB active: 2.15 MiB 00177 kmalloc-64 total: 2.08 MiB active: 2.07 MiB 00177 task_struct total: 1.95 MiB active: 1.95 MiB 00177 kmalloc-4k total: 1.50 MiB active: 1.50 MiB 00177 signal_cache total: 1.34 MiB active: 1.34 MiB 00177 kmalloc-2k total: 1.16 MiB active: 1.16 MiB 00177 bch_inode_info total: 1.02 MiB active: 922 KiB 00177 perf_event total: 1.02 MiB active: 1.02 MiB 00177 biovec-max total: 992 KiB active: 960 KiB 00177 Shrinkers: 00177 super_cache_scan: objects: 127 00177 super_cache_scan: objects: 106 00177 jbd2_journal_shrink_scan: objects: 32 00177 ext4_es_scan: objects: 32 00177 bch2_btree_cache_scan: objects: 8 00177 nr nodes: 24 00177 nr dirty: 0 00177 cannibalize lock: 0000000000000000 00177 00177 super_cache_scan: objects: 8 00177 super_cache_scan: objects: 1 Signed-off-by: Kent Overstreet --- mm/oom_kill.c | 23 --------------------- mm/show_mem.c | 14 +++++++++++++ mm/slab.h | 6 ++++-- mm/slab_common.c | 53 ++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 63 insertions(+), 33 deletions(-) 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; } -/* - * 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 = 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 kill * @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/mm/show_mem.c b/mm/show_mem.c index 1c26c14ffb..24b662f64d 100644 --- a/mm/show_mem.c +++ b/mm/show_mem.c @@ -7,11 +7,15 @@ #include #include +#include + +#include "slab.h" void show_mem(unsigned int filter, nodemask_t *nodemask) { pg_data_t *pgdat; unsigned long total = 0, reserved = 0, highmem = 0; + struct printbuf buf = PRINTBUF; 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", printbuf_str(&buf)); + printbuf_reset(&buf); + + printk("Shrinkers:\n"); + shrinkers_to_text(&buf); + printk("%s", printbuf_str(&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) #endif +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..1209480797 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -24,6 +24,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -1084,10 +1085,15 @@ static int slab_show(struct seq_file *m, void *p) return 0; } -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 = 0; /* * 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; } - pr_info("Unreclaimable slab info:\n"); - pr_info("Name Used Total\n"); + printbuf_atomic_inc(out); list_for_each_entry(s, &slab_caches, list) { if (s->flags & SLAB_RECLAIM_ACCOUNT) @@ -1110,11 +1115,43 @@ void dump_unreclaimable_slab(void) get_slabinfo(s, &sinfo); - 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 = s; + n.total = sinfo.num_objs * s->size; + n.active = sinfo.active_objs * s->size; + + for (i = 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] = n; + } + + for (i = nr - 1; i >= 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); } + + printbuf_atomic_dec(out); mutex_unlock(&slab_mutex); }