From patchwork Tue Sep 11 19:18:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Waiman Long X-Patchwork-Id: 10596197 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7D45414F9 for ; Tue, 11 Sep 2018 19:18:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 762EB29BD9 for ; Tue, 11 Sep 2018 19:18:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 69D2C29D10; Tue, 11 Sep 2018 19:18:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B5EB729BD9 for ; Tue, 11 Sep 2018 19:18:45 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 97BFA8E0005; Tue, 11 Sep 2018 15:18:39 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 92D5A8E0001; Tue, 11 Sep 2018 15:18:39 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 8410E8E0005; Tue, 11 Sep 2018 15:18:39 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-qt0-f200.google.com (mail-qt0-f200.google.com [209.85.216.200]) by kanga.kvack.org (Postfix) with ESMTP id 5B2BD8E0001 for ; Tue, 11 Sep 2018 15:18:39 -0400 (EDT) Received: by mail-qt0-f200.google.com with SMTP id d18-v6so25657270qtj.20 for ; Tue, 11 Sep 2018 12:18:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-original-authentication-results:x-gm-message-state:from:to:cc :subject:date:message-id:in-reply-to:references; bh=MV7sweeXZCYt1FY8IUx5TOm44xr8ZjSGlGVv/JPWaXM=; b=sQvoZ1es7/jN9w2kzR8ByWBS5ndXq7+vSPmbZWAW4Me2YOGfPecxvqkD/Rxh3A3Gn1 CQF3xEa3dOfrCSnAz8uk2L3oRXxojul1XYBklpVllAe/Z9q2C7pbn/dVfF9U/wR6um81 QWIxwdWoPhHNq3EQ2GwnOXqoCVDgJVzP989cDRbqbCJZZgI9AhQ3sNrHw6ebi8kB2lX1 fvJ20qmFc9TYcWfVzWQ4TrZBTFqr7H5SwTVjYaR13/ypC1bsdWvpgPEwqgYKU8glV73V pZKt9ukaolyISt1m9rkdmE1OHjnKbOMYOW5lwGioTVnZ3RvJx3A1VyiEFOj57Kf4PwQF mBrw== X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of longman@redhat.com designates 66.187.233.73 as permitted sender) smtp.mailfrom=longman@redhat.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com X-Gm-Message-State: APzg51DkVB19+YcJ+5sVCHgxfNzLS/F/XcqKtYfN+blZ2Yj1qTbDwQHz KhfDDFfeAIbzOvI/ODIPAES6mF6m/ug0zVvXEwdq/SJ2DF4Jb8fc3DG0wDWPRCOH8jJBdn4XjnI I0pHiZRWRiOLfly+Gn+P/k1AnXfyxAHbPNVf8vaEbia0OAzaVOcQeXWAoAQgPOTgKsg== X-Received: by 2002:ac8:24d0:: with SMTP id t16-v6mr20935322qtt.116.1536693519113; Tue, 11 Sep 2018 12:18:39 -0700 (PDT) X-Google-Smtp-Source: ANB0VdZasF69OOQPc5AczSZIJitxlnfNLGNRq6ULhSxRfycNty6ddG5JSE6f7Cnjmq6bm4MA3syA X-Received: by 2002:ac8:24d0:: with SMTP id t16-v6mr20935279qtt.116.1536693518184; Tue, 11 Sep 2018 12:18:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536693518; cv=none; d=google.com; s=arc-20160816; b=U0Vt8f4r3e9e9+uJQF5bZGkDH+ykdq43XT3VBuK1HBjv5cK/LvAZ0oWzLSVCwLjkqz cutL7Tsfmib+wvffyQjMIVObACBdz/lWcDjtb5FKqxaz4aQyES1QiblRYICkayL7x3J0 XPnCUeBtJsV0RETg/+plpndBbdhR14twt/IyqtHvHd1EVFoLDJnfAaP44HDq8GIZPjnA Y2csn4TYDW541DXh7uNT6r8+/Rg2spDynUeMoq7m9scHx3bSwo1qBBVf7pIcdOEv7xtA 5UyptPV7G+seyed/haynki7MvJ7MxMbh0ef7MBTpiAz3pTglKIaKZkgy6zedJg7b6DxM rdCA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from; bh=MV7sweeXZCYt1FY8IUx5TOm44xr8ZjSGlGVv/JPWaXM=; b=BDu7aiDsimpNKtJz89fO2n7LW1RDixQjxkfOH1bYp2JiaKYRRkLA8hzA8JjFQrglkW 822S2O6BSFf3UT3EUZok/IazY+D4fm9Jc7QH+8gl49WiUUfI9+MWn782Y8KYyuaMRPQm osQR8V1eoHLjJoBYsxXFaixqA0Od1aUopHsRC/pVYI0czoJuVS3Q9h6MPquOe6MAUkkO 4g4nbG6pxSWIJmONoxiX0a8AAn1vO0ZFe1UEqXFPLMNmP1me+PaTxZcwe/LvmvSF0gP5 71jlNRAxN01EukgzHtriYixbUt3O4K39Bed3VcTyBYOxyq5ctqInJiWNFL9UXWoIuVGd NpKQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of longman@redhat.com designates 66.187.233.73 as permitted sender) smtp.mailfrom=longman@redhat.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from mx1.redhat.com (mx3-rdu2.redhat.com. [66.187.233.73]) by mx.google.com with ESMTPS id 21-v6si4226748qtp.70.2018.09.11.12.18.38 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 11 Sep 2018 12:18:38 -0700 (PDT) Received-SPF: pass (google.com: domain of longman@redhat.com designates 66.187.233.73 as permitted sender) client-ip=66.187.233.73; Authentication-Results: mx.google.com; spf=pass (google.com: domain of longman@redhat.com designates 66.187.233.73 as permitted sender) smtp.mailfrom=longman@redhat.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B794C804B9F4; Tue, 11 Sep 2018 19:18:37 +0000 (UTC) Received: from llong.com (ovpn-123-172.rdu2.redhat.com [10.10.123.172]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9FCF82157F4A; Tue, 11 Sep 2018 19:18:36 +0000 (UTC) From: Waiman Long To: Alexander Viro , Jonathan Corbet Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-doc@vger.kernel.org, "Luis R. Rodriguez" , Kees Cook , Linus Torvalds , Jan Kara , "Paul E. McKenney" , Andrew Morton , Ingo Molnar , Miklos Szeredi , Matthew Wilcox , Larry Woodman , James Bottomley , "Wangkai (Kevin C)" , Michal Hocko , Waiman Long Subject: [PATCH v3 3/4] fs/dcache: Track & report number of negative dentries Date: Tue, 11 Sep 2018 15:18:25 -0400 Message-Id: <1536693506-11949-4-git-send-email-longman@redhat.com> In-Reply-To: <1536693506-11949-1-git-send-email-longman@redhat.com> References: <1536693506-11949-1-git-send-email-longman@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Tue, 11 Sep 2018 19:18:37 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Tue, 11 Sep 2018 19:18:37 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'longman@redhat.com' RCPT:'' 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: X-Virus-Scanned: ClamAV using ClamSMTP The current dentry number tracking code doesn't distinguish between positive & negative dentries. It just reports the total number of dentries in the LRU lists. As excessive number of negative dentries can have an impact on system performance, it will be wise to track the number of positive and negative dentries separately. This patch adds tracking for the total number of negative dentries in the system LRU lists and reports it in the 7th field in the /proc/sys/fs/dentry-state file. The number, however, does not include negative dentries that are in flight but not in the LRU yet as well as those in the shrinker lists. The number of positive dentries in the LRU lists can be roughly found by subtracting the number of negative dentries from the unused count. Matthew Wilcox had confirmed that since the introduction of the dentry_stat structure in 2.1.60, the dummy array was there, probably for future extension. They were not replacements of pre-existing fields. So no sane applications that read the value of /proc/sys/fs/dentry-state will do dummy thing if the last 2 fields of the sysctl parameter are not zero. IOW, it will be safe to use one of the dummy array entry for negative dentry count. Signed-off-by: Waiman Long --- Documentation/sysctl/fs.txt | 26 ++++++++++++++++---------- fs/dcache.c | 31 +++++++++++++++++++++++++++++++ include/linux/dcache.h | 7 ++++--- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt index 819caf8..3b4f441 100644 --- a/Documentation/sysctl/fs.txt +++ b/Documentation/sysctl/fs.txt @@ -56,26 +56,32 @@ of any kernel data structures. dentry-state: -From linux/fs/dentry.c: +From linux/include/linux/dcache.h: -------------------------------------------------------------- -struct { +struct dentry_stat_t dentry_stat { int nr_dentry; int nr_unused; int age_limit; /* age in seconds */ int want_pages; /* pages requested by system */ - int dummy[2]; -} dentry_stat = {0, 0, 45, 0,}; --------------------------------------------------------------- - -Dentries are dynamically allocated and deallocated, and -nr_dentry seems to be 0 all the time. Hence it's safe to -assume that only nr_unused, age_limit and want_pages are -used. Nr_unused seems to be exactly what its name says. + int nr_negative; /* # of unused negative dentries */ + int dummy; /* Reserved */ +}; +-------------------------------------------------------------- + +Dentries are dynamically allocated and deallocated. + +nr_dentry shows the total number of dentries allocated (active ++ unused). nr_unused shows the number of dentries that are not +actively used, but are saved in the LRU list for future reuse. + Age_limit is the age in seconds after which dcache entries can be reclaimed when memory is short and want_pages is nonzero when shrink_dcache_pages() has been called and the dcache isn't pruned yet. +nr_negative shows the number of unused dentries that are also +negative dentries which do not mapped to actual files. + ============================================================== dquot-max & dquot-nr: diff --git a/fs/dcache.c b/fs/dcache.c index cb515f1..c1cc956 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -119,6 +119,7 @@ struct dentry_stat_t dentry_stat = { static DEFINE_PER_CPU(long, nr_dentry); static DEFINE_PER_CPU(long, nr_dentry_unused); +static DEFINE_PER_CPU(long, nr_dentry_negative); #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS) @@ -152,11 +153,22 @@ static long get_nr_dentry_unused(void) return sum < 0 ? 0 : sum; } +static long get_nr_dentry_negative(void) +{ + int i; + long sum = 0; + + for_each_possible_cpu(i) + sum += per_cpu(nr_dentry_negative, i); + return sum < 0 ? 0 : sum; +} + int proc_nr_dentry(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { dentry_stat.nr_dentry = get_nr_dentry(); dentry_stat.nr_unused = get_nr_dentry_unused(); + dentry_stat.nr_negative = get_nr_dentry_negative(); return proc_doulongvec_minmax(table, write, buffer, lenp, ppos); } #endif @@ -331,6 +343,8 @@ static inline void __d_clear_type_and_inode(struct dentry *dentry) flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU); WRITE_ONCE(dentry->d_flags, flags); dentry->d_inode = NULL; + if (dentry->d_flags & DCACHE_LRU_LIST) + this_cpu_inc(nr_dentry_negative); } static void dentry_free(struct dentry *dentry) @@ -385,6 +399,10 @@ static void dentry_unlink_inode(struct dentry * dentry) * The per-cpu "nr_dentry_unused" counters are updated with * the DCACHE_LRU_LIST bit. * + * The per-cpu "nr_dentry_negative" counters are only updated + * when deleted or added to the per-superblock LRU list, not + * on the shrink list. + * * These helper functions make sure we always follow the * rules. d_lock must be held by the caller. */ @@ -394,6 +412,8 @@ static void d_lru_add(struct dentry *dentry) D_FLAG_VERIFY(dentry, 0); dentry->d_flags |= DCACHE_LRU_LIST; this_cpu_inc(nr_dentry_unused); + if (d_is_negative(dentry)) + this_cpu_inc(nr_dentry_negative); WARN_ON_ONCE(!list_lru_add(&dentry->d_sb->s_dentry_lru, &dentry->d_lru)); } @@ -402,6 +422,8 @@ static void d_lru_del(struct dentry *dentry) D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); dentry->d_flags &= ~DCACHE_LRU_LIST; this_cpu_dec(nr_dentry_unused); + if (d_is_negative(dentry)) + this_cpu_dec(nr_dentry_negative); WARN_ON_ONCE(!list_lru_del(&dentry->d_sb->s_dentry_lru, &dentry->d_lru)); } @@ -432,6 +454,8 @@ static void d_lru_isolate(struct list_lru_one *lru, struct dentry *dentry) D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); dentry->d_flags &= ~DCACHE_LRU_LIST; this_cpu_dec(nr_dentry_unused); + if (d_is_negative(dentry)) + this_cpu_dec(nr_dentry_negative); list_lru_isolate(lru, &dentry->d_lru); } @@ -440,6 +464,8 @@ static void d_lru_shrink_move(struct list_lru_one *lru, struct dentry *dentry, { D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST); dentry->d_flags |= DCACHE_SHRINK_LIST; + if (d_is_negative(dentry)) + this_cpu_dec(nr_dentry_negative); list_lru_isolate_move(lru, &dentry->d_lru, list); } @@ -1836,6 +1862,11 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode) WARN_ON(d_in_lookup(dentry)); spin_lock(&dentry->d_lock); + /* + * Decrement negative dentry count if it was in the LRU list. + */ + if (dentry->d_flags & DCACHE_LRU_LIST) + this_cpu_dec(nr_dentry_negative); hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry); raw_write_seqcount_begin(&dentry->d_seq); __d_set_inode_and_type(dentry, inode, add_flags); diff --git a/include/linux/dcache.h b/include/linux/dcache.h index ef4b70f..73ff9f0 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -62,9 +62,10 @@ struct qstr { struct dentry_stat_t { long nr_dentry; long nr_unused; - long age_limit; /* age in seconds */ - long want_pages; /* pages requested by system */ - long dummy[2]; + long age_limit; /* age in seconds */ + long want_pages; /* pages requested by system */ + long nr_negative; /* # of unused negative dentries */ + long dummy; /* Reserved */ }; extern struct dentry_stat_t dentry_stat;