From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B69DC19E819 for ; Fri, 17 Apr 2026 02:17:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776392225; cv=none; b=kyHlS+EMKBD7lze45NFmA1ZTPf4hyM3oqQ0n01NtzeIc938DmpiWJgVhw3y6ju5npd6isoojIquQeDyyjIohA/WVWA2I/Jkzt3hEWsUMl108SMBUw5rsHuLJ3ouDcIzYNOP+2rUt3WLgibghf6dDGxjAyHJM/KkzxXmSU7BV1wk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776392225; c=relaxed/simple; bh=KIpUTke7ygpWmUQZYIHp7ogFqhg8A3dVs9R5X8zNhoA=; h=Message-ID:Date:MIME-Version:Cc:Subject:To:References:From: In-Reply-To:Content-Type; b=tu30mhe3B8D/qSaWNYhjrkh2J64RH+BXXP62Ha/6u5MwPvNoMEqh6/VcRVgrtQtthGyF2cB/v6MrL3pvX+Ef1Iy8uy9dRcNWtp52IP65OQVFA/ff3mTuSXxhW8sLZBZk7aCf4Gxk8sa8aYehtFLdMdvIUNQSX6J0H1Is8QvMrGw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KFZkdUQT; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KFZkdUQT" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DB3ECC2BCAF; Fri, 17 Apr 2026 02:17:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1776392225; bh=KIpUTke7ygpWmUQZYIHp7ogFqhg8A3dVs9R5X8zNhoA=; h=Date:Cc:Subject:To:References:From:In-Reply-To:From; b=KFZkdUQTJo5BcwtsOdHtcq+LU1bNstTgfKuoBYwBZQ3WqOY8GPFJ2YftKHuMG02b7 ONbHBPT7c1zPtYM+zBV/tUDDp/P8VmLNBOXtLu3hTBl8jaC+N9cg5NfbIneShm+d4o vxXDvrVp05NC5fcAGxgWe2xImt6O2cjilJS1oPr6+cBtpp1GvX0zhzNaPW5hJrSOnR 6yNFpZC4+pXNU9MQVW0KyHbB9wSnp8bpe2iVpdStflCnAEcdoP8JNdZTycTRtS+b3/ LkKlw8jKOjVnyEUYQ8kTfCah8Ig3R+wzlAzEu2lzyEmi39K2zuuPwLHhLTQ0WCKzwx CFFXkw/cVYilA== Message-ID: <930d444c-d71e-4712-9d24-2c7bfe57b18d@kernel.org> Date: Fri, 17 Apr 2026 10:17:02 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Cc: chao@kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org Subject: Re: [RFC PATCH v1] f2fs: map data writes to FDP streams To: Wenjie Qi , jaegeuk@kernel.org References: <20260415081451.2333535-1-qiwenjie@xiaomi.com> Content-Language: en-US From: Chao Yu In-Reply-To: <20260415081451.2333535-1-qiwenjie@xiaomi.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit On 4/15/2026 4:14 PM, Wenjie Qi wrote: > From: Wenjie Qi > > From: Wenjie Qi > > F2FS already classifies DATA writes using its existing hot, warm and cold > temperature policy, but it only passes that intent down as a write hint. > That hint alone is not sufficient for NVMe FDP placement, because the > current NVMe command path consumes `bio->bi_write_stream` rather than > `bio->bi_write_hint` when selecting a placement ID. > > When the target block device exposes write streams, map the existing F2FS > DATA temperature classes onto stream IDs and set `bio->bi_write_stream` > for both buffered and direct writes. If the device exposes no write > streams, keep the current behavior by leaving the stream unset. > > The stream mapping is evaluated against the target block device of each > bio, so the existing per-device fallback behavior stays unchanged for > multi-device filesystems. Existing blkzoned restrictions also remain in > place. > > The mapping is intentionally small and deterministic: > > - 1 stream: hot, warm and cold all use stream 1 > - 2 streams: hot/warm use 1, cold uses 2 > - 3+ streams: hot uses 1, warm uses 2, cold uses 3 Hi Wenjie, Can we add doc to describe the default config? > > Signed-off-by: Wenjie Qi > > --- > RFC notes: > - Scope is intentionally limited to DATA writes only. > - Validation used stock QEMU 8.2.2 NVMe FDP emulation with a 16G > namespace. > - FDP enabled: buffered and direct writes each produced 3 dominant > NVMe placement tuples. > - FDP disabled: buffered and direct writes each collapsed to 1 > dominant tuple. > > fs/f2fs/data.c | 2 ++ > fs/f2fs/f2fs.h | 2 ++ > fs/f2fs/file.c | 2 ++ > fs/f2fs/segment.c | 24 ++++++++++++++++++++++++ > 4 files changed, 30 insertions(+) > > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c > index 338df7a2a..df9f4a230 100644 > --- a/fs/f2fs/data.c > +++ b/fs/f2fs/data.c > @@ -508,6 +508,8 @@ static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages) > bio->bi_private = sbi; > bio->bi_write_hint = f2fs_io_type_to_rw_hint(sbi, > fio->type, fio->temp); > + bio->bi_write_stream = f2fs_io_type_to_write_stream(bdev, fio->type, > + fio->temp); > } > iostat_alloc_and_bind_ctx(sbi, bio, NULL); > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > index bb34e864d..2f0777478 100644 > --- a/fs/f2fs/f2fs.h > +++ b/fs/f2fs/f2fs.h > @@ -4056,6 +4056,8 @@ void f2fs_destroy_segment_manager_caches(void); > int f2fs_rw_hint_to_seg_type(struct f2fs_sb_info *sbi, enum rw_hint hint); > enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi, > enum page_type type, enum temp_type temp); > +u8 f2fs_io_type_to_write_stream(struct block_device *bdev, > + enum page_type type, enum temp_type temp); > unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi); > unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi, > unsigned int segno); > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c > index c8a2f17a8..a3186cfc9 100644 > --- a/fs/f2fs/file.c > +++ b/fs/f2fs/file.c > @@ -5064,6 +5064,8 @@ static void f2fs_dio_write_submit_io(const struct iomap_iter *iter, > enum temp_type temp = f2fs_get_segment_temp(sbi, type); > > bio->bi_write_hint = f2fs_io_type_to_rw_hint(sbi, DATA, temp); > + bio->bi_write_stream = > + f2fs_io_type_to_write_stream(bio->bi_bdev, DATA, temp); > blk_crypto_submit_bio(bio); > } > > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c > index 6a97fe767..ef8a3ac55 100644 > --- a/fs/f2fs/segment.c > +++ b/fs/f2fs/segment.c > @@ -3626,6 +3626,30 @@ enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi, > } > } > > +u8 f2fs_io_type_to_write_stream(struct block_device *bdev, > + enum page_type type, enum temp_type temp) > +{ > + unsigned short nr = bdev_max_write_streams(bdev); > + > + if (type != DATA || !nr) > + return 0; > + if (nr == 1) > + return 1; > + if (nr == 2) > + return temp == COLD ? 2 : 1; > + > + switch (temp) { > + case HOT: > + return 1; > + case WARM: > + return 2; > + case COLD: > + return 3; > + default: > + return 0; How about using existing macros if there is instead magic numbers? Thanks, > + } > +} > + > static int __get_segment_type_2(struct f2fs_io_info *fio) > { > if (fio->type == DATA)