Received: by 2002:a25:1506:0:0:0:0:0 with SMTP id 6csp3079547ybv; Mon, 24 Feb 2020 17:44:10 -0800 (PST) X-Google-Smtp-Source: APXvYqx0Ya+3Zp6a5aquB5MNqLXb99qFfiJct/bP1mA5cMuk9uQExTjnGeatxF/NcS0pAgxxRKFA X-Received: by 2002:a9d:7ccd:: with SMTP id r13mr41214309otn.56.1582595049986; Mon, 24 Feb 2020 17:44:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1582595049; cv=none; d=google.com; s=arc-20160816; b=gPH8so4/+uGPnSMIjERUQfXRIieWDU/T/jk5Vb6kYwpe6vSL9zIhTxWd+h15pi1IaG mZXk21zwBbpSGfZoRFozWQGR/fEOS1BGTi4wM5SMd1h63OU1xeOAW1XEgYHexMBMY+E2 A/79Blwc6fLwZRxggw8lpjjB/jC09Qu3blZspffRlGnl1a/kuQXj4OfG18QTD6biOLWb WTsZYJW/2vzZ8Q7VSbsC1nyGJuP84EvOn9EtTCVo6ji3P69qWTauvkP/H+BqDnZuXpSB sEwHyd0+4qt0Y4lxaLmNvcPs/XV8RAiISsEVry5uP4bulNoZoElzaQwasrs/l1sxoei+ 2laQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:message-id:date:subject:cc :to:from; bh=4OnnLOm+0893oqSYjRGs75abuvoXChjJxnmOHqdSBd8=; b=eHjozwEu+CPdyLw+kNMT6iIViF0Ka0Y58L6GjWLJkaVKV6Xb6rS2MHmCkw0NLXqXm0 8Iq8Ea8fqZHo4vXjUkojDcUPueYNUVjIFA6VAzqrTk0o1hbizy2R2A7FKj85TxTEn+wO q2UrI680/HtEMIdhuGG3JS7o/L8noIm7BKSetro2GsxAPXKCbOaFxS9D6GAfAfXGIdTl 6bOW/ekjs8OoKQMEC0G6ewgYEbQvKsuZSmj1Y1adkAsH59DnbnF1epjJJCpmKvSKkOr+ RLPCgFC3lnOYMXb168RxOG2+IksqmuMx3YPu6hhra9UsqYhU5Dw1XSg51C5GEw4rml7R STxg== 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 c18si10047750ots.317.2020.02.24.17.43.57; Mon, 24 Feb 2020 17:44:09 -0800 (PST) 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 S1728546AbgBYBnX (ORCPT + 99 others); Mon, 24 Feb 2020 20:43:23 -0500 Received: from szxga06-in.huawei.com ([45.249.212.32]:34746 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726962AbgBYBnX (ORCPT ); Mon, 24 Feb 2020 20:43:23 -0500 Received: from DGGEMS409-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id 2020AE18E1B2C497C114; Tue, 25 Feb 2020 09:43:20 +0800 (CST) Received: from szvp000203569.huawei.com (10.120.216.130) by DGGEMS409-HUB.china.huawei.com (10.3.19.209) with Microsoft SMTP Server id 14.3.439.0; Tue, 25 Feb 2020 09:43:14 +0800 From: Chao Yu To: CC: , , , Chao Yu , Park Ju Hyung Subject: [PATCH] f2fs: use kmem_cache pool during inline xattr lookups Date: Tue, 25 Feb 2020 09:42:57 +0800 Message-ID: <20200225014257.83903-1-yuchao0@huawei.com> X-Mailer: git-send-email 2.18.0.rc1 MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.120.216.130] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org It's been observed that kzalloc() on lookup_all_xattrs() are called millions of times on Android, quickly becoming the top abuser of slub memory allocator. Use a dedicated kmem cache pool for xattr lookups to mitigate this. Signed-off-by: Park Ju Hyung Signed-off-by: Chao Yu --- Hi, Ju Hyung, Let me know if you have any objection on this patch. :) fs/f2fs/f2fs.h | 3 +++ fs/f2fs/super.c | 10 ++++++++- fs/f2fs/xattr.c | 54 ++++++++++++++++++++++++++++++++++++++++++++----- fs/f2fs/xattr.h | 4 ++++ 4 files changed, 65 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 12a197e89a3e..23b93a116c73 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1486,6 +1486,9 @@ struct f2fs_sb_info { __u32 s_chksum_seed; struct workqueue_struct *post_read_wq; /* post read workqueue */ + + struct kmem_cache *inline_xattr_slab; /* inline xattr entry */ + unsigned int inline_xattr_slab_size; /* default inline xattr slab size */ }; struct f2fs_private_dio { diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index d241e07c0bfa..0b16204d3b7d 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1201,6 +1201,7 @@ static void f2fs_put_super(struct super_block *sb) kvfree(sbi->raw_super); destroy_device_list(sbi); + f2fs_destroy_xattr_caches(sbi); mempool_destroy(sbi->write_io_dummy); #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) @@ -3457,12 +3458,17 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) } } + /* init per sbi slab cache */ + err = f2fs_init_xattr_caches(sbi); + if (err) + goto free_io_dummy; + /* get an inode for meta space */ sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi)); if (IS_ERR(sbi->meta_inode)) { f2fs_err(sbi, "Failed to read F2FS meta data inode"); err = PTR_ERR(sbi->meta_inode); - goto free_io_dummy; + goto free_xattr_cache; } err = f2fs_get_valid_checkpoint(sbi); @@ -3735,6 +3741,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) make_bad_inode(sbi->meta_inode); iput(sbi->meta_inode); sbi->meta_inode = NULL; +free_xattr_cache: + f2fs_destroy_xattr_caches(sbi); free_io_dummy: mempool_destroy(sbi->write_io_dummy); free_percpu: diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index a3360a97e624..e46a10eb0e42 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -23,6 +23,25 @@ #include "xattr.h" #include "segment.h" +static void *xattr_alloc(struct f2fs_sb_info *sbi, int size, bool *is_inline) +{ + *is_inline = (size == sbi->inline_xattr_slab_size); + + if (*is_inline) + return kmem_cache_zalloc(sbi->inline_xattr_slab, GFP_NOFS); + + return f2fs_kzalloc(sbi, size, GFP_NOFS); +} + +static void xattr_free(struct f2fs_sb_info *sbi, void *xattr_addr, + bool is_inline) +{ + if (is_inline) + kmem_cache_free(sbi->inline_xattr_slab, xattr_addr); + else + kvfree(xattr_addr); +} + static int f2fs_xattr_generic_get(const struct xattr_handler *handler, struct dentry *unused, struct inode *inode, const char *name, void *buffer, size_t size) @@ -301,7 +320,8 @@ static int read_xattr_block(struct inode *inode, void *txattr_addr) static int lookup_all_xattrs(struct inode *inode, struct page *ipage, unsigned int index, unsigned int len, const char *name, struct f2fs_xattr_entry **xe, - void **base_addr, int *base_size) + void **base_addr, int *base_size, + bool *is_inline) { void *cur_addr, *txattr_addr, *last_txattr_addr; void *last_addr = NULL; @@ -313,7 +333,7 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage, return -ENODATA; *base_size = XATTR_SIZE(inode) + XATTR_PADDING_SIZE; - txattr_addr = f2fs_kzalloc(F2FS_I_SB(inode), *base_size, GFP_NOFS); + txattr_addr = xattr_alloc(F2FS_I_SB(inode), *base_size, is_inline); if (!txattr_addr) return -ENOMEM; @@ -362,7 +382,7 @@ static int lookup_all_xattrs(struct inode *inode, struct page *ipage, *base_addr = txattr_addr; return 0; out: - kvfree(txattr_addr); + xattr_free(F2FS_I_SB(inode), txattr_addr, *is_inline); return err; } @@ -499,6 +519,7 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name, unsigned int size, len; void *base_addr = NULL; int base_size; + bool is_inline; if (name == NULL) return -EINVAL; @@ -509,7 +530,7 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name, down_read(&F2FS_I(inode)->i_xattr_sem); error = lookup_all_xattrs(inode, ipage, index, len, name, - &entry, &base_addr, &base_size); + &entry, &base_addr, &base_size, &is_inline); up_read(&F2FS_I(inode)->i_xattr_sem); if (error) return error; @@ -532,7 +553,7 @@ int f2fs_getxattr(struct inode *inode, int index, const char *name, } error = size; out: - kvfree(base_addr); + xattr_free(F2FS_I_SB(inode), base_addr, is_inline); return error; } @@ -767,3 +788,26 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name, f2fs_update_time(sbi, REQ_TIME); return err; } + +int f2fs_init_xattr_caches(struct f2fs_sb_info *sbi) +{ + dev_t dev = sbi->sb->s_bdev->bd_dev; + char slab_name[32]; + + sprintf(slab_name, "f2fs_xattr_entry-%u:%u", MAJOR(dev), MINOR(dev)); + + sbi->inline_xattr_slab_size = F2FS_OPTION(sbi).inline_xattr_size * + sizeof(__le32) + XATTR_PADDING_SIZE; + + sbi->inline_xattr_slab = f2fs_kmem_cache_create(slab_name, + sbi->inline_xattr_slab_size); + if (!sbi->inline_xattr_slab) + return -ENOMEM; + + return 0; +} + +void f2fs_destroy_xattr_caches(struct f2fs_sb_info *sbi) +{ + kmem_cache_destroy(sbi->inline_xattr_slab); +} diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h index 574beea46494..7345dfa7b7a9 100644 --- a/fs/f2fs/xattr.h +++ b/fs/f2fs/xattr.h @@ -131,6 +131,8 @@ extern int f2fs_setxattr(struct inode *, int, const char *, extern int f2fs_getxattr(struct inode *, int, const char *, void *, size_t, struct page *); extern ssize_t f2fs_listxattr(struct dentry *, char *, size_t); +extern int f2fs_init_xattr_caches(struct f2fs_sb_info *); +extern void f2fs_destroy_xattr_caches(struct f2fs_sb_info *); #else #define f2fs_xattr_handlers NULL @@ -151,6 +153,8 @@ static inline ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, { return -EOPNOTSUPP; } +static int f2fs_init_xattr_caches(struct f2fs_sb_info *sbi) { return 0; } +static void f2fs_destroy_xattr_caches(struct f2fs_sb_info *sbi) { return 0; } #endif #ifdef CONFIG_F2FS_FS_SECURITY -- 2.18.0.rc1