From patchwork Mon Nov 28 08:58:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: qixiaoyu1 X-Patchwork-Id: 26588 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp5528138wrr; Mon, 28 Nov 2022 01:09:24 -0800 (PST) X-Google-Smtp-Source: AA0mqf4IilbOScgQNkje/G59ht+ijE2Nf4SGYpW82WkwsFaZAUbjj0gPa00LEQNN3NSc9EUio7UF X-Received: by 2002:a05:6402:1655:b0:46a:80cc:d5bd with SMTP id s21-20020a056402165500b0046a80ccd5bdmr19330205edx.210.1669626563993; Mon, 28 Nov 2022 01:09:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669626563; cv=none; d=google.com; s=arc-20160816; b=NpmEdgbf+q770dTj7tZ9RUTk3cN13iGc9L/hqSbvFZUbdud02b+vC9yz5JJntxEwCg giBkMAiswvZ2cYSZIvemrySuMVHkDf5zySjI6+AqX6C0YRgdL6BAzkJae9BpMPWOAs9C rMXFsESfYyq4h482DhaXTUGOY5PY8dXASkVbqwkd6phCVGsyAnXZei3+DWbxzRtC+8hB mRuHpdZjPXzWeHJ7cCuZCxbUn44JxLrHcSwRFTago9IuN8YAQ1gbMJUyjQ4q7Qt7KgqK xS6//IaVdG+pn2pGeV0YsZl+Yo4CSig7bQctTvKs1rEjBvBmM7Q8oQ7jASag8cPWKLd7 yaaQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=L6mvHVs7Emq3x8O+6oK7btk4FzaW3Q9LW/n9YIaMeEY=; b=AzejHozS0c9KQS1ALryy4UDf4yQst4vQrPqw/y/3kVE4klPdqDy+RR8pYcBGtJdvR0 /RZilkUfTwadft80KAdLbNKd865PvzK7A8dr0yuLJk0g9xLDFPYM7NJnWL9ji6ovzEne C+cDScUAJfAK3zerJAz2uD4WRi/uiGjlI1HFHdzv2jI6cz7gJIRnqGQvSci0LEWavXFk kmlf2OifwG+zdawDxpTECyBXzoF79hJPvuFo2Q6qH+NSmf1UwzEk2cNpmH/9vc9FBckp U0iHwyIH8XHNhTLN02Ydkmguaq8qfbKxrj7ZQC960hnFYK9Q3bM2baYTD+HZYPbzpJcx tQ7g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=aByivIjP; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id b8-20020a0564021f0800b0046b2840ca3dsi1965769edb.474.2022.11.28.01.09.00; Mon, 28 Nov 2022 01:09:23 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=aByivIjP; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230266AbiK1JG0 (ORCPT + 99 others); Mon, 28 Nov 2022 04:06:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36796 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230247AbiK1JGV (ORCPT ); Mon, 28 Nov 2022 04:06:21 -0500 Received: from mail-pl1-x62b.google.com (mail-pl1-x62b.google.com [IPv6:2607:f8b0:4864:20::62b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5600F178A7 for ; Mon, 28 Nov 2022 01:06:17 -0800 (PST) Received: by mail-pl1-x62b.google.com with SMTP id p12so9529168plq.4 for ; Mon, 28 Nov 2022 01:06:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=L6mvHVs7Emq3x8O+6oK7btk4FzaW3Q9LW/n9YIaMeEY=; b=aByivIjPectLrfW7PJXAKPBbF9CLRob7SfyWRzgeeaRgkZ5fbyjzDKES1vf+sI8ePP nlobNUu993/691YL35O5WEg87gefC5w9TvH3sAfV/4nsJq1MOfkuWt8yyn44d3rfr2ML TZlPB7cUR5XVg/bAQ9vnqrdgc2v20LOf4MBnf73zgKmfAZV6EDwphTNETPLkXoAsRx27 Q2jLgaZcEn6nljMAjg/FBdpZPjouD8UJaTcFPcvlZ6bi9BSlHwQLOKs5yzV5AX8XBqgD M2atmyJfSwfyVhQHXchpnq2v9TyYbWfsXF09Ku21JocGu6eDkPNc/QQE1e6iDWwbJvF4 G8RA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=L6mvHVs7Emq3x8O+6oK7btk4FzaW3Q9LW/n9YIaMeEY=; b=VzQ3v5bDUysSfEp0NFBP6hSSXYpB4SBzV1nZQ6hy+moJceYP+z5hOiJWb9wSN4Yd+Q H287p9aIiGGBMTr6VsYl036252NlldjQC2FjGkTt5jrQENiPYj058HEH8K1n66n+x75C zYvS1aF9/38hyYBb5cdSzcTEOmr6BcYqQ1nTK/W/6XIzdZRVEdL4E3k1+BwPxSdV0anN j0gc4cuezITakjInDfcXOy1YIBJ/k+TIMY8A+rMGDRCYd2L3VXUdcIhjgBRofwXNiTwX WGAl5N76db8tV2pDcwjY/nDuuIv1H7R8f+SLzQLxaqTW/NlhxJ7mlZNNDBpF1wZAw6vi ibig== X-Gm-Message-State: ANoB5plRhFCc5fhXHjxyBh66SMMc7/C0YTIC1Cg4WqxDbzA79rnsMvHM PZkk5fqQUnNThT4i6/WAdrzSCw+W85AcQg== X-Received: by 2002:a17:90b:394c:b0:213:1935:9744 with SMTP id oe12-20020a17090b394c00b0021319359744mr53565330pjb.207.1669626376866; Mon, 28 Nov 2022 01:06:16 -0800 (PST) Received: from mi-HP-ProDesk-680-G4-MT.mioffice.cn ([43.224.245.252]) by smtp.gmail.com with ESMTPSA id s17-20020a170902ea1100b001811a197797sm8269268plg.194.2022.11.28.01.06.14 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Nov 2022 01:06:16 -0800 (PST) From: qixiaoyu1 X-Google-Original-From: qixiaoyu1 To: Jaegeuk Kim , Chao Yu Cc: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, qixiaoyu1 , xiongping1 Subject: [PATCH 1/5] f2fs: record total data blocks allocated since mount Date: Mon, 28 Nov 2022 16:58:55 +0800 Message-Id: <20221128085859.5295-2-qixiaoyu1@xiaomi.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20221128085859.5295-1-qixiaoyu1@xiaomi.com> References: <20221128085859.5295-1-qixiaoyu1@xiaomi.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750730344004307704?= X-GMAIL-MSGID: =?utf-8?q?1750730344004307704?= From: xiongping1 Signed-off-by: xiongping1 Signed-off-by: qixiaoyu1 --- fs/f2fs/Kconfig | 7 +++++++ fs/f2fs/Makefile | 1 + fs/f2fs/block_age.c | 28 ++++++++++++++++++++++++++++ fs/f2fs/debug.c | 7 +++++++ fs/f2fs/f2fs.h | 15 +++++++++++++++ fs/f2fs/segment.c | 4 ++++ fs/f2fs/super.c | 4 ++++ 7 files changed, 66 insertions(+) create mode 100644 fs/f2fs/block_age.c diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig index 03ef087537c7..84915f9c6bc8 100644 --- a/fs/f2fs/Kconfig +++ b/fs/f2fs/Kconfig @@ -150,3 +150,10 @@ config F2FS_UNFAIR_RWSEM help Use unfair rw_semaphore, if system configured IO priority by block cgroup. + +config F2FS_FS_DATA_SEPARATION + bool "F2FS hot/cold data separation feature" + depends on F2FS_FS + help + Enable data blocks separation according to block update frequency. + diff --git a/fs/f2fs/Makefile b/fs/f2fs/Makefile index 8a7322d229e4..70d8f0e23b46 100644 --- a/fs/f2fs/Makefile +++ b/fs/f2fs/Makefile @@ -10,3 +10,4 @@ f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o f2fs-$(CONFIG_FS_VERITY) += verity.o f2fs-$(CONFIG_F2FS_FS_COMPRESSION) += compress.o f2fs-$(CONFIG_F2FS_IOSTAT) += iostat.o +f2fs-$(CONFIG_F2FS_FS_DATA_SEPARATION) += block_age.o diff --git a/fs/f2fs/block_age.c b/fs/f2fs/block_age.c new file mode 100644 index 000000000000..1e8711a03959 --- /dev/null +++ b/fs/f2fs/block_age.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * fs/f2fs/block_age.c + * + * Copyright (c) 2022 xiaomi Co., Ltd. + * http://www.xiaomi.com/ + */ +#include +#include + +#include "f2fs.h" +#include "segment.h" + +static inline void f2fs_inc_data_block_alloc(struct f2fs_sb_info *sbi) +{ + atomic64_inc(&sbi->total_data_alloc); +} + +void f2fs_init_block_age_info(struct f2fs_sb_info *sbi) +{ + atomic64_set(&sbi->total_data_alloc, 0); +} + +void f2fs_inc_block_alloc_count(struct f2fs_sb_info *sbi, int type) +{ + if (IS_DATASEG(type)) + f2fs_inc_data_block_alloc(sbi); +} diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index a216dcdf6941..d24abdac20bb 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -81,6 +81,9 @@ static void update_general_status(struct f2fs_sb_info *sbi) si->ext_tree = atomic_read(&sbi->total_ext_tree); si->zombie_tree = atomic_read(&sbi->total_zombie_tree); si->ext_node = atomic_read(&sbi->total_ext_node); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + si->total_data_blocks_alloc = atomic64_read(&sbi->total_data_alloc); +#endif si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES); si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS); si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META); @@ -373,6 +376,10 @@ static int stat_show(struct seq_file *s, void *v) seq_printf(s, "Utilization: %u%% (%u valid blocks)\n", si->utilization, si->valid_count); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + seq_printf(s, " - Data Block Allocated: %llu\n", + si->total_data_blocks_alloc); +#endif seq_printf(s, " - Node: %u (Inode: %u, ", si->valid_node_count, si->valid_inode_count); seq_printf(s, "Other: %u)\n - Data: %u\n", diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index e6355a5683b7..686f09846de4 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1807,6 +1807,10 @@ struct f2fs_sb_info { u64 sectors_written_start; u64 kbytes_written; +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + atomic64_t total_data_alloc; +#endif + /* Reference to checksum algorithm driver via cryptoapi */ struct crypto_shash *s_chksum_driver; @@ -3858,6 +3862,9 @@ struct f2fs_stat_info { int main_area_segs, main_area_sections, main_area_zones; unsigned long long hit_largest, hit_cached, hit_rbtree; unsigned long long hit_total, total_ext; +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + unsigned long long total_data_blocks_alloc; +#endif int ext_tree, zombie_tree, ext_node; int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta; int ndirty_data, ndirty_qdata; @@ -4166,6 +4173,14 @@ void f2fs_init_extent_cache_info(struct f2fs_sb_info *sbi); int __init f2fs_create_extent_cache(void); void f2fs_destroy_extent_cache(void); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION +/* + * block_age.c + */ +void f2fs_init_block_age_info(struct f2fs_sb_info *sbi); +void f2fs_inc_block_alloc_count(struct f2fs_sb_info *sbi, int type); +#endif + /* * sysfs.c */ diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index acf3d3fa4363..0cf022fd3560 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -3280,6 +3280,10 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr)); locate_dirty_segment(sbi, GET_SEGNO(sbi, *new_blkaddr)); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + f2fs_inc_block_alloc_count(sbi, type); +#endif + up_write(&sit_i->sentry_lock); if (page && IS_NODESEG(type)) { diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 3834ead04620..bf799d92282a 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4475,6 +4475,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) f2fs_join_shrinker(sbi); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + f2fs_init_block_age_info(sbi); +#endif + f2fs_tuning_parameters(sbi); f2fs_notice(sbi, "Mounted with checkpoint version = %llx", From patchwork Mon Nov 28 08:58:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: qixiaoyu1 X-Patchwork-Id: 26589 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp5528207wrr; Mon, 28 Nov 2022 01:09:34 -0800 (PST) X-Google-Smtp-Source: AA0mqf6C0EgC8/N1l4LqfxWut2ZK2tmAVlvBlECR9c31MwSaSRLfc9duCZQvDuhrk5KAIRHUi+78 X-Received: by 2002:a17:906:a148:b0:7ad:b286:8ee2 with SMTP id bu8-20020a170906a14800b007adb2868ee2mr11142ejb.511.1669626574303; Mon, 28 Nov 2022 01:09:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669626574; cv=none; d=google.com; s=arc-20160816; b=SRIgZ9fs0rxLYObO5zdJvrA0TVzEkirrFpENJ1ZTVgGHFWWAAxsxWyS/QcQ+hvrYSd OXY9JdnHEhsEZ9YYCEYjKzNkdJocRdtv89NfBGGmTNZ/4dV2mCN+x+cdjUoyFtHas6RI /rJHucW45W6DNvOm1g9o/kEfFavFMmziTkfmn16H78ubgINBWwrYCsJox3XdviNX3jqd nLCiBFTkTEnpD8HR8gVrGoyt5644kGS63bv72qwdHGoK7dEClXDNSjDpdC8rRCksrddw oLvUfus2w/TrnV56qbmnlY2Fc613bqLlXawEH67GbOAFqxfxNxAB03XnH2IX5v3Qof/d 4M5g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=CsU4/OuRMovveciFxhVb5bu8yT4MmZjVpSlJ69GC4U4=; b=fvXJq1EgLlohu8aZasFeGWE287Y/nW6LKGbAqMXya/LOGeFrWbaig510Cq6UOBj3Q4 CyiivajRP0BpPvfOn1QRniZee7eZi6SlrWvzOC1ZuSpLTBEBXaIQ8D58UdSyXFqZ+ycE NR3BLbZTjLVXhHqkdFYlq+mXHDF8buNn3SyOUpVb6ibV1YFtNon35AeQxQM4Z+T/DiH/ FGMEkKqhXaapGqsF59fxXeGgb3jPtrX1Zlw/q8f/GclLRQy556LWawuYCJTWGdHCLKhe jknkXnPwfUqQgESNpCinieVjpwFbkZBRYUlTFK/wvjI81EMGUE//xhiLfbNcxaT6RgaA yjIA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b="BL3rp/rV"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id v12-20020a50d08c000000b00462f85ee700si9944936edd.65.2022.11.28.01.09.10; Mon, 28 Nov 2022 01:09:34 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b="BL3rp/rV"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230292AbiK1JGg (ORCPT + 99 others); Mon, 28 Nov 2022 04:06:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36796 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230247AbiK1JG3 (ORCPT ); Mon, 28 Nov 2022 04:06:29 -0500 Received: from mail-pg1-x536.google.com (mail-pg1-x536.google.com [IPv6:2607:f8b0:4864:20::536]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3418B140E0 for ; Mon, 28 Nov 2022 01:06:21 -0800 (PST) Received: by mail-pg1-x536.google.com with SMTP id f3so9383335pgc.2 for ; Mon, 28 Nov 2022 01:06:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=CsU4/OuRMovveciFxhVb5bu8yT4MmZjVpSlJ69GC4U4=; b=BL3rp/rVs9Gg7Sd783cM4AUnvSJqIDeFCw2qPt/FzHEK+V3Ajwt8cRhn6oHvqSxPXV /SZ/iuh+c6j9kMDRuu8WIg40Y3nWCOOAHv1Qjex/G20oNLWZftDMAx77jiRTALgNqLQi zYAJLAImm+rdJqwDtR0yGNNcmPkecG8x0YBCHy9diGvmhJXO9/wEfaUh9uZx6RHNy0+2 7erAFqBywOsrVGoPfG7xUm31m9eMQFCG9DX64HHp9UZT91zHhJkx8SHf8nl2tr7hnLMY rO4Tg+hMtyR0kKBiMpwnLasVrTBHfj8A+sNoZEbNzCxfbUMsAd1mb9XrAhI0ORQmoS9q MHgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CsU4/OuRMovveciFxhVb5bu8yT4MmZjVpSlJ69GC4U4=; b=Um2cxFc/QgcDYHgwt4jJC8jurrp9o7evnIrFY2WYlmcH2EQiAQgYqVXWihwE01rUaa 6P1yb0URhHJTGnITK9A49bb9dqNSCErF4vVlo16SJ4ywISHvmskWYU2dcjM7H7JPz5cj oJj0E4qT5uIQDZBH/E6+Z/E8VGGB5G+JkNbWaZScFOIQaq6jF3un+Acf5aL5gzdTh1uO +0xsry+OQiZ60kIbJjzNj78q9+rq3HPYZ1igCAIWNKkLGQLxZBgoAbL8P7s67jOwWFqB L0DH//sKzV2H5tiiwxYKQUWky0klDiimQffY6zJAC8/pQMzhxlV6uytUq5Xh2BsENE6I lbaw== X-Gm-Message-State: ANoB5pnDxwsiHAYkGBVNmkdv8E8hqAHrhnrz/0cBiQDAyedhCFMGJEVk TBThTjs9EmT4qE+wBmmAbcw= X-Received: by 2002:a62:1a45:0:b0:575:253e:48d5 with SMTP id a66-20020a621a45000000b00575253e48d5mr4706628pfa.32.1669626380512; Mon, 28 Nov 2022 01:06:20 -0800 (PST) Received: from mi-HP-ProDesk-680-G4-MT.mioffice.cn ([43.224.245.252]) by smtp.gmail.com with ESMTPSA id s17-20020a170902ea1100b001811a197797sm8269268plg.194.2022.11.28.01.06.18 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Nov 2022 01:06:19 -0800 (PST) From: qixiaoyu1 X-Google-Original-From: qixiaoyu1 To: Jaegeuk Kim , Chao Yu Cc: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, qixiaoyu1 , xiongping1 Subject: [PATCH 2/5] f2fs: implement cache to manager block update frequency per inode Date: Mon, 28 Nov 2022 16:58:56 +0800 Message-Id: <20221128085859.5295-3-qixiaoyu1@xiaomi.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20221128085859.5295-1-qixiaoyu1@xiaomi.com> References: <20221128085859.5295-1-qixiaoyu1@xiaomi.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750730354664988247?= X-GMAIL-MSGID: =?utf-8?q?1750730354664988247?= From: xiongping1 Signed-off-by: xiongping1 Signed-off-by: qixiaoyu1 --- fs/f2fs/block_age.c | 590 +++++++++++++++++++++++++++++++++++- fs/f2fs/debug.c | 13 + fs/f2fs/f2fs.h | 64 +++- fs/f2fs/file.c | 10 + fs/f2fs/inode.c | 8 + fs/f2fs/namei.c | 4 + fs/f2fs/node.c | 7 +- fs/f2fs/node.h | 3 + fs/f2fs/segment.c | 6 + fs/f2fs/shrinker.c | 3 + fs/f2fs/super.c | 22 +- include/trace/events/f2fs.h | 239 +++++++++++++++ 12 files changed, 965 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/block_age.c b/fs/f2fs/block_age.c index 1e8711a03959..c8e8fbe51d8e 100644 --- a/fs/f2fs/block_age.c +++ b/fs/f2fs/block_age.c @@ -10,19 +10,607 @@ #include "f2fs.h" #include "segment.h" +#include + +static struct kmem_cache *age_extent_tree_slab; +static struct kmem_cache *age_extent_node_slab; + static inline void f2fs_inc_data_block_alloc(struct f2fs_sb_info *sbi) { atomic64_inc(&sbi->total_data_alloc); } -void f2fs_init_block_age_info(struct f2fs_sb_info *sbi) +static void f2fs_init_block_age_info(struct f2fs_sb_info *sbi) { atomic64_set(&sbi->total_data_alloc, 0); } +static inline bool f2fs_may_age_extent_tree(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + + /* + * for recovered files during mount do not create extents + * if shrinker is not registered. + */ + if (list_empty(&sbi->s_list)) + return false; + + /* don't cache block age info for cold file */ + if (is_inode_flag_set(inode, FI_COMPRESSED_FILE) || + file_is_cold(inode)) + return false; + + return S_ISREG(inode->i_mode) + || S_ISDIR(inode->i_mode); +} + +static void f2fs_init_age_cache_info(struct f2fs_sb_info *sbi) +{ + INIT_RADIX_TREE(&sbi->age_extent_tree_root, GFP_NOIO); + mutex_init(&sbi->age_extent_tree_lock); + INIT_LIST_HEAD(&sbi->age_extent_list); + spin_lock_init(&sbi->age_extent_lock); + atomic_set(&sbi->total_age_ext_tree, 0); + INIT_LIST_HEAD(&sbi->zombie_age_list); + atomic_set(&sbi->total_zombie_age_tree, 0); + atomic_set(&sbi->total_age_ext_node, 0); +} + +#ifdef CONFIG_QUOTA +static void f2fs_init_quota_age_extent_cache(struct f2fs_sb_info *sbi) +{ + struct quota_info *dqopt = sb_dqopt(sbi->sb); + struct inode *qinode; + int cnt; + + for (cnt = 0; cnt < MAXQUOTAS; cnt++) { + if (!sb_has_quota_active(sbi->sb, cnt)) + continue; + + qinode = dqopt->files[cnt]; + f2fs_init_age_extent_tree(qinode); + } +} +#endif + +static void __detach_age_extent_node(struct f2fs_sb_info *sbi, + struct age_extent_tree *et, struct age_extent_node *en) +{ + rb_erase_cached(&en->rb_node, &et->root); + atomic_dec(&et->node_cnt); + atomic_dec(&sbi->total_age_ext_node); + + if (et->cached_en == en) + et->cached_en = NULL; + + trace_f2fs_detach_age_extent_node(sbi, et, &en->ei); + kmem_cache_free(age_extent_node_slab, en); +} + +/* + * Flow to release an age_extent_node: + * 1. list_del_init + * 2. __detach_age_extent_node + * 3. kmem_cache_free. + */ +static void __release_age_extent_node(struct f2fs_sb_info *sbi, + struct age_extent_tree *et, struct age_extent_node *en) +{ + spin_lock(&sbi->age_extent_lock); + f2fs_bug_on(sbi, list_empty(&en->list)); + list_del_init(&en->list); + spin_unlock(&sbi->age_extent_lock); + + __detach_age_extent_node(sbi, et, en); +} + +static unsigned int __free_age_extent_tree(struct f2fs_sb_info *sbi, + struct age_extent_tree *et) +{ + struct rb_node *node, *next; + struct age_extent_node *en; + unsigned int count = atomic_read(&et->node_cnt); + + node = rb_first_cached(&et->root); + while (node) { + next = rb_next(node); + en = rb_entry(node, struct age_extent_node, rb_node); + __release_age_extent_node(sbi, et, en); + node = next; + } + + return count - atomic_read(&et->node_cnt); +} + +unsigned int f2fs_drop_age_extent_node(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct age_extent_tree *et = F2FS_I(inode)->age_extent_tree; + unsigned int node_cnt = 0; + + if (!et || !atomic_read(&et->node_cnt)) + return 0; + + write_lock(&et->lock); + node_cnt = __free_age_extent_tree(sbi, et); + write_unlock(&et->lock); + + return node_cnt; +} + +unsigned int f2fs_shrink_age_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink) +{ + struct age_extent_tree *et, *next; + struct age_extent_node *en; + unsigned int node_cnt = 0, tree_cnt = 0; + int remained; + + if (!atomic_read(&sbi->total_zombie_age_tree)) + goto free_node; + + if (!mutex_trylock(&sbi->age_extent_tree_lock)) + goto out; + + /* 1. remove unreferenced extent tree */ + list_for_each_entry_safe(et, next, &sbi->zombie_age_list, list) { + if (atomic_read(&et->node_cnt)) { + write_lock(&et->lock); + node_cnt += __free_age_extent_tree(sbi, et); + write_unlock(&et->lock); + } + f2fs_bug_on(sbi, atomic_read(&et->node_cnt)); + list_del_init(&et->list); + radix_tree_delete(&sbi->age_extent_tree_root, et->ino); + kmem_cache_free(age_extent_tree_slab, et); + atomic_dec(&sbi->total_age_ext_tree); + atomic_dec(&sbi->total_zombie_age_tree); + tree_cnt++; + + if (node_cnt + tree_cnt >= nr_shrink) + goto unlock_out; + cond_resched(); + } + mutex_unlock(&sbi->age_extent_tree_lock); + +free_node: + /* 2. remove LRU extent entries */ + if (!mutex_trylock(&sbi->age_extent_tree_lock)) + goto out; + + remained = nr_shrink - (node_cnt + tree_cnt); + + spin_lock(&sbi->age_extent_lock); + for (; remained > 0; remained--) { + if (list_empty(&sbi->age_extent_list)) + break; + en = list_first_entry(&sbi->age_extent_list, + struct age_extent_node, list); + et = en->et; + if (!write_trylock(&et->lock)) { + /* refresh this extent node's position in extent list */ + list_move_tail(&en->list, &sbi->age_extent_list); + continue; + } + + list_del_init(&en->list); + spin_unlock(&sbi->age_extent_lock); + + __detach_age_extent_node(sbi, et, en); + + write_unlock(&et->lock); + node_cnt++; + spin_lock(&sbi->age_extent_lock); + } + spin_unlock(&sbi->age_extent_lock); + +unlock_out: + mutex_unlock(&sbi->age_extent_tree_lock); +out: + trace_f2fs_shrink_age_extent_tree(sbi, nr_shrink, node_cnt, tree_cnt); + + return node_cnt + tree_cnt; +} + +static bool f2fs_lookup_age_extent_tree(struct inode *inode, pgoff_t pgofs, + struct age_extent_info *ei) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct age_extent_tree *et = F2FS_I(inode)->age_extent_tree; + struct age_extent_node *en; + + if (!et) + return false; + + trace_f2fs_lookup_age_extent_tree_start(inode, pgofs); + + read_lock(&et->lock); + + en = (struct age_extent_node *)f2fs_lookup_rb_tree(&et->root, + (struct rb_entry *)et->cached_en, pgofs); + if (!en) { + read_unlock(&et->lock); + return false; + } + + if (ei) + *ei = en->ei; + spin_lock(&sbi->age_extent_lock); + if (!list_empty(&en->list)) { + list_move_tail(&en->list, &sbi->age_extent_list); + et->cached_en = en; + } + spin_unlock(&sbi->age_extent_lock); + read_unlock(&et->lock); + + trace_f2fs_lookup_age_extent_tree_end(inode, pgofs, &en->ei); + return true; +} + +bool f2fs_lookup_age_extent_cache(struct inode *inode, pgoff_t pgofs, + struct age_extent_info *ei) +{ + if (!f2fs_may_age_extent_tree(inode)) + return false; + + return f2fs_lookup_age_extent_tree(inode, pgofs, ei); +} + +static inline bool __is_age_extent_mergeable(struct age_extent_info *back, + struct age_extent_info *front) +{ + return (back->fofs + back->len == front->fofs && + back->age == front->age && + back->last_blocks == front->last_blocks); +} + +static inline bool __is_back_age_ext_mergeable(struct age_extent_info *cur, + struct age_extent_info *back) +{ + return __is_age_extent_mergeable(back, cur); +} + +static inline bool __is_front_age_ext_mergeable(struct age_extent_info *cur, + struct age_extent_info *front) +{ + return __is_age_extent_mergeable(cur, front); +} + +static inline void set_age_extent_info(struct age_extent_info *ei, unsigned int fofs, + unsigned int len, unsigned long long age, + unsigned long long last_blocks) +{ + ei->fofs = fofs; + ei->len = len; + ei->age = age; + ei->last_blocks = last_blocks; +} + +static struct age_extent_node *__try_merge_age_extent_node(struct f2fs_sb_info *sbi, + struct age_extent_tree *et, struct age_extent_info *ei, + struct age_extent_node *prev_ex, + struct age_extent_node *next_ex) +{ + struct age_extent_node *en = NULL; + + if (prev_ex && __is_back_age_ext_mergeable(ei, &prev_ex->ei)) { + prev_ex->ei.len += ei->len; + ei = &prev_ex->ei; + en = prev_ex; + } + + if (next_ex && __is_front_age_ext_mergeable(ei, &next_ex->ei)) { + next_ex->ei.fofs = ei->fofs; + next_ex->ei.len += ei->len; + if (en) + __release_age_extent_node(sbi, et, prev_ex); + + en = next_ex; + } + + if (!en) + return NULL; + + spin_lock(&sbi->age_extent_lock); + if (!list_empty(&en->list)) { + list_move_tail(&en->list, &sbi->age_extent_list); + et->cached_en = en; + } + spin_unlock(&sbi->age_extent_lock); + + trace_f2fs_merged_age_extent_node(sbi, et, &en->ei); + return en; +} + +static struct age_extent_node *__attach_age_extent_node(struct f2fs_sb_info *sbi, + struct age_extent_tree *et, struct age_extent_info *ei, + struct rb_node *parent, struct rb_node **p, + bool leftmost) +{ + struct age_extent_node *en; + + en = kmem_cache_alloc(age_extent_node_slab, GFP_ATOMIC); + if (!en) + return NULL; + + en->ei = *ei; + INIT_LIST_HEAD(&en->list); + en->et = et; + + rb_link_node(&en->rb_node, parent, p); + rb_insert_color_cached(&en->rb_node, &et->root, leftmost); + atomic_inc(&et->node_cnt); + atomic_inc(&sbi->total_age_ext_node); + + trace_f2fs_attach_age_extent_node(sbi, en->et, &en->ei); + return en; +} + +static struct age_extent_node *__insert_age_extent_tree(struct f2fs_sb_info *sbi, + struct age_extent_tree *et, struct age_extent_info *ei, + struct rb_node **insert_p, + struct rb_node *insert_parent, + bool leftmost) +{ + struct rb_node **p; + struct rb_node *parent = NULL; + struct age_extent_node *en = NULL; + + if (insert_p && insert_parent) { + parent = insert_parent; + p = insert_p; + goto do_insert; + } + + leftmost = true; + + p = f2fs_lookup_rb_tree_for_insert(sbi, &et->root, &parent, + ei->fofs, &leftmost); +do_insert: + en = __attach_age_extent_node(sbi, et, ei, parent, p, leftmost); + if (!en) + return NULL; + + /* update in global extent list */ + spin_lock(&sbi->age_extent_lock); + list_add_tail(&en->list, &sbi->age_extent_list); + et->cached_en = en; + spin_unlock(&sbi->age_extent_lock); + + return en; +} + +static void f2fs_update_age_extent_tree_range(struct inode *inode, + pgoff_t fofs, unsigned int len, unsigned long long age, + unsigned long long last_blks) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct age_extent_tree *et = F2FS_I(inode)->age_extent_tree; + struct age_extent_node *en = NULL, *en1 = NULL; + struct age_extent_node *prev_en = NULL, *next_en = NULL; + struct age_extent_info ei, dei; + struct rb_node **insert_p = NULL, *insert_parent = NULL; + unsigned int end = fofs + len; + unsigned int pos = (unsigned int)fofs; + bool leftmost = false; + + if (!et) + return; + + trace_f2fs_update_age_extent_tree_range(inode, fofs, len, age, last_blks); + + write_lock(&et->lock); + + /* 1. lookup first extent node in range [fofs, fofs + len - 1] */ + en = (struct age_extent_node *)f2fs_lookup_rb_tree_ret(&et->root, + (struct rb_entry *)et->cached_en, fofs, + (struct rb_entry **)&prev_en, + (struct rb_entry **)&next_en, + &insert_p, &insert_parent, false, + &leftmost); + if (!en) + en = next_en; + + /* 2. invlidate all age extent nodes in range [fofs, fofs + len - 1] */ + while (en && en->ei.fofs < end) { + unsigned int org_end; + int parts = 0; /* # of parts current age extent split into */ + + next_en = en1 = NULL; + + dei = en->ei; + org_end = dei.fofs + dei.len; + f2fs_bug_on(sbi, pos >= org_end); + + if (pos > dei.fofs) { + en->ei.len = pos - en->ei.fofs; + prev_en = en; + parts = 1; + } + + if (end < org_end) { + if (parts) { + set_age_extent_info(&ei, end, + org_end - end, dei.age, dei.last_blocks); + en1 = __insert_age_extent_tree(sbi, et, &ei, + NULL, NULL, true); + next_en = en1; + } else { + en->ei.fofs = end; + en->ei.len -= end - dei.fofs; + en->ei.age = dei.age; + en->ei.last_blocks = dei.last_blocks; + next_en = en; + } + parts++; + } + + if (!next_en) { + struct rb_node *node = rb_next(&en->rb_node); + + next_en = rb_entry_safe(node, struct age_extent_node, + rb_node); + } + + if (!parts) + __release_age_extent_node(sbi, et, en); + + /* + * if original extent is split into zero or two parts, extent + * tree has been altered by deletion or insertion, therefore + * invalidate pointers regard to tree. + */ + if (parts != 1) { + insert_p = NULL; + insert_parent = NULL; + } + en = next_en; + } + + /* 3. update extent in extent cache */ + if (last_blks) { + set_age_extent_info(&ei, fofs, len, age, last_blks); + if (!__try_merge_age_extent_node(sbi, et, &ei, prev_en, next_en)) + __insert_age_extent_tree(sbi, et, &ei, + insert_p, insert_parent, leftmost); + } + + write_unlock(&et->lock); +} + +void f2fs_update_age_extent_cache(struct inode *inode, pgoff_t fofs, + unsigned int len, unsigned long long age, + unsigned long long cur_blk_alloced) +{ + if (!f2fs_may_age_extent_tree(inode)) + return; + + f2fs_update_age_extent_tree_range(inode, fofs, len, age, cur_blk_alloced); +} + +void f2fs_truncate_age_extent_cache(struct inode *inode, pgoff_t fofs, unsigned int len) +{ + f2fs_update_age_extent_cache(inode, fofs, len, 0, 0); +} + +void f2fs_destroy_age_extent_tree(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct age_extent_tree *et = F2FS_I(inode)->age_extent_tree; + unsigned int node_cnt = 0; + + if (!et) + return; + + if (inode->i_nlink && !is_bad_inode(inode) && + atomic_read(&et->node_cnt)) { + mutex_lock(&sbi->age_extent_tree_lock); + list_add_tail(&et->list, &sbi->zombie_age_list); + atomic_inc(&sbi->total_zombie_age_tree); + mutex_unlock(&sbi->age_extent_tree_lock); + return; + } + + /* free all extent info belong to this extent tree */ + node_cnt = f2fs_drop_age_extent_node(inode); + + /* delete extent tree entry in radix tree */ + mutex_lock(&sbi->age_extent_tree_lock); + f2fs_bug_on(sbi, atomic_read(&et->node_cnt)); + radix_tree_delete(&sbi->age_extent_tree_root, inode->i_ino); + kmem_cache_free(age_extent_tree_slab, et); + atomic_dec(&sbi->total_age_ext_tree); + mutex_unlock(&sbi->age_extent_tree_lock); + + F2FS_I(inode)->age_extent_tree = NULL; + + trace_f2fs_destroy_age_extent_tree(inode, node_cnt); +} + +void f2fs_init_data_seperation_info(struct f2fs_sb_info *sbi) +{ + f2fs_init_block_age_info(sbi); + f2fs_init_age_cache_info(sbi); + + f2fs_init_age_extent_tree(sbi->sb->s_root->d_inode); +#ifdef CONFIG_QUOTA + f2fs_init_quota_age_extent_cache(sbi); +#endif +} + void f2fs_inc_block_alloc_count(struct f2fs_sb_info *sbi, int type) { if (IS_DATASEG(type)) f2fs_inc_data_block_alloc(sbi); } + +int __init f2fs_create_age_extent_cache(void) +{ + age_extent_tree_slab = f2fs_kmem_cache_create("f2fs_age_extent_tree", + sizeof(struct age_extent_tree)); + if (!age_extent_tree_slab) + return -ENOMEM; + age_extent_node_slab = f2fs_kmem_cache_create("f2fs_age_extent_node", + sizeof(struct age_extent_node)); + if (!age_extent_node_slab) { + kmem_cache_destroy(age_extent_tree_slab); + return -ENOMEM; + } + return 0; +} + +bool f2fs_init_age_extent_tree(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct age_extent_tree *et; + nid_t ino = inode->i_ino; + + if (!f2fs_may_age_extent_tree(inode)) + return false; + + mutex_lock(&sbi->age_extent_tree_lock); + et = radix_tree_lookup(&sbi->age_extent_tree_root, ino); + if (!et) { + et = f2fs_kmem_cache_alloc(age_extent_tree_slab, GFP_NOFS, false, sbi); + f2fs_radix_tree_insert(&sbi->age_extent_tree_root, ino, et); + memset(et, 0, sizeof(struct age_extent_tree)); + et->ino = ino; + et->root = RB_ROOT_CACHED; + et->cached_en = NULL; + rwlock_init(&et->lock); + INIT_LIST_HEAD(&et->list); + atomic_set(&et->node_cnt, 0); + atomic_inc(&sbi->total_age_ext_tree); + } else { + atomic_dec(&sbi->total_zombie_age_tree); + list_del_init(&et->list); + } + mutex_unlock(&sbi->age_extent_tree_lock); + + /* never died until evict_inode */ + F2FS_I(inode)->age_extent_tree = et; + + trace_f2fs_init_age_extent_tree(inode, atomic_read(&et->node_cnt)); + return true; +} + +unsigned long long f2fs_total_age_cache_size(struct f2fs_sb_info *sbi) +{ + return atomic_read(&sbi->total_age_ext_tree) * + sizeof(struct age_extent_tree) + + atomic_read(&sbi->total_age_ext_node) * + sizeof(struct age_extent_node); +} + +unsigned long f2fs_count_age_extent_cache(struct f2fs_sb_info *sbi) +{ + return atomic_read(&sbi->total_zombie_age_tree) + + atomic_read(&sbi->total_age_ext_node); +} + +void f2fs_destroy_age_extent_cache(void) +{ + kmem_cache_destroy(age_extent_node_slab); + kmem_cache_destroy(age_extent_tree_slab); +} diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index d24abdac20bb..38eb8699a497 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c @@ -83,6 +83,8 @@ static void update_general_status(struct f2fs_sb_info *sbi) si->ext_node = atomic_read(&sbi->total_ext_node); #ifdef CONFIG_F2FS_FS_DATA_SEPARATION si->total_data_blocks_alloc = atomic64_read(&sbi->total_data_alloc); + si->age_ext_tree_count = atomic_read(&sbi->total_age_ext_tree); + si->age_ext_node_count = atomic_read(&sbi->total_age_ext_node); #endif si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES); si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS); @@ -301,6 +303,9 @@ static void update_mem_info(struct f2fs_sb_info *sbi) sizeof(struct extent_tree); si->cache_mem += atomic_read(&sbi->total_ext_node) * sizeof(struct extent_node); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + si->age_ext_mem = f2fs_total_age_cache_size(sbi); +#endif si->page_mem = 0; if (sbi->node_inode) { @@ -575,6 +580,14 @@ static int stat_show(struct seq_file *s, void *v) si->base_mem >> 10); seq_printf(s, " - cached: %llu KB\n", si->cache_mem >> 10); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + seq_printf(s, " - age cached: %llu KB\n", + si->age_ext_mem >> 10); + seq_printf(s, " - ext tree count: %u\n", + si->age_ext_tree_count); + seq_printf(s, " - ext node count: %u\n", + si->age_ext_node_count); +#endif seq_printf(s, " - paged : %llu KB\n", si->page_mem >> 10); } diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 686f09846de4..5cc516228407 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -603,6 +603,10 @@ enum { #define RECOVERY_MIN_RA_BLOCKS 1 #define F2FS_ONSTACK_PAGES 16 /* nr of onstack pages */ +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION +/* number of age extent info in extent cache we try to shrink */ +#define AGE_EXTENT_CACHE_SHRINK_NUMBER 128 +#endif struct rb_entry { struct rb_node rb_node; /* rb node located in rb-tree */ @@ -642,6 +646,31 @@ struct extent_tree { bool largest_updated; /* largest extent updated */ }; +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION +struct age_extent_info { + unsigned int fofs; /* start offset in a file */ + unsigned int len; /* length of the extent */ + unsigned long long age; /* block age of the extent */ + unsigned long long last_blocks; /* last total blocks allocated */ +}; + +struct age_extent_node { + struct rb_node rb_node; /* rb node located in rb-tree */ + struct age_extent_info ei; /* age extent info */ + struct list_head list; /* node in global age extent list of sbi */ + struct age_extent_tree *et; /* age extent tree pointer */ +}; + +struct age_extent_tree { + nid_t ino; /* inode number */ + struct rb_root_cached root; /* root of age extent info rb-tree */ + struct age_extent_node *cached_en; /* recently accessed age extent node */ + struct list_head list; /* to be used by sbi->zombie_age_list */ + rwlock_t lock; /* protect age extent info rb-tree */ + atomic_t node_cnt; /* # of age extent node in rb-tree*/ +}; +#endif + /* * This structure is taken from ext4_map_blocks. * @@ -803,6 +832,9 @@ struct f2fs_inode_info { struct extent_tree *extent_tree; /* cached extent_tree entry */ struct inode *cow_inode; /* copy-on-write inode for atomic write */ +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + struct age_extent_tree *age_extent_tree; /* cached age_extent_tree entry */ +#endif /* avoid racing between foreground op and gc */ struct f2fs_rwsem i_gc_rwsem[2]; struct f2fs_rwsem i_xattr_sem; /* avoid racing between reading and changing EAs */ @@ -1677,6 +1709,18 @@ struct f2fs_sb_info { atomic_t total_zombie_tree; /* extent zombie tree count */ atomic_t total_ext_node; /* extent info count */ +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + /* for age extent tree cache */ + struct radix_tree_root age_extent_tree_root; /* cache age extent cache entries */ + struct mutex age_extent_tree_lock; /* locking age extent radix tree */ + struct list_head age_extent_list; /* lru list for shrinker */ + spinlock_t age_extent_lock; /* locking age extent lru list */ + atomic_t total_age_ext_tree; /* age extent tree count */ + struct list_head zombie_age_list; /* age extent zombie tree list */ + atomic_t total_zombie_age_tree; /* age extent zombie tree count */ + atomic_t total_age_ext_node; /* age extent info count */ +#endif + /* basic filesystem units */ unsigned int log_sectors_per_block; /* log2 sectors per block */ unsigned int log_blocksize; /* log2 block size */ @@ -3864,6 +3908,9 @@ struct f2fs_stat_info { unsigned long long hit_total, total_ext; #ifdef CONFIG_F2FS_FS_DATA_SEPARATION unsigned long long total_data_blocks_alloc; + unsigned long long age_ext_mem; + unsigned int age_ext_tree_count; + unsigned int age_ext_node_count; #endif int ext_tree, zombie_tree, ext_node; int ndirty_node, ndirty_dent, ndirty_meta, ndirty_imeta; @@ -4177,8 +4224,23 @@ void f2fs_destroy_extent_cache(void); /* * block_age.c */ -void f2fs_init_block_age_info(struct f2fs_sb_info *sbi); +void f2fs_init_data_seperation_info(struct f2fs_sb_info *sbi); void f2fs_inc_block_alloc_count(struct f2fs_sb_info *sbi, int type); +unsigned long long f2fs_total_age_cache_size(struct f2fs_sb_info *sbi); +unsigned long f2fs_count_age_extent_cache(struct f2fs_sb_info *sbi); +bool f2fs_init_age_extent_tree(struct inode *inode); +unsigned int f2fs_shrink_age_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink); +unsigned int f2fs_drop_age_extent_node(struct inode *inode); +void f2fs_destroy_age_extent_tree(struct inode *inode); +bool f2fs_lookup_age_extent_cache(struct inode *inode, pgoff_t pgofs, + struct age_extent_info *ei); +void f2fs_update_age_extent_cache(struct inode *inode, pgoff_t fofs, + unsigned int len, u64 age, + unsigned long long cur_blk_alloced); +void f2fs_truncate_age_extent_cache(struct inode *inode, pgoff_t fofs, + unsigned int len); +int __init f2fs_create_age_extent_cache(void); +void f2fs_destroy_age_extent_cache(void); #endif /* diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 82cda1258227..860e2405e6bb 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -619,6 +619,10 @@ void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count) fofs = f2fs_start_bidx_of_node(ofs_of_node(dn->node_page), dn->inode) + ofs; f2fs_update_extent_cache_range(dn, fofs, 0, len); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + /* delete block age info from cache */ + f2fs_truncate_age_extent_cache(dn->inode, fofs, nr_free); +#endif dec_valid_block_count(sbi, dn->inode, nr_free); } dn->ofs_in_node = ofs; @@ -1403,6 +1407,9 @@ static int f2fs_do_collapse(struct inode *inode, loff_t offset, loff_t len) f2fs_lock_op(sbi); f2fs_drop_extent_tree(inode); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + f2fs_drop_age_extent_node(inode); +#endif truncate_pagecache(inode, offset); ret = __exchange_data_block(inode, inode, end, start, nrpages - end, true); f2fs_unlock_op(sbi); @@ -1664,6 +1671,9 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len) f2fs_lock_op(sbi); f2fs_drop_extent_tree(inode); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + f2fs_drop_age_extent_node(inode); +#endif ret = __exchange_data_block(inode, inode, idx, idx + delta, nr, false); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 9f0d3864d9f1..be05870b466f 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -394,6 +394,10 @@ static int do_read_inode(struct inode *inode) f2fs_init_extent_tree(inode, node_page); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + f2fs_init_age_extent_tree(inode); +#endif + get_inline_info(inode, ri); fi->i_extra_isize = f2fs_has_extra_attr(inode) ? @@ -782,6 +786,10 @@ void f2fs_evict_inode(struct inode *inode) f2fs_destroy_extent_tree(inode); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + f2fs_destroy_age_extent_tree(inode); +#endif + if (inode->i_nlink || is_bad_inode(inode)) goto no_delete; diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index a389772fd212..193d65e8f292 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -105,6 +105,10 @@ static struct inode *f2fs_new_inode(struct user_namespace *mnt_userns, f2fs_init_extent_tree(inode, NULL); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + f2fs_init_age_extent_tree(inode); +#endif + F2FS_I(inode)->i_flags = f2fs_mask_flags(mode, F2FS_I(dir)->i_flags & F2FS_FL_INHERITED); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 983572f23896..280dcc8d4939 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -60,7 +60,7 @@ bool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type) avail_ram = val.totalram - val.totalhigh; /* - * give 25%, 25%, 50%, 50%, 50% memory for each components respectively + * give 25%, 25%, 50%, 50%, 50%, 50% memory for each components respectively */ if (type == FREE_NIDS) { mem_size = (nm_i->nid_cnt[FREE_NID] * @@ -91,6 +91,11 @@ bool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type) atomic_read(&sbi->total_ext_node) * sizeof(struct extent_node)) >> PAGE_SHIFT; res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + } else if (type == AGE_EXTENT_CACHE) { + mem_size = f2fs_total_age_cache_size(sbi) >> PAGE_SHIFT; + res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1); +#endif } else if (type == DISCARD_CACHE) { mem_size = (atomic_read(&dcc->discard_cmd_cnt) * sizeof(struct discard_cmd)) >> PAGE_SHIFT; diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index 3c09cae058b0..3a103bd3833f 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h @@ -147,6 +147,9 @@ enum mem_type { DIRTY_DENTS, /* indicates dirty dentry pages */ INO_ENTRIES, /* indicates inode entries */ EXTENT_CACHE, /* indicates extent cache */ +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + AGE_EXTENT_CACHE, /* indicates age extent cache */ +#endif DISCARD_CACHE, /* indicates memory of cached discard cmds */ COMPRESS_PAGE, /* indicates memory of cached compressed pages */ BASE_CHECK, /* check kernel status */ diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 0cf022fd3560..b105d8418f77 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -440,6 +440,12 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg) if (!f2fs_available_free_memory(sbi, EXTENT_CACHE)) f2fs_shrink_extent_tree(sbi, EXTENT_CACHE_SHRINK_NUMBER); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + /* try to shrink age extent cache when there is no enough memory */ + if (!f2fs_available_free_memory(sbi, AGE_EXTENT_CACHE)) + f2fs_shrink_age_extent_tree(sbi, AGE_EXTENT_CACHE_SHRINK_NUMBER); +#endif + /* check the # of cached NAT entries */ if (!f2fs_available_free_memory(sbi, NAT_ENTRIES)) f2fs_try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK); diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c index dd3c3c7a90ec..9a139a0a6f8f 100644 --- a/fs/f2fs/shrinker.c +++ b/fs/f2fs/shrinker.c @@ -131,6 +131,9 @@ void f2fs_join_shrinker(struct f2fs_sb_info *sbi) void f2fs_leave_shrinker(struct f2fs_sb_info *sbi) { f2fs_shrink_extent_tree(sbi, __count_extent_cache(sbi)); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + f2fs_shrink_age_extent_tree(sbi, f2fs_count_age_extent_cache(sbi)); +#endif spin_lock(&f2fs_list_lock); list_del_init(&sbi->s_list); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index bf799d92282a..91d3c9d0425d 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1421,6 +1421,10 @@ static int f2fs_drop_inode(struct inode *inode) /* should remain fi->extent_tree for writepage */ f2fs_destroy_extent_node(inode); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + f2fs_drop_age_extent_node(inode); +#endif + sb_start_intwrite(inode->i_sb); f2fs_i_size_write(inode, 0); @@ -4476,7 +4480,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) f2fs_join_shrinker(sbi); #ifdef CONFIG_F2FS_FS_DATA_SEPARATION - f2fs_init_block_age_info(sbi); + f2fs_init_data_seperation_info(sbi); #endif f2fs_tuning_parameters(sbi); @@ -4673,9 +4677,18 @@ static int __init init_f2fs_fs(void) err = f2fs_create_extent_cache(); if (err) goto free_recovery_cache; +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + err = f2fs_create_age_extent_cache(); + if (err) + goto free_extent_cache; +#endif err = f2fs_create_garbage_collection_cache(); if (err) +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + goto free_age_extent_cache; +#else goto free_extent_cache; +#endif err = f2fs_init_sysfs(); if (err) goto free_garbage_collection_cache; @@ -4729,6 +4742,10 @@ static int __init init_f2fs_fs(void) f2fs_exit_sysfs(); free_garbage_collection_cache: f2fs_destroy_garbage_collection_cache(); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION +free_age_extent_cache: + f2fs_destroy_age_extent_cache(); +#endif free_extent_cache: f2fs_destroy_extent_cache(); free_recovery_cache: @@ -4761,6 +4778,9 @@ static void __exit exit_f2fs_fs(void) f2fs_destroy_garbage_collection_cache(); f2fs_destroy_extent_cache(); f2fs_destroy_recovery_cache(); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + f2fs_destroy_age_extent_cache(); +#endif f2fs_destroy_checkpoint_caches(); f2fs_destroy_segment_manager_caches(); f2fs_destroy_node_manager_caches(); diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index c6b372401c27..b19c057ff801 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -160,6 +160,11 @@ struct extent_info; struct victim_sel_policy; struct f2fs_map_blocks; +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION +struct age_extent_tree; +struct age_extent_info; +#endif + DECLARE_EVENT_CLASS(f2fs__inode, TP_PROTO(struct inode *inode), @@ -1659,6 +1664,240 @@ TRACE_EVENT(f2fs_destroy_extent_tree, __entry->node_cnt) ); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION +DECLARE_EVENT_CLASS(f2fs_add_age_extent_node, + + TP_PROTO(struct f2fs_sb_info *sbi, + struct age_extent_tree *et, struct age_extent_info *ei), + + TP_ARGS(sbi, et, ei), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(unsigned int, cnt) + __field(unsigned int, fofs) + __field(unsigned int, len) + __field(unsigned long long, age) + __field(unsigned long long, blocks) + ), + + TP_fast_assign( + __entry->dev = sbi->sb->s_dev; + __entry->ino = et->ino; + __entry->cnt = atomic_read(&et->node_cnt); + __entry->fofs = ei->fofs; + __entry->len = ei->len; + __entry->age = ei->age; + __entry->blocks = ei->last_blocks; + ), + + TP_printk("dev = (%d,%d), ino = %lu, node_cnt = %lu, " + "age_ext_info(fofs: %u, len: %u, age: %llu, blocks: %llu)", + show_dev_ino(__entry), + __entry->cnt, + __entry->fofs, + __entry->len, + __entry->age, + __entry->blocks) +); + +DEFINE_EVENT(f2fs_add_age_extent_node, f2fs_attach_age_extent_node, + + TP_PROTO(struct f2fs_sb_info *sbi, + struct age_extent_tree *et, struct age_extent_info *ei), + + TP_ARGS(sbi, et, ei) +); + +DEFINE_EVENT(f2fs_add_age_extent_node, f2fs_merged_age_extent_node, + + TP_PROTO(struct f2fs_sb_info *sbi, + struct age_extent_tree *et, struct age_extent_info *ei), + + TP_ARGS(sbi, et, ei) +); + +DEFINE_EVENT(f2fs_add_age_extent_node, f2fs_detach_age_extent_node, + + TP_PROTO(struct f2fs_sb_info *sbi, + struct age_extent_tree *et, struct age_extent_info *ei), + + TP_ARGS(sbi, et, ei) +); + +TRACE_EVENT(f2fs_lookup_age_extent_tree_start, + + TP_PROTO(struct inode *inode, unsigned int pgofs), + + TP_ARGS(inode, pgofs), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(unsigned int, pgofs) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->pgofs = pgofs; + ), + + TP_printk("dev = (%d,%d), ino = %lu, pgofs = %u", + show_dev_ino(__entry), + __entry->pgofs) +); + +TRACE_EVENT_CONDITION(f2fs_lookup_age_extent_tree_end, + + TP_PROTO(struct inode *inode, unsigned int pgofs, + struct age_extent_info *ei), + + TP_ARGS(inode, pgofs, ei), + + TP_CONDITION(ei), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(unsigned int, pgofs) + __field(unsigned int, fofs) + __field(unsigned int, len) + __field(unsigned long long, age) + __field(unsigned long long, blocks) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->pgofs = pgofs; + __entry->fofs = ei->fofs; + __entry->len = ei->len; + __entry->age = ei->age; + __entry->blocks = ei->last_blocks; + ), + + TP_printk("dev = (%d,%d), ino = %lu, pgofs = %u, " + "age_ext_info(fofs: %u, len: %u, age: %llu, blocks: %llu)", + show_dev_ino(__entry), + __entry->pgofs, + __entry->fofs, + __entry->len, + __entry->age, + __entry->blocks) +); + +TRACE_EVENT(f2fs_update_age_extent_tree_range, + + TP_PROTO(struct inode *inode, unsigned int pgofs, unsigned int len, + unsigned long long age, + unsigned long long last_blks), + + TP_ARGS(inode, pgofs, len, age, last_blks), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(unsigned int, pgofs) + __field(unsigned int, len) + __field(unsigned long long, age) + __field(unsigned long long, blocks) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->pgofs = pgofs; + __entry->len = len; + __entry->age = age; + __entry->blocks = last_blks; + ), + + TP_printk("dev = (%d,%d), ino = %lu, pgofs = %u, " + "len = %u, age = %llu, blocks = %llu", + show_dev_ino(__entry), + __entry->pgofs, + __entry->len, + __entry->age, + __entry->blocks) +); + +TRACE_EVENT(f2fs_shrink_age_extent_tree, + + TP_PROTO(struct f2fs_sb_info *sbi, int nr_shrink, + unsigned int node_cnt, unsigned int tree_cnt), + + TP_ARGS(sbi, nr_shrink, node_cnt, tree_cnt), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(int, nr_shrink) + __field(unsigned int, node_cnt) + __field(unsigned int, tree_cnt) + ), + + TP_fast_assign( + __entry->dev = sbi->sb->s_dev; + __entry->nr_shrink = nr_shrink; + __entry->node_cnt = node_cnt; + __entry->tree_cnt = tree_cnt; + ), + + TP_printk("dev = (%d,%d), nr_shrink = %d, shrunk: node_cnt = %u, tree_cnt = %u", + show_dev(__entry->dev), + __entry->nr_shrink, + __entry->node_cnt, + __entry->tree_cnt) +); + +TRACE_EVENT(f2fs_init_age_extent_tree, + + TP_PROTO(struct inode *inode, unsigned int node_cnt), + + TP_ARGS(inode, node_cnt), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(unsigned int, node_cnt) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->node_cnt = node_cnt; + ), + + TP_printk("dev = (%d,%d), ino = %lu, node_cnt = %u", + show_dev_ino(__entry), + __entry->node_cnt) +); + +TRACE_EVENT(f2fs_destroy_age_extent_tree, + + TP_PROTO(struct inode *inode, unsigned int node_cnt), + + TP_ARGS(inode, node_cnt), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(unsigned int, node_cnt) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->node_cnt = node_cnt; + ), + + TP_printk("dev = (%d,%d), ino = %lu, destroyed: node_cnt = %u", + show_dev_ino(__entry), + __entry->node_cnt) +); +#endif + DECLARE_EVENT_CLASS(f2fs_sync_dirty_inodes, TP_PROTO(struct super_block *sb, int type, s64 count), From patchwork Mon Nov 28 08:58:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: qixiaoyu1 X-Patchwork-Id: 26590 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp5528287wrr; Mon, 28 Nov 2022 01:09:50 -0800 (PST) X-Google-Smtp-Source: AA0mqf7zZ0e0GCQ+tuHSfgO6frkRaBUbxhI2882nZvvxobz0zMuXsgOkxMXLdht72Fh3bwL6250P X-Received: by 2002:a17:906:3a4c:b0:7ae:4f8f:36c with SMTP id a12-20020a1709063a4c00b007ae4f8f036cmr41243080ejf.137.1669626589800; Mon, 28 Nov 2022 01:09:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669626589; cv=none; d=google.com; s=arc-20160816; b=WgQBLkS+ndQIgAx6hmb0jIYGClsMdniKWQ+DiQlMg+GclzQVjHW8cubOxNgeZX6iF8 0aZZBIEZeMwfR5aYR5QOAouwgK4uOzDelpfvT2Hg5o+p4X9MGI92ODwqXHN/mFheK1ob 53YSLrLBvbKAoapv6gLeYVfsBKBWR3+dxOqSVeU0oo85VSysUTngMRz6VlI3iooYalY/ /c90PSU630NAticKvcy9+5Zpsxjpi/6WLkIWAqmnAmAVBq5uXdDl7/NH8toMPbmXHUkR dn09dobqIma4Xavyv0KSnpktboV6Puem8far6FiHGtiHYMsTGIPzM9qSwv/cmVs4nOwu Rxfw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=93lUf2Yl5jzTi/ZpIQt/d66du6Z7M3MI5N1pwAOidPY=; b=fsWXevZ7+Pr8dBzokf/zXp/dS2k75UIInCQr93oa+K57f+w6NGr8kqGbFkCqrBXDeM jVMHgBE31sCr4oNuW9qaSStGxeC6W3PcddV075BmLVzwKs4Kp9JQRR/zwZe7sMpojoEA lH1vftwgQvZsznS8mSSdVyRg3G63mEo5XozH4EahTnFHgsiIO3z/5BAyPpTDPM0LxbkK qahhZ94xKoLuYxYYxNPB76Fu6MHmDi/56PO3CG7UQBAsKF7B5oYWiPnhugiXwulw4TqX xsl8E83iK54hVGVHqbgJWgww5loyB37BtkAYwb8+ctLTqgltBSK2OYhcK/YfAiRc1u95 gtyQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=cvRduKxQ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id sd36-20020a1709076e2400b007313312730esi8896083ejc.85.2022.11.28.01.09.24; Mon, 28 Nov 2022 01:09:49 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=cvRduKxQ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230299AbiK1JGl (ORCPT + 99 others); Mon, 28 Nov 2022 04:06:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37150 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230285AbiK1JGd (ORCPT ); Mon, 28 Nov 2022 04:06:33 -0500 Received: from mail-pf1-x436.google.com (mail-pf1-x436.google.com [IPv6:2607:f8b0:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B295C140BF for ; Mon, 28 Nov 2022 01:06:27 -0800 (PST) Received: by mail-pf1-x436.google.com with SMTP id q12so5735886pfn.10 for ; Mon, 28 Nov 2022 01:06:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=93lUf2Yl5jzTi/ZpIQt/d66du6Z7M3MI5N1pwAOidPY=; b=cvRduKxQBd+dQX00FcUDlva9HxIMi7VXrDhju+OzmsUksxd1+QVOsiRPhFgy1T9nk/ 5ey7nbpakRWL4y+EWdA67WIm0iQ4B701ccG8U1TBVOKA0IutNu4Pyp0WMOvf2gAk6kF1 ua6qCIR1QsIUTkNFdhQl0UgwEofc8ZeeyTzo3aI804XeaaqcrYlDhGZgrZrW0zDkwMyx X5mFupdqjR6Oxo2uEnyMGhLvS6vLzohHdbDTZUT+4kegvUzNR/Dnvo9vcResfKIV9dXu +DZ65C2fLgesKA/EZ+PLJGH03NNezkjyjLWhjBFL4KewSBH35r7BSAKRFwj0H6OcJQrG ZjTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=93lUf2Yl5jzTi/ZpIQt/d66du6Z7M3MI5N1pwAOidPY=; b=akKqGig94ESVmofQKWFNoLVA1LGFLBrFwOINo3eATyJTF/rLf1bXdrX/5TJxNH/qlO mSDG6VmMuudEpgFk0Z68S+/EvaomLM4wIttzWnL6HFtNLzZOR3MKaZc7XYdobeohb70w Wbf3CWAP1ECEHsE/RBusAoQ1JsgOtlV3xvLfNBsTC6542Thc6SBz986ymlVWWqrJpQjT y1xV2jn2VJEfizgsHIQJdSoPssUvtPrNmrH7GqEuiGpDVGGuPfTDfE+IoAbxQgY8a1L6 TTM72VphH/yGd+Lympouptc5+8wQjaXkvq1Nh/rvcPU1BaTwspsR4KmkvE0T2E0gCRg+ Kp1A== X-Gm-Message-State: ANoB5pmkBhKZVZZzpksk88Z87mq1xwkZ6YaMFy44AlVrZpnC2SxX5TEq fCbzIbNiFH1fht2ysBe3t7o= X-Received: by 2002:aa7:9045:0:b0:56c:a321:eecb with SMTP id n5-20020aa79045000000b0056ca321eecbmr52091885pfo.19.1669626387218; Mon, 28 Nov 2022 01:06:27 -0800 (PST) Received: from mi-HP-ProDesk-680-G4-MT.mioffice.cn ([43.224.245.252]) by smtp.gmail.com with ESMTPSA id s17-20020a170902ea1100b001811a197797sm8269268plg.194.2022.11.28.01.06.25 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Nov 2022 01:06:26 -0800 (PST) From: qixiaoyu1 X-Google-Original-From: qixiaoyu1 To: Jaegeuk Kim , Chao Yu Cc: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, qixiaoyu1 , xiongping1 Subject: [PATCH 3/5] f2fs: add age_extent_cache mount option Date: Mon, 28 Nov 2022 16:58:57 +0800 Message-Id: <20221128085859.5295-4-qixiaoyu1@xiaomi.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20221128085859.5295-1-qixiaoyu1@xiaomi.com> References: <20221128085859.5295-1-qixiaoyu1@xiaomi.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750730371329798777?= X-GMAIL-MSGID: =?utf-8?q?1750730371329798777?= From: xiongping1 enable data block seperation feature only when age_extent_cache mount option is on Signed-off-by: xiongping1 Signed-off-by: qixiaoyu1 --- Documentation/filesystems/f2fs.rst | 4 ++++ fs/f2fs/block_age.c | 3 +++ fs/f2fs/f2fs.h | 1 + fs/f2fs/super.c | 27 +++++++++++++++++++++++++++ 4 files changed, 35 insertions(+) diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst index 17df9a02ccff..f4e8943f649d 100644 --- a/Documentation/filesystems/f2fs.rst +++ b/Documentation/filesystems/f2fs.rst @@ -340,6 +340,10 @@ memory=%s Control memory mode. This supports "normal" and "low" modes. Because of the nature of low memory devices, in this mode, f2fs will try to save memory sometimes by sacrificing performance. "normal" mode is the default mode and same as before. +age_extent_cache Enable an age extent cache based on rb-tree, it can record + data block update frequency of the extent per inode, in + order to indicate better temperature info for data block + allocation. ======================== ============================================================ Debugfs Entries diff --git a/fs/f2fs/block_age.c b/fs/f2fs/block_age.c index c8e8fbe51d8e..bc009616adfb 100644 --- a/fs/f2fs/block_age.c +++ b/fs/f2fs/block_age.c @@ -37,6 +37,9 @@ static inline bool f2fs_may_age_extent_tree(struct inode *inode) if (list_empty(&sbi->s_list)) return false; + if (!test_opt(sbi, AGE_EXTENT_CACHE)) + return false; + /* don't cache block age info for cold file */ if (is_inode_flag_set(inode, FI_COMPRESSED_FILE) || file_is_cold(inode)) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 5cc516228407..428cc560b721 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -106,6 +106,7 @@ extern const char *f2fs_fault_name[FAULT_MAX]; #define F2FS_MOUNT_MERGE_CHECKPOINT 0x10000000 #define F2FS_MOUNT_GC_MERGE 0x20000000 #define F2FS_MOUNT_COMPRESS_CACHE 0x40000000 +#define F2FS_MOUNT_AGE_EXTENT_CACHE 0x80000000 #define F2FS_OPTION(sbi) ((sbi)->mount_opt) #define clear_opt(sbi, option) (F2FS_OPTION(sbi).opt &= ~F2FS_MOUNT_##option) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 91d3c9d0425d..dcb5905c7264 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -161,6 +161,9 @@ enum { Opt_nogc_merge, Opt_discard_unit, Opt_memory_mode, +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + Opt_age_extent_cache, +#endif Opt_err, }; @@ -238,6 +241,9 @@ static match_table_t f2fs_tokens = { {Opt_nogc_merge, "nogc_merge"}, {Opt_discard_unit, "discard_unit=%s"}, {Opt_memory_mode, "memory=%s"}, +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + {Opt_age_extent_cache, "age_extent_cache"}, +#endif {Opt_err, NULL}, }; @@ -1253,6 +1259,11 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) } kfree(name); break; +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + case Opt_age_extent_cache: + set_opt(sbi, AGE_EXTENT_CACHE); + break; +#endif default: f2fs_err(sbi, "Unrecognized mount option \"%s\" or missing value", p); @@ -2035,6 +2046,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) else if (F2FS_OPTION(sbi).memory_mode == MEMORY_MODE_LOW) seq_printf(seq, ",memory=%s", "low"); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + if (test_opt(sbi, AGE_EXTENT_CACHE)) + seq_puts(seq, ",age_extent_cache"); +#endif return 0; } @@ -2206,6 +2221,9 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) bool need_restart_discard = false, need_stop_discard = false; bool no_extent_cache = !test_opt(sbi, EXTENT_CACHE); bool enable_checkpoint = !test_opt(sbi, DISABLE_CHECKPOINT); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + bool no_age_extent_cache = !test_opt(sbi, AGE_EXTENT_CACHE); +#endif bool no_io_align = !F2FS_IO_ALIGNED(sbi); bool no_atgc = !test_opt(sbi, ATGC); bool no_discard = !test_opt(sbi, DISCARD); @@ -2300,6 +2318,15 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data) goto restore_opts; } +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + /* disallow enable/disable age extent_cache dynamically */ + if (no_age_extent_cache == !!test_opt(sbi, AGE_EXTENT_CACHE)) { + err = -EINVAL; + f2fs_warn(sbi, "switch age_extent_cache option is not allowed"); + goto restore_opts; + } +#endif + if (no_io_align == !!F2FS_IO_ALIGNED(sbi)) { err = -EINVAL; f2fs_warn(sbi, "switch io_bits option is not allowed"); From patchwork Mon Nov 28 08:58:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: qixiaoyu1 X-Patchwork-Id: 26592 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp5529113wrr; Mon, 28 Nov 2022 01:11:52 -0800 (PST) X-Google-Smtp-Source: AA0mqf4gnsKnZtRZ+x+91PF4wNcwsQS+skq87lTA7/Hi4cVChGdck475nQEdbJ+JMv8uEHq7uCYY X-Received: by 2002:a63:4424:0:b0:477:96e2:9065 with SMTP id r36-20020a634424000000b0047796e29065mr27184565pga.533.1669626712636; Mon, 28 Nov 2022 01:11:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669626712; cv=none; d=google.com; s=arc-20160816; b=mtSONOKBimkhCGpMqXA5sx4xAlBrK4VYSxg0LDL7qzr3eGe5k9SW61y0wsOvAYWSUg l3t+g1W2YGNOO8d3AaGS/IFp+mUJNg9WJg01bjYGlKikY0++6YDgNDdZuAOIchZAUQSD W4Gh+FceFRfRh8DpOyp951zxPrZNWR+IVgjJkGBI+QCQYCXC7taR8glH0g4KbRVCBuwR Jwv+1ndst3P+P2kfnvOrdN0Z3iMbPTlrV5oso1eKBS7/iSTIFn2EUrQxvOB2yK49bdB3 XcKLsOR9Tklyn+05L3XmmHD4mhGVGiQ/e8lmOZWb2b4R/y0QPfn5jewZ5Cc9hjgHO4qE Sq7g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ycZaznc+xC+6/FUK+5zwqZvTJkK+CKo/Qas+UmyGYJA=; b=HenEuGmVJQ/+h5ovw359gm2uEhQQ+n/sEyZzh1AERvrzHN2hjTuccFs7ldhJXqwOOP Eveym50RK4xD/k44pWY4MIY1iggBWQAlNq/EzcF2IG+/3+Wi7XpQYkU5aIjb1dp13Gwc cOOc4XQiXMIU0MIvtRnBDTNq09pJROSmtwqTfc68eEhvpm7OLU+IaOYyhaK9UM4xjw90 TjjTVvBR2gZz6vycHWOFwCKf8Rf3YkCeBJ2VBvDjeEcFeWgb8vE9YaM5fyBd+TeYsrHe JZAY1AA8X3q2pIsKHOxQCDkMVJwVVoBxlZ+WjGEnaxCXwdHgqDzceZ7qL6MoA4sCHepr cp7Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=KXr9mkIA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id go15-20020a17090b03cf00b0021932afecefsi2851301pjb.187.2022.11.28.01.11.39; Mon, 28 Nov 2022 01:11:52 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=KXr9mkIA; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230251AbiK1JG4 (ORCPT + 99 others); Mon, 28 Nov 2022 04:06:56 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37086 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230289AbiK1JGg (ORCPT ); Mon, 28 Nov 2022 04:06:36 -0500 Received: from mail-pg1-x532.google.com (mail-pg1-x532.google.com [IPv6:2607:f8b0:4864:20::532]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B8E8F1839D for ; Mon, 28 Nov 2022 01:06:31 -0800 (PST) Received: by mail-pg1-x532.google.com with SMTP id 82so1897937pgc.0 for ; Mon, 28 Nov 2022 01:06:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ycZaznc+xC+6/FUK+5zwqZvTJkK+CKo/Qas+UmyGYJA=; b=KXr9mkIABUKR23sDpx3J4fNYP0/DhMiVooAUH26XjKNyzrAOgpeNrWG0wdIl/X4SFb HkU1RDGt9qEPz8nVJfhbpbjAqjnsB0zvKkE7VgVGTjBaxBEd/o31Yd5es62ZAXQlX/Mx w3bgAW3VB+uZBxpy2qM/gdaokCHBC4IFVeHCwcwT/OUYq8kz/akUmUzFjxkmuzxBwBhO 4cAJCQ5ASANz4N0mzLeELq6PbwvskDJNjSBtCyWTOkEqCw5mdZTf17H67HFFr/CEqung g47oNHwN/orzx/86GzTOz0/wwxlMSkGuhKy/IeO+lhObh08Xy98UzMJHIm/9/xPpBz/T 4LYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ycZaznc+xC+6/FUK+5zwqZvTJkK+CKo/Qas+UmyGYJA=; b=piTn30n7fgALdwmWjg0CRFItWcaV/G3/l0nZvTHl4wu4Q+3Wv+JUCUlzmxQZ01AI2E Q6gUpLQstOLcY+CN+G5MOlS555y3dAWCMVdEI4oMHbOJBzTFTvsOUW1NDSs4eRygcCLW KiMGTKugISG+zrJ3Fylu+wP5jSIZ1nCEkRFI2Akj6/x0HCnkBghPQ1Jd1PJPZ79OlmF1 yKYvrCUteLDn4Mc4sLmEggBqsErGwrnUgiepnOa3wwOyDTE8/4q0ImSwZVh56P6PIAbc 4dMzjxeC3l2sln5iScpY/HVwh+aL150xitfDu4cfNEcC63OBLe16QF7pmgGM2ifOv/io O19Q== X-Gm-Message-State: ANoB5pm176pnJYcrs0nnuqsCGmXS22MZiOtROoqaeWkA9EGJGq430j/S Dj3iAuixZP/Ju3KXnYytKISsNWj5hMsmUA== X-Received: by 2002:a63:1055:0:b0:46e:f011:9548 with SMTP id 21-20020a631055000000b0046ef0119548mr26085763pgq.553.1669626391178; Mon, 28 Nov 2022 01:06:31 -0800 (PST) Received: from mi-HP-ProDesk-680-G4-MT.mioffice.cn ([43.224.245.252]) by smtp.gmail.com with ESMTPSA id s17-20020a170902ea1100b001811a197797sm8269268plg.194.2022.11.28.01.06.28 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Nov 2022 01:06:30 -0800 (PST) From: qixiaoyu1 X-Google-Original-From: qixiaoyu1 To: Jaegeuk Kim , Chao Yu Cc: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, qixiaoyu1 , xiongping1 Subject: [PATCH 4/5] f2fs: update block age info during out of place update Date: Mon, 28 Nov 2022 16:58:58 +0800 Message-Id: <20221128085859.5295-5-qixiaoyu1@xiaomi.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20221128085859.5295-1-qixiaoyu1@xiaomi.com> References: <20221128085859.5295-1-qixiaoyu1@xiaomi.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750730499983396864?= X-GMAIL-MSGID: =?utf-8?q?1750730499983396864?= Signed-off-by: qixiaoyu1 Signed-off-by: xiongping1 --- fs/f2fs/block_age.c | 89 ++++++++++++++++++++++++++++++++++++++++++++- fs/f2fs/f2fs.h | 1 + fs/f2fs/segment.c | 4 ++ 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/block_age.c b/fs/f2fs/block_age.c index bc009616adfb..488461b3f4bf 100644 --- a/fs/f2fs/block_age.c +++ b/fs/f2fs/block_age.c @@ -9,9 +9,14 @@ #include #include "f2fs.h" +#include "node.h" #include "segment.h" #include + +#define LAST_AGE_WEIGHT 30 +#define SAME_AGE_REGION 1024 + static struct kmem_cache *age_extent_tree_slab; static struct kmem_cache *age_extent_node_slab; @@ -264,8 +269,8 @@ static inline bool __is_age_extent_mergeable(struct age_extent_info *back, struct age_extent_info *front) { return (back->fofs + back->len == front->fofs && - back->age == front->age && - back->last_blocks == front->last_blocks); + abs(back->age - front->age) <= SAME_AGE_REGION && + abs(back->last_blocks - front->last_blocks) <= SAME_AGE_REGION); } static inline bool __is_back_age_ext_mergeable(struct age_extent_info *cur, @@ -497,6 +502,86 @@ void f2fs_truncate_age_extent_cache(struct inode *inode, pgoff_t fofs, unsigned f2fs_update_age_extent_cache(inode, fofs, len, 0, 0); } +unsigned long long f2fs_get_cur_dblock_allocated(struct f2fs_sb_info *sbi) +{ + return atomic64_read(&sbi->total_data_alloc); +} + +static unsigned long long calculate_block_age(unsigned long long new, + unsigned long long old) +{ + if (new >= old) + return new - (new - old) * LAST_AGE_WEIGHT / 100; + else + return new + (old - new) * LAST_AGE_WEIGHT / 100; +} + +void f2fs_update_data_block_age(struct dnode_of_data *dn) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); + unsigned long long cur_total_blk_alloced = f2fs_get_cur_dblock_allocated(sbi); + pgoff_t fofs; + unsigned long long cur_age, new_age; + struct age_extent_info ei; + bool find; + loff_t f_size = i_size_read(dn->inode); + + if (!f2fs_may_age_extent_tree(dn->inode)) + return; + + fofs = f2fs_start_bidx_of_node(ofs_of_node(dn->node_page), dn->inode) + + dn->ofs_in_node; + + + /* When I/O is not aligned to a PAGE_SIZE, update will happen to the last + * file block even in seq write. So don't record age for newly last file + * block here. + */ + if ((f_size >> PAGE_SHIFT) == fofs && f_size & (PAGE_SIZE - 1) && + dn->data_blkaddr == NEW_ADDR) + return; + + find = f2fs_lookup_age_extent_cache(dn->inode, fofs, &ei); + if (find) { + if (cur_total_blk_alloced >= ei.last_blocks) + cur_age = cur_total_blk_alloced - ei.last_blocks; + else + /* total_data_alloc overflow */ + cur_age = ULLONG_MAX - ei.last_blocks + cur_total_blk_alloced; + + if (ei.age) + new_age = calculate_block_age(cur_age, ei.age); + else + new_age = cur_age; + + WARN(new_age > cur_total_blk_alloced, + "inode block(%lu: %lu) age changed from: %llu to %llu", + dn->inode->i_ino, fofs, ei.age, new_age); + } else { + f2fs_bug_on(sbi, dn->data_blkaddr == NULL_ADDR); + + if (dn->data_blkaddr == NEW_ADDR) + /* the data block was allocated for the first time */ + new_age = 0; + else { + if (__is_valid_data_blkaddr(dn->data_blkaddr) && + !f2fs_is_valid_blkaddr(sbi, dn->data_blkaddr, + DATA_GENERIC_ENHANCE)) { + f2fs_bug_on(sbi, 1); + return; + } + + /* + * init block age with zero, this can happen when the block age extent + * was reclaimed due to memory constraint or system reboot + */ + new_age = 0; + } + } + + f2fs_update_age_extent_cache(dn->inode, fofs, 1, new_age, cur_total_blk_alloced); +} + void f2fs_destroy_age_extent_tree(struct inode *inode) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 428cc560b721..23516498b6d0 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -4238,6 +4238,7 @@ bool f2fs_lookup_age_extent_cache(struct inode *inode, pgoff_t pgofs, void f2fs_update_age_extent_cache(struct inode *inode, pgoff_t fofs, unsigned int len, u64 age, unsigned long long cur_blk_alloced); +void f2fs_update_data_block_age(struct dnode_of_data *dn); void f2fs_truncate_age_extent_cache(struct inode *inode, pgoff_t fofs, unsigned int len); int __init f2fs_create_age_extent_cache(void); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index b105d8418f77..d4c338f332fa 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -3417,6 +3417,10 @@ void f2fs_outplace_write_data(struct dnode_of_data *dn, struct f2fs_summary sum; f2fs_bug_on(sbi, dn->data_blkaddr == NULL_ADDR); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + if (fio->io_type == FS_DATA_IO || fio->io_type == FS_CP_DATA_IO) + f2fs_update_data_block_age(dn); +#endif set_summary(&sum, dn->nid, dn->ofs_in_node, fio->version); do_write_page(&sum, fio); f2fs_update_data_blkaddr(dn, fio->new_blkaddr); From patchwork Mon Nov 28 08:58:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: qixiaoyu1 X-Patchwork-Id: 26591 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp5528794wrr; Mon, 28 Nov 2022 01:11:04 -0800 (PST) X-Google-Smtp-Source: AA0mqf4jGZKjhGoUNealqV3qEa+CopOgGq5U8/ZQ7dT1I0C7JJVRVHauqj0btffa5K8JALBaGtEY X-Received: by 2002:a17:906:e2cb:b0:7ad:c35a:ad76 with SMTP id gr11-20020a170906e2cb00b007adc35aad76mr43119871ejb.705.1669626664016; Mon, 28 Nov 2022 01:11:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669626664; cv=none; d=google.com; s=arc-20160816; b=SKrGmmowDLGhLhN+qGXoGay1HUO5JtbHnoHVSFlaebAMnEzylWxW7JjXruyKmja6TG 0eKFDx4QKJNZF/mL5gzTa8Qv6nR0x9YSPLVjuEml1ZrQvKilxxwsRu5EVAHymN7B70gs 1cU3IbmpWi20ZDDhCPGnEY7cdOhNSlsqoL/dJCVoHF07d+bU8NsZwPNDSpMEgo5sFCdX HhY0aPG2WOLOkU1nbc69sz82OeSY7kgPbIGtKLj4aQDhAXwkQeYHiUA/iqeyM6yuMPrW +paArkxxUsxGU7VRkTAImNyppPTqf6Pke6nnw5bOPP8ZE8PImSxtx/hg09TExtwF9UbG cqjA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=BLKXiYJYrg2dlB187g+CWrgI5UTddt8FYxHfk/bEX8w=; b=aAsJNOxSLmxKm8hfIbdDCAJu0kPxhlZKSsLtZ8Rc/kfP2sdOffe4Y8EmkezsuaibO3 Bcnmiz4l4LQgKztMzVa12FQKM9Y5Sna6zq1/tvIfAK8BF0bxD0ST6JxmhXplQEuldPO/ ip2axQzJ0DFYs1NAJZkizqev5PtUsSs3xlydmO90iet1/bZN2+fQ1fgSTKLhybk9s9QG mKiG3VEI6KsPz1tgCD2Y8L45AcJBPRpPiDyW/xyfvYQYlkGuhtVR4z0k2ltMLSomzaEo SXYtr8xqkadcy92VWmN4zfgiFdjmZw1eGsSgQbWz1dGiplXzTUs48VDGuE31U9nUJ6LV uZsQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=ToLYrPdB; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id l15-20020a170906794f00b007b6ff799abasi9848232ejo.465.2022.11.28.01.10.40; Mon, 28 Nov 2022 01:11:03 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=ToLYrPdB; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230305AbiK1JG6 (ORCPT + 99 others); Mon, 28 Nov 2022 04:06:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37298 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230298AbiK1JGk (ORCPT ); Mon, 28 Nov 2022 04:06:40 -0500 Received: from mail-pg1-x52c.google.com (mail-pg1-x52c.google.com [IPv6:2607:f8b0:4864:20::52c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F248415724 for ; Mon, 28 Nov 2022 01:06:34 -0800 (PST) Received: by mail-pg1-x52c.google.com with SMTP id q1so9351369pgl.11 for ; Mon, 28 Nov 2022 01:06:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BLKXiYJYrg2dlB187g+CWrgI5UTddt8FYxHfk/bEX8w=; b=ToLYrPdB/98crZI29wTwpCgtIfl/tinLjbghq0UsSmXB2VSNQysz1AWDV7ZjS+w92q j3bHP+azMDr6JM7C5wovgdSnbiIozqyUkx3DXGF35KYw5g1fkY77vcpHzlF/A1G84z16 82FKGw5VhYdmolDeXmI9yADrFBQCtML6NTVcIOO4n+1Vtz3VR3IlwVsuNogkg9TQ6+p0 1z3N0hQJ9yswmrLj8J+ZuEzK6gYew9JzvDN0DQmhcWeqxXkLhcpwMCF0zJnxbhhjgM9X 7WuN+5ry+F+ieUwp10pUrAAgtjh4FeCzFfujT4koheU5sT9t6RgapnDHQ2i+bcRiD1eD z2Vw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BLKXiYJYrg2dlB187g+CWrgI5UTddt8FYxHfk/bEX8w=; b=Y09KbQWddTP41yPsoaOi2QIEiH9eSNAWEjdLuNNJY2Om7CDbFGPrczmy4WZdQHhmEQ WrPuwtLRiDgBvsyqvTjUvjb2KvISMaq57uJlwIZCERkaeoWZK1fChZUDOPMiW21u4V3D AeydXurVhCLy6OePLB85gEW+tzIqPYTY01PDz4gS5J6frFibJnSTI4cWZlnTlpPLBBsh /tqFDqUHHtz5vCRZE54zn7oQRbLC7EeT9fKLF1m9r53vRO4sZb+NOeneS0hRvKuHlGVO vuUZ/lejWkClo9YqxrWqMaepIVNBqLrHX9UIzixWzWldnH5n2HtTCpQzYgaZUukvenKx Ym6A== X-Gm-Message-State: ANoB5pnRRvid0IaQWwSdJCT+11xONGjG8qSJJ5q+ZCsSYL90Dt0SPD3A jpQHDLKmUvfQ1J7zKwTQJAw= X-Received: by 2002:a05:6a00:4009:b0:563:2ada:30a3 with SMTP id by9-20020a056a00400900b005632ada30a3mr32385650pfb.27.1669626394381; Mon, 28 Nov 2022 01:06:34 -0800 (PST) Received: from mi-HP-ProDesk-680-G4-MT.mioffice.cn ([43.224.245.252]) by smtp.gmail.com with ESMTPSA id s17-20020a170902ea1100b001811a197797sm8269268plg.194.2022.11.28.01.06.32 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Nov 2022 01:06:33 -0800 (PST) From: qixiaoyu1 X-Google-Original-From: qixiaoyu1 To: Jaegeuk Kim , Chao Yu Cc: linux-kernel@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, qixiaoyu1 , xiongping1 Subject: [PATCH 5/5] f2fs: implement data block seperation with block update frequency Date: Mon, 28 Nov 2022 16:58:59 +0800 Message-Id: <20221128085859.5295-6-qixiaoyu1@xiaomi.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20221128085859.5295-1-qixiaoyu1@xiaomi.com> References: <20221128085859.5295-1-qixiaoyu1@xiaomi.com> MIME-Version: 1.0 X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750730449101468820?= X-GMAIL-MSGID: =?utf-8?q?1750730449101468820?= Signed-off-by: qixiaoyu1 Signed-off-by: xiongping1 --- Documentation/ABI/testing/sysfs-fs-f2fs | 14 ++++++++++++ fs/f2fs/block_age.c | 29 +++++++++++++++++++++++++ fs/f2fs/f2fs.h | 4 ++++ fs/f2fs/segment.c | 9 ++++++++ fs/f2fs/sysfs.c | 28 ++++++++++++++++++++++++ include/trace/events/f2fs.h | 2 +- 6 files changed, 85 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index 483639fb727b..34952666b2fe 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -634,3 +634,17 @@ Date: July 2022 Contact: "Daeho Jeong" Description: Show the accumulated total revoked atomic write block count after boot. If you write "0" here, you can initialize to "0". + +What: /sys/fs/f2fs//hot_data_age_threshold +Date: November 2022 +Contact: "Ping Xiong" +Description: When DATA SEPARATION is on, it controls the age threshold to indicate + the data blocks as hot. By default it was initialized as 262144 blocks + (equals to 1GB). + +What: /sys/fs/f2fs//warm_data_age_threshold +Date: November 2022 +Contact: "Ping Xiong" +Description: When DATA SEPARATION is on, it controls the age threshold to indicate + the data blocks as warm. By default it was initialized as 2621440 blocks + (equals to 10GB). diff --git a/fs/f2fs/block_age.c b/fs/f2fs/block_age.c index 488461b3f4bf..d0b578544df7 100644 --- a/fs/f2fs/block_age.c +++ b/fs/f2fs/block_age.c @@ -17,6 +17,13 @@ #define LAST_AGE_WEIGHT 30 #define SAME_AGE_REGION 1024 +/* + * Define data block with age less than 1GB as hot data + * define data block with age less than 10GB but more than 1GB as warm data + */ +#define DEF_HOT_DATA_AGE_THRESHOLD 262144 +#define DEF_WARM_DATA_AGE_THRESHOLD 2621440 + static struct kmem_cache *age_extent_tree_slab; static struct kmem_cache *age_extent_node_slab; @@ -29,6 +36,9 @@ static inline void f2fs_inc_data_block_alloc(struct f2fs_sb_info *sbi) static void f2fs_init_block_age_info(struct f2fs_sb_info *sbi) { atomic64_set(&sbi->total_data_alloc, 0); + + sbi->hot_data_age_threshold = DEF_HOT_DATA_AGE_THRESHOLD; + sbi->warm_data_age_threshold = DEF_WARM_DATA_AGE_THRESHOLD; } static inline bool f2fs_may_age_extent_tree(struct inode *inode) @@ -697,6 +707,25 @@ unsigned long f2fs_count_age_extent_cache(struct f2fs_sb_info *sbi) atomic_read(&sbi->total_age_ext_node); } +int f2fs_get_data_segment_type(struct inode *inode, pgoff_t pgofs) +{ + struct age_extent_info ei; + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + + if (f2fs_lookup_age_extent_cache(inode, pgofs, &ei)) { + if (ei.age != 0) { + if (ei.age <= sbi->hot_data_age_threshold) + return CURSEG_HOT_DATA; + else if (ei.age <= sbi->warm_data_age_threshold) + return CURSEG_WARM_DATA; + else + return CURSEG_COLD_DATA; + } + } + + return NO_CHECK_TYPE; +} + void f2fs_destroy_age_extent_cache(void) { kmem_cache_destroy(age_extent_node_slab); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 23516498b6d0..50f6f21b23bf 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1854,6 +1854,9 @@ struct f2fs_sb_info { #ifdef CONFIG_F2FS_FS_DATA_SEPARATION atomic64_t total_data_alloc; + /* The threshold used for hot and warm data seperation*/ + unsigned int hot_data_age_threshold; + unsigned int warm_data_age_threshold; #endif /* Reference to checksum algorithm driver via cryptoapi */ @@ -4241,6 +4244,7 @@ void f2fs_update_age_extent_cache(struct inode *inode, pgoff_t fofs, void f2fs_update_data_block_age(struct dnode_of_data *dn); void f2fs_truncate_age_extent_cache(struct inode *inode, pgoff_t fofs, unsigned int len); +int f2fs_get_data_segment_type(struct inode *inode, pgoff_t pgofs); int __init f2fs_create_age_extent_cache(void); void f2fs_destroy_age_extent_cache(void); #endif diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index d4c338f332fa..2fa5b22119ac 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -3163,6 +3163,9 @@ static int __get_segment_type_6(struct f2fs_io_info *fio) if (fio->type == DATA) { struct inode *inode = fio->page->mapping->host; +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + int type; +#endif if (is_inode_flag_set(inode, FI_ALIGNED_WRITE)) return CURSEG_COLD_DATA_PINNED; @@ -3176,6 +3179,12 @@ static int __get_segment_type_6(struct f2fs_io_info *fio) } if (file_is_cold(inode) || f2fs_need_compress_data(inode)) return CURSEG_COLD_DATA; + +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + type = f2fs_get_data_segment_type(inode, fio->page->index); + if (type != NO_CHECK_TYPE) + return type; +#endif if (file_is_hot(inode) || is_inode_flag_set(inode, FI_HOT_DATA) || f2fs_is_cow_file(inode)) diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index df27afd71ef4..68ba8c1c2cb3 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -648,6 +648,25 @@ static ssize_t __sbi_store(struct f2fs_attr *a, sbi->revoked_atomic_block = 0; return count; } +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + if (!strcmp(a->attr.name, "hot_data_age_threshold")) { + if (t == 0 || t >= sbi->warm_data_age_threshold) + return -EINVAL; + if (t == *ui) + return count; + *ui = (unsigned int)t; + return count; + } + + if (!strcmp(a->attr.name, "warm_data_age_threshold")) { + if (t == 0 || t <= sbi->hot_data_age_threshold) + return -EINVAL; + if (t == *ui) + return count; + *ui = (unsigned int)t; + return count; + } +#endif *ui = (unsigned int)t; @@ -902,6 +921,11 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, peak_atomic_write, peak_atomic_write); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, committed_atomic_block, committed_atomic_block); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, revoked_atomic_block, revoked_atomic_block); +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, hot_data_age_threshold, hot_data_age_threshold); +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, warm_data_age_threshold, warm_data_age_threshold); +#endif + #define ATTR_LIST(name) (&f2fs_attr_##name.attr) static struct attribute *f2fs_attrs[] = { ATTR_LIST(gc_urgent_sleep_time), @@ -995,6 +1019,10 @@ static struct attribute *f2fs_attrs[] = { ATTR_LIST(peak_atomic_write), ATTR_LIST(committed_atomic_block), ATTR_LIST(revoked_atomic_block), +#ifdef CONFIG_F2FS_FS_DATA_SEPARATION + ATTR_LIST(hot_data_age_threshold), + ATTR_LIST(warm_data_age_threshold), +#endif NULL, }; ATTRIBUTE_GROUPS(f2fs); diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index b19c057ff801..0adb26397e68 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -1692,7 +1692,7 @@ DECLARE_EVENT_CLASS(f2fs_add_age_extent_node, __entry->blocks = ei->last_blocks; ), - TP_printk("dev = (%d,%d), ino = %lu, node_cnt = %lu, " + TP_printk("dev = (%d,%d), ino = %lu, node_cnt = %u, " "age_ext_info(fofs: %u, len: %u, age: %llu, blocks: %llu)", show_dev_ino(__entry), __entry->cnt,