RE: [PATCH] fs/dcache: dentries should free after files unlinked or directories removed

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




> -----Original Message-----
> From: Wangkai (Kevin,C)
> Sent: Monday, August 07, 2017 5:55 PM
> To: linux-fsdevel@xxxxxxxxxxxxxxx; viro@xxxxxxxxxxxxxxxxxx
> Cc: Wangkai (Kevin,C); Renjinyong (Renjinyong, Business Support Dept)
> Subject: [PATCH] fs/dcache: dentries should free after files unlinked or
> directories removed
> 
> sometimes, on my server, there were lots of files creating and removing, and I
> found that memory usage were high, and I checked, almost all the memory was
> occupied by slab recliamable, the slab struct was dentry, and I checked the
> code of dcache, and found that when a file was deleted the dentry never free,
> unless a memory recliam was triggerd.
> 
> I made this patch to mark the dentry as a remove state after file unlinked or
> directory removed, and when the dentry’s reference count dec to zero and
> free it, and it worked well on my server base on kernel 4.4.
> 
> 
> Signed-off-by: Wangkai <wangkai86@xxxxxxxxxx>
> ---
>  fs/dcache.c            | 12 +++++++++++-
>  fs/namei.c             |  6 ++++++
>  include/linux/dcache.h |  2 +-
>  3 files changed, 18 insertions(+), 2 deletions(-)
>  mode change 100644 => 100755 fs/dcache.c
>  mode change 100644 => 100755 fs/namei.c
>  mode change 100644 => 100755 include/linux/dcache.h
> 
> diff --git a/fs/dcache.c b/fs/dcache.c
> old mode 100644
> new mode 100755
> index f901413..6828463
> --- a/fs/dcache.c
> +++ b/fs/dcache.c
> @@ -722,7 +722,8 @@ static inline bool fast_dput(struct dentry *dentry)
>  	 */
>  	smp_rmb();
>  	d_flags = ACCESS_ONCE(dentry->d_flags);
> -	d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST |
> DCACHE_DISCONNECTED;
> +	d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST |
> DCACHE_DISCONNECTED
> +		| DCACHE_FILE_REMOVED;
> 
>  	/* Nothing to do? Dropping the reference was all we needed? */
>  	if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST)
> && !d_unhashed(dentry))
> @@ -816,6 +817,15 @@ void dput(struct dentry *dentry)
>  	dentry_lru_add(dentry);
> 
>  	dentry->d_lockref.count--;
> +
> +	/*
> +	 * if file has been declare as removed and reference count is zero
> +	 * then we can free the dentry rather than leave it stay in dcache
> +	 */
> +	if (unlikely(dentry->d_flags & DCACHE_FILE_REMOVED)) {
> +		if (dentry->d_lockref.count == 0)
> +			goto kill_it;
> +	}
>  	spin_unlock(&dentry->d_lock);
>  	return;
> 
> diff --git a/fs/namei.c b/fs/namei.c
> old mode 100644
> new mode 100755
> index ddb6a7c..0ec1478
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -3918,6 +3918,9 @@ static long do_rmdir(int dfd, const char __user
> *pathname)
>  		goto exit3;
>  	error = vfs_rmdir(path.dentry->d_inode, dentry);
>  exit3:


> +	/* after remove the dir set dentry remove flag */
> +	if (!error)
> +		dentry->d_flags |= DCACHE_FILE_REMOVED;
>  	dput(dentry);
>  exit2:
>  	inode_unlock(path.dentry->d_inode);
> @@ -4042,6 +4045,9 @@ static long do_unlinkat(int dfd, const char __user
> *pathname)
>  			goto exit2;
>  		error = vfs_unlink(path.dentry->d_inode, dentry, &delegated_inode);
>  exit2:
> +		/* after unlink file set dentry remove flag */
> +		if (!error)
> +			dentry->d_flags |= DCACHE_FILE_REMOVED;
>  		dput(dentry);
>  	}
>  	inode_unlock(path.dentry->d_inode);
> diff --git a/include/linux/dcache.h b/include/linux/dcache.h
> old mode 100644
> new mode 100755
> index aae1cdb..2d65bd6
> --- a/include/linux/dcache.h
> +++ b/include/linux/dcache.h
> @@ -215,7 +215,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_FILE_REMOVED		0x08000000 /* file or dir has been
> unlinked or removed */
>  #define DCACHE_PAR_LOOKUP		0x10000000 /* being looked up (with
> parent locked shared) */
>  #define DCACHE_DENTRY_CURSOR		0x20000000
> 
> --
> 2.8.0.GIT

Hi, all
The negative dentries keep growing and waste a lots of kernel memory, this problem has been
Occurred on my server, and I looked for internet, and many people had met the same problem.
Recently, I discussed with Longman, we have two different patches to solve this problem,
In my patch, remove the negative dentries with the files unlinked, I checked 15 years ago,
Viro and linus had talked about this, that unlink was only worth doing.
  ref:   http://yarchive.net/comp/linux/negative_dentries.html
in Longman patch, limit the negative dentries number
maybe we can discuss.

Thanks,
Kevin





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux