From patchwork Tue Aug 28 17:19:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Waiman Long X-Patchwork-Id: 10578873 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 4B218175A for ; Tue, 28 Aug 2018 17:20:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2ABEC2A924 for ; Tue, 28 Aug 2018 17:20:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1CAE32A928; Tue, 28 Aug 2018 17:20:04 +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 6CACF2A924 for ; Tue, 28 Aug 2018 17:20:03 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 125BB6B472F; Tue, 28 Aug 2018 13:20:01 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 0890C6B4732; Tue, 28 Aug 2018 13:20:01 -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 E78DC6B4733; Tue, 28 Aug 2018 13:20:00 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-qt0-f197.google.com (mail-qt0-f197.google.com [209.85.216.197]) by kanga.kvack.org (Postfix) with ESMTP id B51B36B472F for ; Tue, 28 Aug 2018 13:20:00 -0400 (EDT) Received: by mail-qt0-f197.google.com with SMTP id c14-v6so1948765qtc.7 for ; Tue, 28 Aug 2018 10:20:00 -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=Xi6y4B1x4qzLxQlY4DcX7Q4ac2mLpjm84kW4qV3ddUM=; b=XiaYSgQxty2t0U1WLGd77iZu6MxAXpctZcxuH59nrAuIqTc1ClbNCGSB5ZNwdlHjYG 5cLBoobdJ6xobJmbrTCnSnXwiNJsD98aJ8wgBW4pyefyHXHMzaEbeqo6FCDyyUcCmG4w ysbASObXYp9e7M27c4X7kREXbs4caBpRfnVGh2Oj+SrAxf5rXQKLEZ8R0/DJ/rNy8sq9 2M/4XxhJyUwQxWcywIBoB0MMPfNcdEYsSe/+Deo6KS1NBOlgQGKA8K1EG0JSc3AGOGW0 86/OivcXgcI7Sa4bW057Nx+5ujA0+i9/3aYSH4sPMcs6c+sewvA37xPOVnQojqh35NK1 +gPA== 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: APzg51AP8Zy2w9ChrFg5NHMnElXOKG2SYxW6UkAMKfGP8qS+Mh7IzqVJ Z9mfwHXdm1ksJyfT1Jf1HmiUDfbR7qaO8bja2hAFhv336BAo1jWecPSr2aShgeREgKFo0k7zPge Rr8IX8ADN6Q4PfcAGQnUAn5AhqbbUoxYCiC9jm3GVxcT0lz9oagJPys3J47JAxtJQfA== X-Received: by 2002:ae9:e314:: with SMTP id v20-v6mr2632917qkf.69.1535476800502; Tue, 28 Aug 2018 10:20:00 -0700 (PDT) X-Google-Smtp-Source: ANB0VdaeuIQi1/MdAKBP6/J0iJz34vA0AUWiWsBc3gEGHmEKf6t3oBIuA5cDbuKWenDkl5/c9PXF X-Received: by 2002:ae9:e314:: with SMTP id v20-v6mr2632848qkf.69.1535476799622; Tue, 28 Aug 2018 10:19:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535476799; cv=none; d=google.com; s=arc-20160816; b=bK4sbjsc0AMeCu7VBdPm41dwwf6Jk72HGok/puVHpp2w8ZVi7QoLpCHChnX519GKeC XVVCL1ebnZABopTveOIWXwodLiHvW19RhEsRM+WTT3DO0/TXSNUBrHUVXNahy9MuWn4X 4D7i1ifoyY47U6sMEUTjDsSQ4YSlbtYLy9zvhjw5j2q8SHcjEpQ7uggijh0VHC0zirso PG1zvugOsEoTZVuP0EoDbnU4MWqWhBeTtQpxkp6IlDNrbVI0vt5Dsn6rrmv3hstxUfKA GdDlqvupmUiPUh7vHV1REE3fk7mEJGFGwCWqNJhi8LPZvMIdNeqiehweLuSPZflHnKq4 cnAw== 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=Xi6y4B1x4qzLxQlY4DcX7Q4ac2mLpjm84kW4qV3ddUM=; b=gvVA8RgWtHqa/HJZWGG0WdVkPdePMj3iFynqEYl9ky7rdxI6O85LrAvZf/Fc43s/C9 ZEQ2M25sEOwdKzTqTb+F/FQy9bh9uASSgrDACFoKxKa8O/UhpxIwUr9vrTBf17S3TwVw PwVrLADOyfOeSp3rIJAIJIzzATjLIUKydRwmdNoeUFD7eJLp8ZkiAOxcy1zV6Zshto2R rFbZ4cS2Ui5PR7NeG0aYQL8/jdRugsfX/2/941NvNivERoXvIZhvC76Ne6n6FQqGXNDW tlyN86QTshpew+gB2VKHdqNnjTyaYo0hP3oDteC9xP4owWqHbZ2EnGlcJDpMfy9In48I fgkg== 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 49-v6si1498766qvd.58.2018.08.28.10.19.59 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Aug 2018 10:19:59 -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 3406580C3C16; Tue, 28 Aug 2018 17:19:59 +0000 (UTC) Received: from llong.com (ovpn-123-12.rdu2.redhat.com [10.10.123.12]) by smtp.corp.redhat.com (Postfix) with ESMTP id A016C63F37; Tue, 28 Aug 2018 17:19:57 +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 1/2] fs/dcache: Track & report number of negative dentries Date: Tue, 28 Aug 2018 13:19:39 -0400 Message-Id: <1535476780-5773-2-git-send-email-longman@redhat.com> In-Reply-To: <1535476780-5773-1-git-send-email-longman@redhat.com> References: <1535476780-5773-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.8]); Tue, 28 Aug 2018 17:19:59 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Tue, 28 Aug 2018 17:19:59 +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, however, does not include negative dentries that are in flight but not in the LRU yet. The number of positive dentries in the LRU lists can be roughly 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 819caf8..118bb93 100644 --- a/Documentation/sysctl/fs.txt +++ b/Documentation/sysctl/fs.txt @@ -63,19 +63,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 2e7e8d8..69f5541 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) { /* @@ -331,6 +365,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) @@ -395,6 +431,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) @@ -403,6 +440,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) @@ -433,6 +471,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, @@ -441,6 +480,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); } /** @@ -1840,6 +1880,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 ef4b70f..df942e5 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; From patchwork Tue Aug 28 17:19:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Waiman Long X-Patchwork-Id: 10578875 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 DA9F217DB for ; Tue, 28 Aug 2018 17:20:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B59A52A925 for ; Tue, 28 Aug 2018 17:20:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A8C692A92E; Tue, 28 Aug 2018 17:20:07 +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 7D4AC2A925 for ; Tue, 28 Aug 2018 17:20:06 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 349316B4732; Tue, 28 Aug 2018 13:20:02 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 2FC156B4733; Tue, 28 Aug 2018 13:20:02 -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 0FC436B4734; Tue, 28 Aug 2018 13:20:02 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-qk0-f198.google.com (mail-qk0-f198.google.com [209.85.220.198]) by kanga.kvack.org (Postfix) with ESMTP id D7DA76B4732 for ; Tue, 28 Aug 2018 13:20:01 -0400 (EDT) Received: by mail-qk0-f198.google.com with SMTP id 93-v6so1877198qkq.7 for ; Tue, 28 Aug 2018 10:20:01 -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=X8B2MZcIaz1/qnz5E6BYH1ls5S1ihyOFhRzTkOvQulQ=; b=V9rEGDCilHsDJ5XSlDqUgiZe6PV3Aa6y0DVyyNusesu0ENgNRFj7zO3LX44Xy41ubn 9U2wwehaXY7ryToA6kDdxEOf+QWyj7BTQ/mfA3o9L2o+QCoJspB+8rHiFMlvTFXuNTIl MNOi0lKWIGfMhiNgw0m7BPfZcCgrjonmK96/0cR+usfCWP4gi1+MlYO2sxbykX9h7QNM uWTvpKqa+GIs6ZCa6z/0etjt67zUlVJ7g8LY3GAXIvxpgdxPGXzURUjTc2blCAXXlF9b kl4CqhKJOCEUxjF2tcX940xTZftboCTyx4fxPMQ73XZUqso9Xglo+TSuubwqdPoNiiCF NRcg== 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: APzg51DZfTO1I8R+K3dPmfCqOezCGwKPeDMbN6x1qt7Udr2snbG3naHj aGl3qOmN8lC0FuJQYwHVO7FGHHeN5Th/8C7F9OqYUmPrS0H9KiJ+I+eufeZMmu8A3bUK5FeS9r5 SGBUkecsk/ZkNI/CxGE1m+a++QdrCdW4JOeSbd7GaCtCqrJ07EihEXVEO2b5/JKi0uw== X-Received: by 2002:a0c:fa4e:: with SMTP id k14-v6mr2639555qvo.35.1535476801642; Tue, 28 Aug 2018 10:20:01 -0700 (PDT) X-Google-Smtp-Source: ANB0Vda7rEOHFP95Jx22tbfo2WUblPstqlAeuuZET3v3yDttQzEKWAs7RhhdZYf88LwNc3eGFRcr X-Received: by 2002:a0c:fa4e:: with SMTP id k14-v6mr2639498qvo.35.1535476800804; Tue, 28 Aug 2018 10:20:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535476800; cv=none; d=google.com; s=arc-20160816; b=MQHs+uQh3B9Knv9K3zonfraKcnA48syjhOFOiMrgzOJLfJMJAUKW2bSKWBVvq2TZgs lS6w74O0OPhwtxSYld7JEkfFPjMn07UrozX5uuJd+OWPbUolZkFmOKnzPdlL98wv4Q1Y Rw/3mthbvq0mPVhu6tGRSCuH41WwpDnibWZ/WVXXlZRkkLK/N4LYoepoJURg4vtw1F1z 0VTyC4Mg+ab/9SaX/udSgipQpSJ1EVsU1bzidBebYmK/jwOIRhdaLu5q+RUfGOPhcjCa lgxTzCsznzEM72VHiyn5oVPOvJslCg0lsskoD4enhAR13jyOw+tGcXSgbCecCtXw8qfi aMTQ== 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=X8B2MZcIaz1/qnz5E6BYH1ls5S1ihyOFhRzTkOvQulQ=; b=oqdoG0YmeIznHX1OBuw1XOhB89wsSrirpMcvCahOEdfiSsb+A52uf6yZbQB2CBd3aS iXd/Ewy81peTzIPWjRIXEgil/vzs/ehhDMBzs2H9sDTZJw9AZM7+ZQyAWTnEav9HTF0h ke8LtR8qZTiax7RxM23Y5sdPZixDtHuOvND+5zmUgnpmWIAjYqaMV/UB9zXI1ey3mDJn n7P/Pxtz6sdd7dkh93wyKHfS/0MLoUyQmcb3ONWe3EeWU5sxprTXKhz7k4lIdZ9D62t/ oDM5xsAS4tm4h2ZjZpeFicDvgEF9c5lJ+DidOS2D1M+wGwOYAfJvyCIICE+7W4ZqRtkw 1+mA== 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 i37-v6si1491275qti.112.2018.08.28.10.20.00 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Aug 2018 10:20:00 -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 39F1640241F0; Tue, 28 Aug 2018 17:20:00 +0000 (UTC) Received: from llong.com (ovpn-123-12.rdu2.redhat.com [10.10.123.12]) by smtp.corp.redhat.com (Postfix) with ESMTP id 43FC89463D; Tue, 28 Aug 2018 17:19:59 +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 2/2] fs/dcache: Make negative dentries easier to be reclaimed Date: Tue, 28 Aug 2018 13:19:40 -0400 Message-Id: <1535476780-5773-3-git-send-email-longman@redhat.com> In-Reply-To: <1535476780-5773-1-git-send-email-longman@redhat.com> References: <1535476780-5773-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.7]); Tue, 28 Aug 2018 17:20:00 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Tue, 28 Aug 2018 17:20:00 +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 For negative dentries that are accessed once and never used again, they should be removed first before other dentries when shrinker is running. This is done by putting negative dentries at the head of the LRU list instead at the tail. A new DCACHE_NEW_NEGATIVE flag is now added to a negative dentry when it is initially created. When such a dentry is added to the LRU, it will be added to the head so that it will be the first to go when a shrinker is running if it is never accessed again (DCACHE_REFERENCED bit not set). The flag is cleared after the LRU list addition. Suggested-by: Larry Woodman Signed-off-by: Waiman Long --- fs/dcache.c | 25 +++++++++++++++++-------- include/linux/dcache.h | 1 + include/linux/list_lru.h | 17 +++++++++++++++++ mm/list_lru.c | 16 ++++++++++++++-- 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 69f5541..ab6a4cf 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -242,12 +242,6 @@ 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) { /* @@ -353,7 +347,7 @@ static inline void __d_set_inode_and_type(struct dentry *dentry, dentry->d_inode = inode; flags = READ_ONCE(dentry->d_flags); - flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU); + flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU | DCACHE_NEW_NEGATIVE); flags |= type_flags; WRITE_ONCE(dentry->d_flags, flags); } @@ -430,8 +424,20 @@ 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)) { + __neg_dentry_inc(dentry); + if (dentry->d_flags & DCACHE_NEW_NEGATIVE) { + /* + * Add the negative dentry to the head once, it + * will be added to the tail next time. + */ + WARN_ON_ONCE(!list_lru_add_head( + &dentry->d_sb->s_dentry_lru, &dentry->d_lru)); + dentry->d_flags &= ~DCACHE_NEW_NEGATIVE; + return; + } + } 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) @@ -2620,6 +2626,9 @@ static inline void __d_add(struct dentry *dentry, struct inode *inode) __d_set_inode_and_type(dentry, inode, add_flags); raw_write_seqcount_end(&dentry->d_seq); fsnotify_update_flags(dentry); + } else { + /* It is a negative dentry, add it to LRU head initially. */ + dentry->d_flags |= DCACHE_NEW_NEGATIVE; } __d_rehash(dentry); if (dir) diff --git a/include/linux/dcache.h b/include/linux/dcache.h index df942e5..03a1918 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -214,6 +214,7 @@ struct dentry_operations { #define DCACHE_FALLTHRU 0x01000000 /* Fall through to lower layer */ #define DCACHE_ENCRYPTED_WITH_KEY 0x02000000 /* dir is encrypted with a valid key */ #define DCACHE_OP_REAL 0x04000000 +#define DCACHE_NEW_NEGATIVE 0x08000000 /* New negative dentry */ #define DCACHE_PAR_LOOKUP 0x10000000 /* being looked up (with parent locked shared) */ #define DCACHE_DENTRY_CURSOR 0x20000000 diff --git a/include/linux/list_lru.h b/include/linux/list_lru.h index aa5efd9..bfac057 100644 --- a/include/linux/list_lru.h +++ b/include/linux/list_lru.h @@ -90,6 +90,23 @@ int __list_lru_init(struct list_lru *lru, bool memcg_aware, bool list_lru_add(struct list_lru *lru, struct list_head *item); /** + * list_lru_add_head: add an element to the lru list's head + * @list_lru: the lru pointer + * @item: the item to be added. + * + * This is similar to list_lru_add(). The only difference is the location + * where the new item will be added. The list_lru_add() function will add + * the new item to the tail as it is the most recently used one. The + * list_lru_add_head() will add the new item into the head so that it + * will the first to go if a shrinker is running. So this function should + * only be used for less important item that can be the first to go if + * the system is under memory pressure. + * + * Return value: true if the list was updated, false otherwise + */ +bool list_lru_add_head(struct list_lru *lru, struct list_head *item); + +/** * list_lru_del: delete an element to the lru list * @list_lru: the lru pointer * @item: the item to be deleted. diff --git a/mm/list_lru.c b/mm/list_lru.c index 5b30625..133f41c 100644 --- a/mm/list_lru.c +++ b/mm/list_lru.c @@ -124,7 +124,8 @@ static inline bool list_lru_memcg_aware(struct list_lru *lru) } #endif /* CONFIG_MEMCG_KMEM */ -bool list_lru_add(struct list_lru *lru, struct list_head *item) +static inline bool __list_lru_add(struct list_lru *lru, struct list_head *item, + const bool add_tail) { int nid = page_to_nid(virt_to_page(item)); struct list_lru_node *nlru = &lru->node[nid]; @@ -134,7 +135,7 @@ bool list_lru_add(struct list_lru *lru, struct list_head *item) spin_lock(&nlru->lock); if (list_empty(item)) { l = list_lru_from_kmem(nlru, item, &memcg); - list_add_tail(item, &l->list); + (add_tail ? list_add_tail : list_add)(item, &l->list); /* Set shrinker bit if the first element was added */ if (!l->nr_items++) memcg_set_shrinker_bit(memcg, nid, @@ -146,8 +147,19 @@ bool list_lru_add(struct list_lru *lru, struct list_head *item) spin_unlock(&nlru->lock); return false; } + +bool list_lru_add(struct list_lru *lru, struct list_head *item) +{ + return __list_lru_add(lru, item, true); +} EXPORT_SYMBOL_GPL(list_lru_add); +bool list_lru_add_head(struct list_lru *lru, struct list_head *item) +{ + return __list_lru_add(lru, item, false); +} +EXPORT_SYMBOL_GPL(list_lru_add_head); + bool list_lru_del(struct list_lru *lru, struct list_head *item) { int nid = page_to_nid(virt_to_page(item));