diff mbox

[v7,6/6] fs/dcache: Allow deconfiguration of negative dentry code to reduce kernel size

Message ID 1531413965-5401-7-git-send-email-longman@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Waiman Long July 12, 2018, 4:46 p.m. UTC
The tracking and limit of negative dentries in a filesystem is a useful
addition. However, for users who want to reduce the kernel size as much
as possible, this feature will probably be on the chopping block. To
suit those users, a default-y config option DCACHE_LIMIT_NEG_ENTRY is
added so that the negative dentry limiting code can be configured out,
if necessary.

Signed-off-by: Waiman Long <longman@redhat.com>
---
 fs/Kconfig             | 10 ++++++++++
 fs/dcache.c            | 29 +++++++++++++++++++++++------
 include/linux/dcache.h |  2 ++
 kernel/sysctl.c        |  2 ++
 4 files changed, 37 insertions(+), 6 deletions(-)

Comments

kernel test robot July 17, 2018, 1:25 a.m. UTC | #1
Hi Waiman,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.18-rc4]
[cannot apply to next-20180713]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Waiman-Long/fs-dcache-Track-report-number-of-negative-dentries/20180714-161258
config: h8300-h8300h-sim_defconfig (attached as .config)
compiler: h8300-linux-gcc (GCC) 8.1.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=8.1.0 make.cross ARCH=h8300 
:::::: branch date: 65 minutes ago
:::::: commit date: 65 minutes ago

All errors (new ones prefixed by >>):

   fs/dcache.c: In function 'neg_dentry_inc_slowpath':
>> fs/dcache.c:374:8: error: implicit declaration of function 'get_nr_dentry_neg'; did you mean 'get_nr_dirty_inodes'? [-Werror=implicit-function-declaration]
     cnt = get_nr_dentry_neg();
           ^~~~~~~~~~~~~~~~~
           get_nr_dirty_inodes
   cc1: some warnings being treated as errors

# https://github.com/0day-ci/linux/commit/ca68ee513a450445b269248c2859302c8931a294
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout ca68ee513a450445b269248c2859302c8931a294
vim +374 fs/dcache.c

bcc9ba8b Waiman Long 2018-07-12  311  
2ccdd02c Waiman Long 2018-07-12  312  static noinline int neg_dentry_inc_slowpath(struct dentry *dentry)
bcc9ba8b Waiman Long 2018-07-12  313  {
bcc9ba8b Waiman Long 2018-07-12  314  	long cnt = 0, *pcnt;
2aa8bf46 Waiman Long 2018-07-12  315  	unsigned long current_time;
bcc9ba8b Waiman Long 2018-07-12  316  
bcc9ba8b Waiman Long 2018-07-12  317  	/*
bcc9ba8b Waiman Long 2018-07-12  318  	 * Try to move some negative dentry quota from the global free
bcc9ba8b Waiman Long 2018-07-12  319  	 * pool to the percpu count to allow more negative dentries to
bcc9ba8b Waiman Long 2018-07-12  320  	 * be added to the LRU.
bcc9ba8b Waiman Long 2018-07-12  321  	 */
bcc9ba8b Waiman Long 2018-07-12  322  	pcnt = get_cpu_ptr(&nr_dentry_neg);
bcc9ba8b Waiman Long 2018-07-12  323  	if ((READ_ONCE(ndblk.nfree) > 0) &&
bcc9ba8b Waiman Long 2018-07-12  324  	    (*pcnt > neg_dentry_percpu_limit)) {
bcc9ba8b Waiman Long 2018-07-12  325  		cnt = __neg_dentry_nfree_dec(*pcnt - neg_dentry_percpu_limit);
bcc9ba8b Waiman Long 2018-07-12  326  		*pcnt -= cnt;
bcc9ba8b Waiman Long 2018-07-12  327  	}
bcc9ba8b Waiman Long 2018-07-12  328  	put_cpu_ptr(&nr_dentry_neg);
bcc9ba8b Waiman Long 2018-07-12  329  
2aa8bf46 Waiman Long 2018-07-12  330  	if (cnt)
2aa8bf46 Waiman Long 2018-07-12  331  		goto out;
2aa8bf46 Waiman Long 2018-07-12  332  
bcc9ba8b Waiman Long 2018-07-12  333  	/*
2ccdd02c Waiman Long 2018-07-12  334  	 * Kill the dentry by setting the DCACHE_KILL_NEGATIVE flag and
2ccdd02c Waiman Long 2018-07-12  335  	 * dec the negative dentry count if the enforcing option is on.
2ccdd02c Waiman Long 2018-07-12  336  	 */
2ccdd02c Waiman Long 2018-07-12  337  	if (neg_dentry_enforce) {
2ccdd02c Waiman Long 2018-07-12  338  		dentry->d_flags |= DCACHE_KILL_NEGATIVE;
2ccdd02c Waiman Long 2018-07-12  339  		this_cpu_dec(nr_dentry_neg);
2ccdd02c Waiman Long 2018-07-12  340  
2ccdd02c Waiman Long 2018-07-12  341  		/*
2ccdd02c Waiman Long 2018-07-12  342  		 * When the dentry is not put into the LRU, we
2ccdd02c Waiman Long 2018-07-12  343  		 * need to keep the reference count to 1 to
2ccdd02c Waiman Long 2018-07-12  344  		 * avoid problem when killing it.
2ccdd02c Waiman Long 2018-07-12  345  		 */
2ccdd02c Waiman Long 2018-07-12  346  		WARN_ON_ONCE(dentry->d_lockref.count);
2ccdd02c Waiman Long 2018-07-12  347  		dentry->d_lockref.count = 1;
2ccdd02c Waiman Long 2018-07-12  348  		return -1; /* Kill the dentry now */
2ccdd02c Waiman Long 2018-07-12  349  	}
2ccdd02c Waiman Long 2018-07-12  350  
2ccdd02c Waiman Long 2018-07-12  351  	/*
2aa8bf46 Waiman Long 2018-07-12  352  	 * Put out a warning every minute or so if there are just too many
2aa8bf46 Waiman Long 2018-07-12  353  	 * negative dentries.
bcc9ba8b Waiman Long 2018-07-12  354  	 */
2aa8bf46 Waiman Long 2018-07-12  355  	current_time = jiffies;
bcc9ba8b Waiman Long 2018-07-12  356  
2aa8bf46 Waiman Long 2018-07-12  357  	if (current_time < ndblk.warn_jiffies + NEG_WARN_PERIOD)
2aa8bf46 Waiman Long 2018-07-12  358  		goto out;
2aa8bf46 Waiman Long 2018-07-12  359  	/*
2aa8bf46 Waiman Long 2018-07-12  360  	 * Update the time in ndblk.warn_jiffies and print a warning
2aa8bf46 Waiman Long 2018-07-12  361  	 * if time update is successful.
2aa8bf46 Waiman Long 2018-07-12  362  	 */
2aa8bf46 Waiman Long 2018-07-12  363  	raw_spin_lock(&ndblk.nfree_lock);
2aa8bf46 Waiman Long 2018-07-12  364  	if (current_time < ndblk.warn_jiffies + NEG_WARN_PERIOD) {
2aa8bf46 Waiman Long 2018-07-12  365  		raw_spin_unlock(&ndblk.nfree_lock);
2aa8bf46 Waiman Long 2018-07-12  366  		goto out;
2aa8bf46 Waiman Long 2018-07-12  367  	}
2aa8bf46 Waiman Long 2018-07-12  368  	ndblk.warn_jiffies = current_time;
2aa8bf46 Waiman Long 2018-07-12  369  	raw_spin_unlock(&ndblk.nfree_lock);
2aa8bf46 Waiman Long 2018-07-12  370  
2aa8bf46 Waiman Long 2018-07-12  371  	/*
2aa8bf46 Waiman Long 2018-07-12  372  	 * Get the current negative dentry count & print a warning.
2aa8bf46 Waiman Long 2018-07-12  373  	 */
2aa8bf46 Waiman Long 2018-07-12 @374  	cnt = get_nr_dentry_neg();
2aa8bf46 Waiman Long 2018-07-12  375  	pr_warn("Warning: Too many negative dentries (%ld). "
2ccdd02c Waiman Long 2018-07-12  376  		"This warning can be disabled by writing 0 to \"fs/neg-dentry-limit\", increasing the limit or writing 1 to \"fs/neg-dentry-enforce\".\n",
2aa8bf46 Waiman Long 2018-07-12  377  		cnt);
2aa8bf46 Waiman Long 2018-07-12  378  out:
2ccdd02c Waiman Long 2018-07-12  379  	return 0;
bcc9ba8b Waiman Long 2018-07-12  380  }
bcc9ba8b Waiman Long 2018-07-12  381  

:::::: The code at line 374 was first introduced by commit
:::::: 2aa8bf4658af0dbc07ae9ea07d04937a347e3ef4 fs/dcache: Print negative dentry warning every min until turned off by user

:::::: TO: Waiman Long <longman@redhat.com>
:::::: CC: 0day robot <lkp@intel.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/fs/Kconfig b/fs/Kconfig
index ac474a6..b521941 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -113,6 +113,16 @@  source "fs/autofs/Kconfig"
 source "fs/fuse/Kconfig"
 source "fs/overlayfs/Kconfig"
 
+#
+# Track and limit the number of negative dentries allowed in the system.
+#
+config DCACHE_LIMIT_NEG_ENTRY
+	bool "Track & limit negative dcache entries"
+	default y
+	help
+	  This option enables the tracking and limiting of the total
+	  number of negative dcache entries allowable in the filesystem.
+
 menu "Caches"
 
 source "fs/fscache/Kconfig"
diff --git a/fs/dcache.c b/fs/dcache.c
index 843c8be..dccfe39 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -141,6 +141,7 @@  struct dentry_stat_t dentry_stat = {
 #define NEG_DENTRY_BATCH	(1 << 8)
 #define NEG_WARN_PERIOD 	(60 * HZ)	/* Print a warning every min */
 
+#ifdef CONFIG_DCACHE_LIMIT_NEG_ENTRY
 static struct static_key limit_neg_key = STATIC_KEY_INIT_FALSE;
 static int neg_dentry_limit_old;
 int neg_dentry_limit;
@@ -156,6 +157,7 @@  struct dentry_stat_t dentry_stat = {
 	unsigned long warn_jiffies;	/* Time when last warning is printed */
 } ndblk ____cacheline_aligned_in_smp;
 proc_handler proc_neg_dentry_limit;
+#endif /* CONFIG_DCACHE_LIMIT_NEG_ENTRY */
 
 static DEFINE_PER_CPU(long, nr_dentry);
 static DEFINE_PER_CPU(long, nr_dentry_unused);
@@ -200,7 +202,9 @@  static long get_nr_dentry_neg(void)
 
 	for_each_possible_cpu(i)
 		sum += per_cpu(nr_dentry_neg, i);
+#ifdef CONFIG_DCACHE_LIMIT_NEG_ENTRY
 	sum += neg_dentry_nfree_init - ndblk.nfree;
+#endif
 	return sum < 0 ? 0 : sum;
 }
 
@@ -267,6 +271,7 @@  static inline int dentry_string_cmp(const unsigned char *cs, const unsigned char
 
 #endif
 
+#ifdef CONFIG_DCACHE_LIMIT_NEG_ENTRY
 /*
  * Decrement negative dentry count if applicable.
  */
@@ -289,12 +294,6 @@  static void __neg_dentry_dec(struct dentry *dentry)
 	}
 }
 
-static inline void neg_dentry_dec(struct dentry *dentry)
-{
-	if (unlikely(d_is_negative(dentry)))
-		__neg_dentry_dec(dentry);
-}
-
 /*
  * Try to decrement the negative dentry free pool by NEG_DENTRY_BATCH.
  * The actual decrement returned by the function may be smaller.
@@ -454,6 +453,20 @@  int proc_neg_dentry_limit(struct ctl_table *ctl, int write,
 	return 0;
 }
 EXPORT_SYMBOL_GPL(proc_neg_dentry_limit);
+#else /* CONFIG_DCACHE_LIMIT_NEG_ENTRY */
+
+static inline void __neg_dentry_dec(struct dentry *dentry)
+{
+	 this_cpu_dec(nr_dentry_neg);
+}
+
+#endif /* CONFIG_DCACHE_LIMIT_NEG_ENTRY */
+
+static inline void neg_dentry_dec(struct dentry *dentry)
+{
+	if (unlikely(d_is_negative(dentry)))
+		__neg_dentry_dec(dentry);
+}
 
 static inline int dentry_cmp(const struct dentry *dentry, const unsigned char *ct, unsigned tcount)
 {
@@ -642,6 +655,7 @@  static void d_lru_add(struct dentry *dentry)
 	dentry->d_flags |= DCACHE_LRU_LIST;
 	this_cpu_inc(nr_dentry_unused);
 	if (d_is_negative(dentry)) {
+#ifdef CONFIG_DCACHE_LIMIT_NEG_ENTRY
 		if (dentry->d_flags & DCACHE_NEW_NEGATIVE) {
 			dentry->d_flags &= ~DCACHE_NEW_NEGATIVE;
 			if (unlikely(neg_dentry_inc(dentry) < 0)) {
@@ -658,6 +672,7 @@  static void d_lru_add(struct dentry *dentry)
 				&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
 			return;
 		}
+#endif
 		/*
 		 * We don't do limit check for existing negative
 		 * dentries.
@@ -3431,7 +3446,9 @@  static void __init dcache_init(void)
 		SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD|SLAB_ACCOUNT,
 		d_iname);
 
+#ifdef CONFIG_DCACHE_LIMIT_NEG_ENTRY
 	raw_spin_lock_init(&ndblk.nfree_lock);
+#endif
 
 	/* Hash may have been set up in dcache_init_early */
 	if (!hashdist)
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 934a6d9..11729a1 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -612,10 +612,12 @@  struct name_snapshot {
 void take_dentry_name_snapshot(struct name_snapshot *, struct dentry *);
 void release_dentry_name_snapshot(struct name_snapshot *);
 
+#ifdef CONFIG_DCACHE_LIMIT_NEG_ENTRY
 /*
  * Negative dentry related declarations.
  */
 extern int neg_dentry_limit;
 extern int neg_dentry_enforce;
+#endif
 
 #endif	/* __LINUX_DCACHE_H */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index a24101e..732c624 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1851,6 +1851,7 @@  static int sysrq_sysctl_handler(struct ctl_table *table, int write,
 		.proc_handler	= proc_dointvec_minmax,
 		.extra1		= &one,
 	},
+#ifdef CONFIG_DCACHE_LIMIT_NEG_ENTRY
 	{
 		.procname	= "neg-dentry-limit",
 		.data		= &neg_dentry_limit,
@@ -1869,6 +1870,7 @@  static int sysrq_sysctl_handler(struct ctl_table *table, int write,
 		.extra1		= &zero,
 		.extra2		= &one,
 	},
+#endif
 	{ }
 };