Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp386737imm; Thu, 26 Jul 2018 05:30:38 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfro+zhhnxgAXpA+qUqZTWHdMqO4LQ7FDv99dIcB2Cb1OQW8knl7tMVKZmodbkYqLqiVP9d X-Received: by 2002:a63:571d:: with SMTP id l29-v6mr1734861pgb.296.1532608238032; Thu, 26 Jul 2018 05:30:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1532608238; cv=none; d=google.com; s=arc-20160816; b=UWyu3b/zPOren6cbD+pidO22d4NcgazLAdTakl72+3jvh3sL7x8/O9AS/3gUysTnUp Fxz6bxv5Fym2yyE5WR2l3C8msDntpwPiULcdNbDZYdURGuUICvCMxKWRZ/d6mDDj78+H Li3drh4qzUN01AEQO39f1dVhn1lNutn2g/Kp0+168MYrV9aotEz2da3qrBNEljDZd7Yv k+YZJPjGR8HhlT3DjH6DEPmeCkepjt0jJRW2IrSB+1F6EIaYzmojMZHvt0Z7xLFq2qJ4 rCUBqop6Z0nKFoDuNbtR6yGvNHFD9lGHCvvjZaMBZPSJMI89PL7htNQGx1UZXyO/g9HJ BuqA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=55B8kJMhPMAUUca1iVA/2TrKKzbiBQli+vhwhRncd/k=; b=aZ0DE9pAq6voq2ADNPsGGBEFmjFoSqRpzzfustTNSZVQEVcfrZ/54Uf+oo6azomuAM JwZTUbLaiJTIUanDHswFmsx7WF7HAF8tbuD52mpJTuat8YqaxGG0Ld6rvhDwrIWex7H0 5fNCTknBRwQcEtQShtiLcaXDuRWcd3FgfFYmfCJOkr7k5pv5QnfEdjzQ9ZGzhZnCzxLv j28mSsr/M5N8KlKzzgqiArU0DyMQbgAaaSiqRWkbfoORd6buEIcATnVN3hp8+HNqLxKw 0/555UuiYBXv4CrNtJvGH4gDSfm1+aTHgnABwrQmKWFAI8AQDRErxYGljg95Me1jdXzm PwDg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i24-v6si1277045pgj.228.2018.07.26.05.30.23; Thu, 26 Jul 2018 05:30:38 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731735AbeGZNpF (ORCPT + 99 others); Thu, 26 Jul 2018 09:45:05 -0400 Received: from szxga04-in.huawei.com ([45.249.212.190]:10136 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729915AbeGZNpF (ORCPT ); Thu, 26 Jul 2018 09:45:05 -0400 Received: from DGGEMS408-HUB.china.huawei.com (unknown [172.30.72.60]) by Forcepoint Email with ESMTP id BDF9B7B6C94E9; Thu, 26 Jul 2018 20:28:22 +0800 (CST) Received: from szvp000100637.huawei.com (10.162.55.131) by smtp.huawei.com (10.3.19.208) with Microsoft SMTP Server (TLS) id 14.3.382.0; Thu, 26 Jul 2018 20:28:15 +0800 From: Gao Xiang To: Greg Kroah-Hartman , CC: , , , , , , , , Gao Xiang Subject: [PATCH 21/25] staging: erofs: introduce erofs shrinker Date: Thu, 26 Jul 2018 20:22:04 +0800 Message-ID: <1532607728-103372-22-git-send-email-gaoxiang25@huawei.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1532607728-103372-1-git-send-email-gaoxiang25@huawei.com> References: <1527764767-22190-1-git-send-email-gaoxiang25@huawei.com> <1532607728-103372-1-git-send-email-gaoxiang25@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.162.55.131] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 scaned objects Signed-off-by: Gao Xiang --- drivers/staging/erofs/internal.h | 7 ++++ drivers/staging/erofs/super.c | 15 +++++++ drivers/staging/erofs/utils.c | 85 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 101 insertions(+), 6 deletions(-) diff --git a/drivers/staging/erofs/internal.h b/drivers/staging/erofs/internal.h index 18e7b9c..42455f0 100644 --- a/drivers/staging/erofs/internal.h +++ b/drivers/staging/erofs/internal.h @@ -66,6 +66,7 @@ struct erofs_fault_info { struct erofs_sb_info { /* list for all registered superblocks, mainly for shrinker */ struct list_head list; + struct mutex umount_mutex; u32 blocks; u32 meta_blkaddr; @@ -93,6 +94,7 @@ struct erofs_sb_info { char *dev_name; unsigned int mount_opt; + unsigned int shrinker_run_no; #ifdef CONFIG_EROFS_FAULT_INJECTION struct erofs_fault_info fault_info; /* For fault injection */ @@ -416,6 +418,11 @@ static inline void erofs_vunmap(const void *mem, unsigned int count) extern void erofs_register_super(struct super_block *sb); extern void erofs_unregister_super(struct super_block *sb); +extern unsigned long erofs_shrink_count(struct shrinker *shrink, + struct shrink_control *sc); +extern unsigned long erofs_shrink_scan(struct shrinker *shrink, + struct shrink_control *sc); + #ifndef lru_to_page #define lru_to_page(head) (list_entry((head)->prev, struct page, lru)) #endif diff --git a/drivers/staging/erofs/super.c b/drivers/staging/erofs/super.c index f455d71..ef85884 100644 --- a/drivers/staging/erofs/super.c +++ b/drivers/staging/erofs/super.c @@ -375,7 +375,9 @@ static void erofs_put_super(struct super_block *sb) infoln("unmounted for %s", sbi->dev_name); __putname(sbi->dev_name); + mutex_lock(&sbi->umount_mutex); erofs_unregister_super(sb); + mutex_unlock(&sbi->umount_mutex); kfree(sbi); sb->s_fs_info = NULL; @@ -415,6 +417,12 @@ static void erofs_kill_sb(struct super_block *sb) kill_block_super(sb); } +static struct shrinker erofs_shrinker_info = { + .scan_objects = erofs_shrink_scan, + .count_objects = erofs_shrink_count, + .seeks = DEFAULT_SEEKS, +}; + static struct file_system_type erofs_fs_type = { .owner = THIS_MODULE, .name = "erofs", @@ -435,6 +443,10 @@ static int __init erofs_module_init(void) if (err) goto icache_err; + err = register_shrinker(&erofs_shrinker_info); + if (err) + goto shrinker_err; + err = register_filesystem(&erofs_fs_type); if (err) goto fs_err; @@ -443,6 +455,8 @@ static int __init erofs_module_init(void) return 0; fs_err: + unregister_shrinker(&erofs_shrinker_info); +shrinker_err: erofs_exit_inode_cache(); icache_err: return err; @@ -451,6 +465,7 @@ static int __init erofs_module_init(void) static void __exit erofs_module_exit(void) { unregister_filesystem(&erofs_fs_type); + unregister_shrinker(&erofs_shrinker_info); erofs_exit_inode_cache(); infoln("successfully finalize erofs"); } diff --git a/drivers/staging/erofs/utils.c b/drivers/staging/erofs/utils.c index 6748def..c1d83ce 100644 --- a/drivers/staging/erofs/utils.c +++ b/drivers/staging/erofs/utils.c @@ -29,20 +29,93 @@ struct page *erofs_allocpage(struct list_head *pool, gfp_t gfp) return page; } -static DEFINE_MUTEX(erofs_sb_list_lock); + +/* 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); +/* global shrink count (for all mounted EROFS instances) */ +static atomic_long_t erofs_global_shrink_cnt; + void erofs_register_super(struct super_block *sb) { - mutex_lock(&erofs_sb_list_lock); - list_add(&EROFS_SB(sb)->list, &erofs_sb_list); - mutex_unlock(&erofs_sb_list_lock); + 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); } void erofs_unregister_super(struct super_block *sb) { - mutex_lock(&erofs_sb_list_lock); + spin_lock(&erofs_sb_list_lock); list_del(&EROFS_SB(sb)->list); - mutex_unlock(&erofs_sb_list_lock); + spin_unlock(&erofs_sb_list_lock); +} + +unsigned long erofs_shrink_count(struct shrinker *shrink, + struct shrink_control *sc) +{ + return atomic_long_read(&erofs_global_shrink_cnt); +} + +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); + 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; + + /* add scan handlers 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; } -- 1.9.1