From: Gao Xiang <gaoxiang25@huawei.com> To: Alexander Viro <viro@zeniv.linux.org.uk>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Andrew Morton <akpm@linux-foundation.org>, Stephen Rothwell <sfr@canb.auug.org.au>, Theodore Ts'o <tytso@mit.edu>, David Sterba <dsterba@suse.cz>, Amir Goldstein <amir73il@gmail.com>, Christoph Hellwig <hch@infradead.org>, "Darrick J . Wong" <darrick.wong@oracle.com>, Dave Chinner <david@fromorbit.com>, Jaegeuk Kim <jaegeuk@kernel.org>, Jan Kara <jack@suse.cz>, Linus Torvalds <torvalds@linux-foundation.org> Cc: <linux-fsdevel@vger.kernel.org>, <devel@driverdev.osuosl.org>, LKML <linux-kernel@vger.kernel.org>, <linux-erofs@lists.ozlabs.org>, Chao Yu <yuchao0@huawei.com>, Miao Xie <miaoxie@huawei.com>, Li Guifu <bluce.liguifu@huawei.com>, Fang Wei <fangwei1@huawei.com>, Gao Xiang <gaoxiang25@huawei.com> Subject: [PATCH v5 15/24] erofs: introduce erofs shrinker Date: Tue, 30 Jul 2019 15:14:04 +0800 [thread overview] Message-ID: <20190730071413.11871-16-gaoxiang25@huawei.com> (raw) In-Reply-To: <20190730071413.11871-1-gaoxiang25@huawei.com> This patch adds a dedicated shrinker targeting to free unneeded memory consumed by a number of erofs in-memory data structures. Like F2FS and UBIFS, it also adds: - sbi->umount_mutex to avoid races on shrinker and put_super; - sbi->shrinker_run_no to not revisit recently scanned objects. Signed-off-by: Gao Xiang <gaoxiang25@huawei.com> --- fs/erofs/internal.h | 7 ++++ fs/erofs/super.c | 6 +++ fs/erofs/utils.c | 93 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 0eef3ee43a76..92de96b6a8c5 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -64,6 +64,9 @@ struct erofs_sb_info { #ifdef CONFIG_EROFS_FS_ZIP /* list for all registered superblocks, mainly for shrinker */ struct list_head list; + struct mutex umount_mutex; + + unsigned int shrinker_run_no; #endif /* CONFIG_EROFS_FS_ZIP */ u32 blocks; u32 meta_blkaddr; @@ -407,9 +410,13 @@ extern const struct file_operations erofs_dir_fops; #ifdef CONFIG_EROFS_FS_ZIP void erofs_shrinker_register(struct super_block *sb); void erofs_shrinker_unregister(struct super_block *sb); +int __init erofs_init_shrinker(void); +void erofs_exit_shrinker(void); #else static inline void erofs_shrinker_register(struct super_block *sb) {} static inline void erofs_shrinker_unregister(struct super_block *sb) {} +static inline int erofs_init_shrinker(void) { return 0; } +static inline void erofs_exit_shrinker(void) {} #endif /* !CONFIG_EROFS_FS_ZIP */ #endif /* __EROFS_INTERNAL_H */ diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 2eca3b25db75..09992cc3b2fd 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -413,6 +413,9 @@ static int __init erofs_module_init(void) if (err) goto icache_err; + err = erofs_init_shrinker(); + if (err) + goto shrinker_err; err = register_filesystem(&erofs_fs_type); if (err) goto fs_err; @@ -421,6 +424,8 @@ static int __init erofs_module_init(void) return 0; fs_err: + erofs_exit_shrinker(); +shrinker_err: erofs_exit_inode_cache(); icache_err: return err; @@ -429,6 +434,7 @@ static int __init erofs_module_init(void) static void __exit erofs_module_exit(void) { unregister_filesystem(&erofs_fs_type); + erofs_exit_shrinker(); erofs_exit_inode_cache(); infoln("successfully finalize erofs"); } diff --git a/fs/erofs/utils.c b/fs/erofs/utils.c index 791b2df1f761..cab7d77c4e59 100644 --- a/fs/erofs/utils.c +++ b/fs/erofs/utils.c @@ -9,6 +9,12 @@ #include "internal.h" #ifdef CONFIG_EROFS_FS_ZIP +/* global shrink count (for all mounted EROFS instances) */ +static atomic_long_t erofs_global_shrink_cnt; + +/* protected by 'erofs_sb_list_lock' */ +static unsigned int shrinker_run_no; + /* protects the mounted 'erofs_sb_list' */ static DEFINE_SPINLOCK(erofs_sb_list_lock); static LIST_HEAD(erofs_sb_list); @@ -17,6 +23,8 @@ void erofs_shrinker_register(struct super_block *sb) { struct erofs_sb_info *sbi = EROFS_SB(sb); + mutex_init(&sbi->umount_mutex); + spin_lock(&erofs_sb_list_lock); list_add(&sbi->list, &erofs_sb_list); spin_unlock(&erofs_sb_list_lock); @@ -24,9 +32,92 @@ void erofs_shrinker_register(struct super_block *sb) void erofs_shrinker_unregister(struct super_block *sb) { + struct erofs_sb_info *const sbi = EROFS_SB(sb); + + mutex_lock(&sbi->umount_mutex); + /* will add shrink final handler here */ + + spin_lock(&erofs_sb_list_lock); + list_del(&sbi->list); + spin_unlock(&erofs_sb_list_lock); + mutex_unlock(&sbi->umount_mutex); +} + +static unsigned long erofs_shrink_count(struct shrinker *shrink, + struct shrink_control *sc) +{ + return atomic_long_read(&erofs_global_shrink_cnt); +} + +static unsigned long erofs_shrink_scan(struct shrinker *shrink, + struct shrink_control *sc) +{ + struct erofs_sb_info *sbi; + struct list_head *p; + + unsigned long nr = sc->nr_to_scan; + unsigned int run_no; + unsigned long freed = 0; + spin_lock(&erofs_sb_list_lock); - list_del(&EROFS_SB(sb)->list); + do { + run_no = ++shrinker_run_no; + } while (run_no == 0); + + /* Iterate over all mounted superblocks and try to shrink them */ + p = erofs_sb_list.next; + while (p != &erofs_sb_list) { + sbi = list_entry(p, struct erofs_sb_info, list); + + /* + * We move the ones we do to the end of the list, so we stop + * when we see one we have already done. + */ + if (sbi->shrinker_run_no == run_no) + break; + + if (!mutex_trylock(&sbi->umount_mutex)) { + p = p->next; + continue; + } + + spin_unlock(&erofs_sb_list_lock); + sbi->shrinker_run_no = run_no; + + /* will add shrink handler here */ + + spin_lock(&erofs_sb_list_lock); + /* Get the next list element before we move this one */ + p = p->next; + + /* + * Move this one to the end of the list to provide some + * fairness. + */ + list_move_tail(&sbi->list, &erofs_sb_list); + mutex_unlock(&sbi->umount_mutex); + + if (freed >= nr) + break; + } spin_unlock(&erofs_sb_list_lock); + return freed; +} + +static struct shrinker erofs_shrinker_info = { + .scan_objects = erofs_shrink_scan, + .count_objects = erofs_shrink_count, + .seeks = DEFAULT_SEEKS, +}; + +int __init erofs_init_shrinker(void) +{ + return register_shrinker(&erofs_shrinker_info); +} + +void erofs_exit_shrinker(void) +{ + unregister_shrinker(&erofs_shrinker_info); } #endif /* !CONFIG_EROFS_FS_ZIP */ -- 2.17.1
WARNING: multiple messages have this Message-ID (diff)
From: gaoxiang25@huawei.com (Gao Xiang) Subject: [PATCH v5 15/24] erofs: introduce erofs shrinker Date: Tue, 30 Jul 2019 15:14:04 +0800 [thread overview] Message-ID: <20190730071413.11871-16-gaoxiang25@huawei.com> (raw) In-Reply-To: <20190730071413.11871-1-gaoxiang25@huawei.com> This patch adds a dedicated shrinker targeting to free unneeded memory consumed by a number of erofs in-memory data structures. Like F2FS and UBIFS, it also adds: - sbi->umount_mutex to avoid races on shrinker and put_super; - sbi->shrinker_run_no to not revisit recently scanned objects. Signed-off-by: Gao Xiang <gaoxiang25 at huawei.com> --- fs/erofs/internal.h | 7 ++++ fs/erofs/super.c | 6 +++ fs/erofs/utils.c | 93 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h index 0eef3ee43a76..92de96b6a8c5 100644 --- a/fs/erofs/internal.h +++ b/fs/erofs/internal.h @@ -64,6 +64,9 @@ struct erofs_sb_info { #ifdef CONFIG_EROFS_FS_ZIP /* list for all registered superblocks, mainly for shrinker */ struct list_head list; + struct mutex umount_mutex; + + unsigned int shrinker_run_no; #endif /* CONFIG_EROFS_FS_ZIP */ u32 blocks; u32 meta_blkaddr; @@ -407,9 +410,13 @@ extern const struct file_operations erofs_dir_fops; #ifdef CONFIG_EROFS_FS_ZIP void erofs_shrinker_register(struct super_block *sb); void erofs_shrinker_unregister(struct super_block *sb); +int __init erofs_init_shrinker(void); +void erofs_exit_shrinker(void); #else static inline void erofs_shrinker_register(struct super_block *sb) {} static inline void erofs_shrinker_unregister(struct super_block *sb) {} +static inline int erofs_init_shrinker(void) { return 0; } +static inline void erofs_exit_shrinker(void) {} #endif /* !CONFIG_EROFS_FS_ZIP */ #endif /* __EROFS_INTERNAL_H */ diff --git a/fs/erofs/super.c b/fs/erofs/super.c index 2eca3b25db75..09992cc3b2fd 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -413,6 +413,9 @@ static int __init erofs_module_init(void) if (err) goto icache_err; + err = erofs_init_shrinker(); + if (err) + goto shrinker_err; err = register_filesystem(&erofs_fs_type); if (err) goto fs_err; @@ -421,6 +424,8 @@ static int __init erofs_module_init(void) return 0; fs_err: + erofs_exit_shrinker(); +shrinker_err: erofs_exit_inode_cache(); icache_err: return err; @@ -429,6 +434,7 @@ static int __init erofs_module_init(void) static void __exit erofs_module_exit(void) { unregister_filesystem(&erofs_fs_type); + erofs_exit_shrinker(); erofs_exit_inode_cache(); infoln("successfully finalize erofs"); } diff --git a/fs/erofs/utils.c b/fs/erofs/utils.c index 791b2df1f761..cab7d77c4e59 100644 --- a/fs/erofs/utils.c +++ b/fs/erofs/utils.c @@ -9,6 +9,12 @@ #include "internal.h" #ifdef CONFIG_EROFS_FS_ZIP +/* global shrink count (for all mounted EROFS instances) */ +static atomic_long_t erofs_global_shrink_cnt; + +/* protected by 'erofs_sb_list_lock' */ +static unsigned int shrinker_run_no; + /* protects the mounted 'erofs_sb_list' */ static DEFINE_SPINLOCK(erofs_sb_list_lock); static LIST_HEAD(erofs_sb_list); @@ -17,6 +23,8 @@ void erofs_shrinker_register(struct super_block *sb) { struct erofs_sb_info *sbi = EROFS_SB(sb); + mutex_init(&sbi->umount_mutex); + spin_lock(&erofs_sb_list_lock); list_add(&sbi->list, &erofs_sb_list); spin_unlock(&erofs_sb_list_lock); @@ -24,9 +32,92 @@ void erofs_shrinker_register(struct super_block *sb) void erofs_shrinker_unregister(struct super_block *sb) { + struct erofs_sb_info *const sbi = EROFS_SB(sb); + + mutex_lock(&sbi->umount_mutex); + /* will add shrink final handler here */ + + spin_lock(&erofs_sb_list_lock); + list_del(&sbi->list); + spin_unlock(&erofs_sb_list_lock); + mutex_unlock(&sbi->umount_mutex); +} + +static unsigned long erofs_shrink_count(struct shrinker *shrink, + struct shrink_control *sc) +{ + return atomic_long_read(&erofs_global_shrink_cnt); +} + +static unsigned long erofs_shrink_scan(struct shrinker *shrink, + struct shrink_control *sc) +{ + struct erofs_sb_info *sbi; + struct list_head *p; + + unsigned long nr = sc->nr_to_scan; + unsigned int run_no; + unsigned long freed = 0; + spin_lock(&erofs_sb_list_lock); - list_del(&EROFS_SB(sb)->list); + do { + run_no = ++shrinker_run_no; + } while (run_no == 0); + + /* Iterate over all mounted superblocks and try to shrink them */ + p = erofs_sb_list.next; + while (p != &erofs_sb_list) { + sbi = list_entry(p, struct erofs_sb_info, list); + + /* + * We move the ones we do to the end of the list, so we stop + * when we see one we have already done. + */ + if (sbi->shrinker_run_no == run_no) + break; + + if (!mutex_trylock(&sbi->umount_mutex)) { + p = p->next; + continue; + } + + spin_unlock(&erofs_sb_list_lock); + sbi->shrinker_run_no = run_no; + + /* will add shrink handler here */ + + spin_lock(&erofs_sb_list_lock); + /* Get the next list element before we move this one */ + p = p->next; + + /* + * Move this one to the end of the list to provide some + * fairness. + */ + list_move_tail(&sbi->list, &erofs_sb_list); + mutex_unlock(&sbi->umount_mutex); + + if (freed >= nr) + break; + } spin_unlock(&erofs_sb_list_lock); + return freed; +} + +static struct shrinker erofs_shrinker_info = { + .scan_objects = erofs_shrink_scan, + .count_objects = erofs_shrink_count, + .seeks = DEFAULT_SEEKS, +}; + +int __init erofs_init_shrinker(void) +{ + return register_shrinker(&erofs_shrinker_info); +} + +void erofs_exit_shrinker(void) +{ + unregister_shrinker(&erofs_shrinker_info); } #endif /* !CONFIG_EROFS_FS_ZIP */ -- 2.17.1
next prev parent reply other threads:[~2019-07-30 7:15 UTC|newest] Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-07-30 7:13 [PATCH v5 00/24] erofs: promote erofs from staging Gao Xiang 2019-07-30 7:13 ` Gao Xiang 2019-07-30 7:13 ` [PATCH v5 01/24] erofs: add on-disk layout Gao Xiang 2019-07-30 7:13 ` Gao Xiang 2019-07-30 7:13 ` [PATCH v5 02/24] erofs: add erofs in-memory stuffs Gao Xiang 2019-07-30 7:13 ` Gao Xiang 2019-07-30 7:13 ` [PATCH v5 03/24] erofs: add super block operations Gao Xiang 2019-07-30 7:13 ` Gao Xiang 2019-07-30 7:13 ` [PATCH v5 04/24] erofs: add raw address_space operations Gao Xiang 2019-07-30 7:13 ` Gao Xiang 2019-07-30 7:13 ` Gao Xiang 2019-07-30 7:13 ` [PATCH v5 05/24] erofs: add inode operations Gao Xiang 2019-07-30 7:13 ` Gao Xiang 2019-07-30 7:13 ` [PATCH v5 06/24] erofs: support special inode Gao Xiang 2019-07-30 7:13 ` Gao Xiang 2019-07-30 7:13 ` [PATCH v5 07/24] erofs: add directory operations Gao Xiang 2019-07-30 7:13 ` Gao Xiang 2019-07-30 7:13 ` [PATCH v5 08/24] erofs: add namei functions Gao Xiang 2019-07-30 7:13 ` Gao Xiang 2019-07-30 7:13 ` [PATCH v5 09/24] erofs: support tracepoint Gao Xiang 2019-07-30 7:13 ` Gao Xiang 2019-07-30 7:13 ` [PATCH v5 10/24] erofs: update Kconfig and Makefile Gao Xiang 2019-07-30 7:13 ` Gao Xiang 2019-07-30 7:14 ` [PATCH v5 11/24] erofs: introduce xattr & posixacl support Gao Xiang 2019-07-30 7:14 ` Gao Xiang 2019-07-30 7:14 ` [PATCH v5 12/24] erofs: introduce tagged pointer Gao Xiang 2019-07-30 7:14 ` Gao Xiang 2019-07-31 13:01 ` Jan Kara 2019-07-31 13:01 ` Jan Kara 2019-07-31 13:20 ` Gao Xiang 2019-07-31 13:20 ` Gao Xiang 2019-07-31 13:30 ` Gao Xiang 2019-07-31 13:30 ` Gao Xiang 2019-07-31 13:52 ` Gao Xiang 2019-07-31 13:52 ` Gao Xiang 2019-07-30 7:14 ` [PATCH v5 13/24] erofs: add compression indexes support Gao Xiang 2019-07-30 7:14 ` Gao Xiang 2019-07-30 7:14 ` [PATCH v5 14/24] erofs: introduce superblock registration Gao Xiang 2019-07-30 7:14 ` Gao Xiang 2019-07-30 7:14 ` Gao Xiang [this message] 2019-07-30 7:14 ` [PATCH v5 15/24] erofs: introduce erofs shrinker Gao Xiang 2019-07-30 7:14 ` [PATCH v5 16/24] erofs: introduce workstation for decompression Gao Xiang 2019-07-30 7:14 ` Gao Xiang 2019-07-30 7:14 ` [PATCH v5 17/24] erofs: introduce per-CPU buffers implementation Gao Xiang 2019-07-30 7:14 ` Gao Xiang 2019-07-30 7:14 ` [PATCH v5 18/24] erofs: introduce pagevec for decompression subsystem Gao Xiang 2019-07-30 7:14 ` Gao Xiang 2019-07-30 7:14 ` [PATCH v5 19/24] erofs: add erofs_allocpage() Gao Xiang 2019-07-30 7:14 ` Gao Xiang 2019-07-30 7:14 ` [PATCH v5 20/24] erofs: introduce generic decompression backend Gao Xiang 2019-07-30 7:14 ` Gao Xiang 2019-07-30 7:14 ` [PATCH v5 21/24] erofs: introduce LZ4 decompression inplace Gao Xiang 2019-07-30 7:14 ` Gao Xiang 2019-07-30 7:14 ` [PATCH v5 22/24] erofs: introduce the decompression frontend Gao Xiang 2019-07-30 7:14 ` Gao Xiang 2019-07-30 7:14 ` [PATCH v5 23/24] erofs: introduce cached decompression Gao Xiang 2019-07-30 7:14 ` Gao Xiang 2019-07-30 7:14 ` [PATCH v5 24/24] erofs: add document Gao Xiang 2019-07-30 7:14 ` Gao Xiang
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20190730071413.11871-16-gaoxiang25@huawei.com \ --to=gaoxiang25@huawei.com \ --cc=akpm@linux-foundation.org \ --cc=amir73il@gmail.com \ --cc=bluce.liguifu@huawei.com \ --cc=darrick.wong@oracle.com \ --cc=david@fromorbit.com \ --cc=devel@driverdev.osuosl.org \ --cc=dsterba@suse.cz \ --cc=fangwei1@huawei.com \ --cc=gregkh@linuxfoundation.org \ --cc=hch@infradead.org \ --cc=jack@suse.cz \ --cc=jaegeuk@kernel.org \ --cc=linux-erofs@lists.ozlabs.org \ --cc=linux-fsdevel@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=miaoxie@huawei.com \ --cc=sfr@canb.auug.org.au \ --cc=torvalds@linux-foundation.org \ --cc=tytso@mit.edu \ --cc=viro@zeniv.linux.org.uk \ --cc=yuchao0@huawei.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.