From patchwork Fri Jul 6 19:32:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Waiman Long X-Patchwork-Id: 10512445 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 35E2B60325 for ; Fri, 6 Jul 2018 19:34:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 23258287AC for ; Fri, 6 Jul 2018 19:34:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1731A287B7; Fri, 6 Jul 2018 19:34:35 +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 6B7F5287AC for ; Fri, 6 Jul 2018 19:34:34 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 897196B026C; Fri, 6 Jul 2018 15:34:30 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 81E3C6B026D; Fri, 6 Jul 2018 15:34:30 -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 64A0D6B026F; Fri, 6 Jul 2018 15:34:30 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-qk0-f197.google.com (mail-qk0-f197.google.com [209.85.220.197]) by kanga.kvack.org (Postfix) with ESMTP id 21A5D6B026C for ; Fri, 6 Jul 2018 15:34:30 -0400 (EDT) Received: by mail-qk0-f197.google.com with SMTP id w126-v6so4895733qka.11 for ; Fri, 06 Jul 2018 12:34:30 -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=b7WTmx1HPBaYXFLhhLWaxwhp7Uzqqf+TVPUGaQ3yIR4=; b=mhvs68ZOo34lQZJfI9/MjMWO4/ZGcRKtXFEpxVvSYVQlDxxhvjGr7NWUsPrLgaca5L vVnOcTJtNjn8TWi70xGu7xs7+KvRr5G479ScoNQ8899dmQDu42HTLtBKelJtoOmjm/W6 eMOGE7+1cNSjl4yAczmyU0gQYynIwWt5Q5q92k6eeJ5sHLTyIKI+oRWmcpWa2FoZ9BeY +eCxJiR42zM/4oehucECPN0jr+DdkGeNyzsLlJdMJ5z+Vt3Cbhd/pXwINisLnxlSY6VY IVqBl/LUBAjkkjJ8lt4QFVGuP+92Oxwiyhiab7jwn2iwixnC2zKnGRy8lRls6dLia9qP n5ow== 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: APt69E0AiJDkwCwIiAG3hYcbsSq0IF+pdD0UClysfCc0veLS5mqylhK6 Mfer/iTth9QVSV/W8pdgLo192QiavLuE54J6zK3rCPigNIudfEVBUDJM2iTJxh0tPuQ65z8CbjB ifOnlJaIvPnZ8sMuRGs6S3eujMT9h+Gz4/H2jINv4dlqbOh/AWnCAdpKwjWhIChiJvQ== X-Received: by 2002:a0c:b067:: with SMTP id l36-v6mr10120540qvc.176.1530905669883; Fri, 06 Jul 2018 12:34:29 -0700 (PDT) X-Google-Smtp-Source: AAOMgpcmpHscMyz5QKrQiTfS2Bq2EriwO8LioMaxH0hTi67JLNZD0knHONkMY56apaL2UjkqMG2S X-Received: by 2002:a0c:b067:: with SMTP id l36-v6mr10120494qvc.176.1530905668900; Fri, 06 Jul 2018 12:34:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1530905668; cv=none; d=google.com; s=arc-20160816; b=y80fsS+7hHmu3ALkqK5mSWQpfrMBdVDZBczWBmYUWewmPs5p9dhHjeRxQodVAo5FPK Ov5+bHNt3UVEemImVkNTccJDmCU1CkDf/BPX/EG8pFk1a8n16ut+ZnP7vHZ5mETzyVAq fmYRy32Ma+Hsipbj0exbD+kdDBQLT8m3p4vBIbbMZviV1FWHmvK1kxTNBoJ/XUqkUHhc hsMzOKipqec2QAvyrNfg1UbOaJDrEMtC+2A95IuFLN2KQ5hATeZ+NgsRpumMCUoHrMUX 5rmIrXW9yR8/er6fnVSNT8KKnCmxSvscziZjwuecfnjPfXc01lvYMiW03ZkZbwmaqRdf SBIA== 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 :arc-authentication-results; bh=b7WTmx1HPBaYXFLhhLWaxwhp7Uzqqf+TVPUGaQ3yIR4=; b=MOKSDKNo0KV4lat3y6Q5vnAvBT5PTpaBzdmZ3H34xVFPhiEWlR8PM2DMN/9td0/MWz zilxLNZOJ1iQPFQQxACHOnFxzT3zHnjDegcl9I6+djTaqXFnaZAmnllQMZWYGTiUyz9o FU/Zho8QLJ6ApsdKjo2nPMYKzKCV0XatnfXSj/VvgZ+iRpc6rZsSXA5FgReF4jpx5HF/ RIoGMk7K16MBeXnhhISY2/acFvH/qi9QjrSEVpY+f9Fx11orwXFR1Bj3sGuqcxRuXw3S zNURm3SCJmFK80HpfSQNMDCGm+sz1za03z/1B1hrq/M3SyBZOCrk0aHndWn9xeyDr1Sa ddQg== 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 q16-v6si4447942qtf.380.2018.07.06.12.34.28 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 06 Jul 2018 12:34:28 -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-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 67984405A015; Fri, 6 Jul 2018 19:34:28 +0000 (UTC) Received: from llong.com (dhcp-17-175.bos.redhat.com [10.18.17.175]) by smtp.corp.redhat.com (Postfix) with ESMTP id EA69579DE; Fri, 6 Jul 2018 19:34:27 +0000 (UTC) From: Waiman Long To: Alexander Viro , Jonathan Corbet , "Luis R. Rodriguez" , Kees Cook Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-doc@vger.kernel.org, Linus Torvalds , Jan Kara , "Paul E. McKenney" , Andrew Morton , Ingo Molnar , Miklos Szeredi , Matthew Wilcox , Larry Woodman , James Bottomley , "Wangkai (Kevin C)" , Waiman Long Subject: [PATCH v6 1/7] fs/dcache: Track & report number of negative dentries Date: Fri, 6 Jul 2018 15:32:46 -0400 Message-Id: <1530905572-817-2-git-send-email-longman@redhat.com> In-Reply-To: <1530905572-817-1-git-send-email-longman@redhat.com> References: <1530905572-817-1-git-send-email-longman@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 06 Jul 2018 19:34:28 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 06 Jul 2018 19:34:28 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.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 /proc/sys/fs/dentry-state file. The number of positive dentries in the LRU lists can be found by subtracting the number of negative dentries from the total. Signed-off-by: Waiman Long --- Documentation/sysctl/fs.txt | 19 +++++++++++++------ fs/dcache.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/dcache.h | 7 ++++--- 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt index 6c00c1e..a8e3f1f 100644 --- a/Documentation/sysctl/fs.txt +++ b/Documentation/sysctl/fs.txt @@ -61,19 +61,26 @@ struct { int nr_unused; int age_limit; /* age in seconds */ int want_pages; /* pages requested by system */ - int dummy[2]; + int nr_negative; /* # of unused negative dentries */ + int dummy; } dentry_stat = {0, 0, 45, 0,}; --------------------------------------------------------------- +-------------------------------------------------------------- + +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. -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. 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 if negative +dentries tracking is enabled. + ============================================================== dquot-max & dquot-nr: diff --git a/fs/dcache.c b/fs/dcache.c index 0e8e5de..dbab6c2 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_neg); #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_neg(void) +{ + int i; + long sum = 0; + + for_each_possible_cpu(i) + sum += per_cpu(nr_dentry_neg, 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_neg(); return proc_doulongvec_minmax(table, write, buffer, lenp, ppos); } #endif @@ -214,6 +226,28 @@ static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char #endif +static inline void __neg_dentry_dec(struct dentry *dentry) +{ + this_cpu_dec(nr_dentry_neg); +} + +static inline void neg_dentry_dec(struct dentry *dentry) +{ + if (unlikely(d_is_negative(dentry))) + __neg_dentry_dec(dentry); +} + +static inline void __neg_dentry_inc(struct dentry *dentry) +{ + this_cpu_inc(nr_dentry_neg); +} + +static inline void neg_dentry_inc(struct dentry *dentry) +{ + if (unlikely(d_is_negative(dentry))) + __neg_dentry_inc(dentry); +} + static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *ct, unsigned tcount) { /* @@ -330,6 +364,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) + __neg_dentry_inc(dentry); } static void dentry_free(struct dentry *dentry) @@ -397,6 +433,7 @@ static void d_lru_add(struct dentry *dentry) dentry->d_flags |= DCACHE_LRU_LIST; this_cpu_inc(nr_dentry_unused); WARN_ON_ONCE(!list_lru_add(&dentry->d_sb->s_dentry_lru, &dentry->d_lru)); + neg_dentry_inc(dentry); } static void d_lru_del(struct dentry *dentry) @@ -405,6 +442,7 @@ static void d_lru_del(struct dentry *dentry) dentry->d_flags &= ~DCACHE_LRU_LIST; this_cpu_dec(nr_dentry_unused); WARN_ON_ONCE(!list_lru_del(&dentry->d_sb->s_dentry_lru, &dentry->d_lru)); + neg_dentry_dec(dentry); } static void d_shrink_del(struct dentry *dentry) @@ -435,6 +473,7 @@ static void d_lru_isolate(struct list_lru_one *lru, struct dentry *dentry) dentry->d_flags &= ~DCACHE_LRU_LIST; this_cpu_dec(nr_dentry_unused); list_lru_isolate(lru, &dentry->d_lru); + neg_dentry_dec(dentry); } static void d_lru_shrink_move(struct list_lru_one *lru, struct dentry *dentry, @@ -443,6 +482,7 @@ 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; list_lru_isolate_move(lru, &dentry->d_lru, list); + neg_dentry_dec(dentry); } /** @@ -1842,6 +1882,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) + __neg_dentry_dec(dentry); 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 66c6e17..6e06d91 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; }; extern struct dentry_stat_t dentry_stat;